Skip to content

Commit ac332c6

Browse files
refactor!: significant refactor of message and modal components (#310)
* feat: created general asset for img uses * feat: export Asset * feat: rework this func * feat: renamed to MediaItem (like discord API) * feat: add MessageComponent and ModalComponent interfaces * refactor!: replace MessageRowBuilder with ActionRow * refactor!: replace MessageButton with Button * refactor: move ComponentType enum inside component.dart file * feat: add isEmpty getter to ServerVoiceChannel * refactor!: replace ModalTextInput with TextInput * refactor!: replace MessageSection with Section * refactor: update TextDisplay to implement MessageComponent and ModalComponent * refactor!: replace MessageSeparator with Separator component * refactor!: replace MessageContainer with Container in MessageBuilder * refactor!: replace ModalLabel with Label component * refactor!: move MessageBuilder and ModalBuilder to builder directory * refactor!: rename MessageGallery to MediaGallery * refactor!: rename MessageThumbnail to Thumbnail * refactor!: rename MessageFile to AttachedFile * refactor: update SelectMenu to implement MessageComponent and ModalComponent * refactor: update MessageBuilder and ModalBuilder to use specific component types * refactor: rename methods in MessageBuilder for consistency and clarity * refactor: rename methods in ModalBuilder for clarity and consistency * refactor: add factory constructor for MessageBuilder to simplify text initialization * style: reorganize methods in MessageBuilder for improved clarity and structure * fix: remove wrong button limit check in MessageBuilder * fix: enforce button limit in addButtons method of MessageBuilder * refactor: rename factory method in MediaItem for clarity * refactor!: improve factory constructor for MediaItem * feat: improve AttachedFile API * chore: enforce item count constraints in MediaGallery constructor * fix: enforce accessory constraints in Section constructor * feat!: simplify MessageBuilder API and add comprehensive method documentation - Change addGallery to accept List<MediaItem> directly - Update addSection to use named parameters like addContainer - Add detailed documentation for all public methods - Include practical examples for each method * refactor: reorder methods in ModalBuilder for improved readability * fix: correct type for component parameter in addLabel method * refactor: improve ModalBuilder API * docs: add documentation and examples in ModalBuilder * style: reorganize exports in api and events files * refactor: remove isEmpty getter from ServerVoiceChannel --------- Co-authored-by: pandaguerrier <[email protected]>
1 parent ef22e82 commit ac332c6

27 files changed

+1183
-284
lines changed

lib/api.dart

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,22 @@ export 'package:mineral/src/api/common/commands/command_helper.dart';
2727
export 'package:mineral/src/api/common/commands/command_option.dart';
2828
export 'package:mineral/src/api/common/commands/command_option_type.dart';
2929
export 'package:mineral/src/api/common/commands/command_type.dart';
30+
export 'package:mineral/src/api/common/components/action_row.dart';
31+
export 'package:mineral/src/api/common/components/attached_file.dart';
32+
// Commons
33+
export 'package:mineral/src/api/common/components/builder/message_builder.dart';
34+
export 'package:mineral/src/api/common/components/builder/modal_builder.dart';
35+
export 'package:mineral/src/api/common/components/button.dart';
3036
export 'package:mineral/src/api/common/components/component.dart';
31-
export 'package:mineral/src/api/common/components/component_type.dart';
37+
export 'package:mineral/src/api/common/components/media_gallery.dart';
3238
export 'package:mineral/src/api/common/components/media_item.dart';
33-
// Commons
34-
export 'package:mineral/src/api/common/components/message/message_builder.dart';
35-
export 'package:mineral/src/api/common/components/message/message_button.dart';
36-
export 'package:mineral/src/api/common/components/message/message_file.dart';
37-
export 'package:mineral/src/api/common/components/message/message_gallery.dart';
38-
export 'package:mineral/src/api/common/components/message/message_row_builder.dart';
39-
export 'package:mineral/src/api/common/components/message/message_section.dart';
40-
export 'package:mineral/src/api/common/components/message/message_separator.dart';
41-
export 'package:mineral/src/api/common/components/message/message_thumbnail.dart';
42-
export 'package:mineral/src/api/common/components/modal/modal_builder.dart';
43-
export 'package:mineral/src/api/common/components/modal/modal_text_input.dart';
44-
export 'package:mineral/src/api/common/components/shared/select_menu.dart';
39+
export 'package:mineral/src/api/common/components/message_component.dart';
40+
export 'package:mineral/src/api/common/components/message_thumbnail.dart';
41+
export 'package:mineral/src/api/common/components/modal_component.dart';
42+
export 'package:mineral/src/api/common/components/section.dart';
43+
export 'package:mineral/src/api/common/components/select_menu.dart';
44+
export 'package:mineral/src/api/common/components/separator.dart';
45+
export 'package:mineral/src/api/common/components/text_input.dart';
4546
export 'package:mineral/src/api/common/embed/message_embed.dart';
4647
export 'package:mineral/src/api/common/embed/message_embed_assets.dart';
4748
export 'package:mineral/src/api/common/embed/message_embed_author.dart';

lib/events.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ export 'package:mineral/src/domains/events/contracts/private/private_channel_cre
1111
export 'package:mineral/src/domains/events/contracts/private/private_channel_delete_event.dart';
1212
export 'package:mineral/src/domains/events/contracts/private/private_channel_pins_update_event.dart';
1313
export 'package:mineral/src/domains/events/contracts/private/private_channel_update_event.dart';
14-
export 'package:mineral/src/domains/events/contracts/private/private_modal_submit_event.dart';
1514
export 'package:mineral/src/domains/events/contracts/private/private_message_create_event.dart';
16-
export 'package:mineral/src/domains/events/contracts/private/private_text_select_event.dart';
17-
export 'package:mineral/src/domains/events/contracts/private/private_user_select_event.dart';
1815
export 'package:mineral/src/domains/events/contracts/private/private_message_reaction_add_event.dart';
1916
export 'package:mineral/src/domains/events/contracts/private/private_message_reaction_remove_event.dart';
17+
export 'package:mineral/src/domains/events/contracts/private/private_modal_submit_event.dart';
18+
export 'package:mineral/src/domains/events/contracts/private/private_text_select_event.dart';
19+
export 'package:mineral/src/domains/events/contracts/private/private_user_select_event.dart';
2020
export 'package:mineral/src/domains/events/contracts/server/server_ban_add_event.dart';
2121
export 'package:mineral/src/domains/events/contracts/server/server_ban_remove_event.dart';
2222
export 'package:mineral/src/domains/events/contracts/server/server_button_click_event.dart';
@@ -27,7 +27,6 @@ export 'package:mineral/src/domains/events/contracts/server/server_channel_selec
2727
export 'package:mineral/src/domains/events/contracts/server/server_channel_update_event.dart';
2828
export 'package:mineral/src/domains/events/contracts/server/server_create_event.dart';
2929
export 'package:mineral/src/domains/events/contracts/server/server_delete_event.dart';
30-
export 'package:mineral/src/domains/events/contracts/server/server_modal_submit_event.dart';
3130
export 'package:mineral/src/domains/events/contracts/server/server_emojis_update_event.dart';
3231
export 'package:mineral/src/domains/events/contracts/server/server_member_add_event.dart';
3332
export 'package:mineral/src/domains/events/contracts/server/server_member_remove_event.dart';
@@ -36,6 +35,7 @@ export 'package:mineral/src/domains/events/contracts/server/server_member_update
3635
export 'package:mineral/src/domains/events/contracts/server/server_message_create_event.dart';
3736
export 'package:mineral/src/domains/events/contracts/server/server_message_reaction_add_event.dart';
3837
export 'package:mineral/src/domains/events/contracts/server/server_message_reaction_remove_event.dart';
38+
export 'package:mineral/src/domains/events/contracts/server/server_modal_submit_event.dart';
3939
export 'package:mineral/src/domains/events/contracts/server/server_presence_update_event.dart';
4040
export 'package:mineral/src/domains/events/contracts/server/server_role_select_event.dart';
4141
export 'package:mineral/src/domains/events/contracts/server/server_roles_create_event.dart';

lib/src/api/common/components/message/message_row_builder.dart renamed to lib/src/api/common/components/action_row.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'package:mineral/api.dart';
22

3-
final class MessageRowBuilder implements Component {
3+
final class ActionRow implements MessageComponent {
44
final List<Component> components;
55

6-
MessageRowBuilder({this.components = const []});
6+
ActionRow({this.components = const []});
77

88
@override
99
Map<String, dynamic> toJson() {
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import 'dart:io';
2+
3+
import 'package:http/http.dart' as http;
4+
import 'package:mineral/api.dart';
5+
6+
final class AttachedFile implements MessageComponent {
7+
ComponentType get type => ComponentType.file;
8+
9+
MediaItem item;
10+
11+
AttachedFile._(this.item);
12+
13+
/// Creates an [AttachedFile] from a local file.
14+
///
15+
/// Example:
16+
/// ```dart
17+
/// final file = File('assets/image.png');
18+
/// final attachedFile = AttachedFile.fromFile(file, 'image.png', spoiler: false);
19+
/// ```
20+
factory AttachedFile.fromFile(
21+
File file,
22+
String name, {
23+
bool? spoiler,
24+
String? proxyUrl,
25+
int? height,
26+
int? width,
27+
String? contentType,
28+
String? description,
29+
}) {
30+
final mediaItem = MediaItem.fromFile(
31+
file,
32+
name,
33+
spoiler: spoiler,
34+
proxyUrl: proxyUrl,
35+
height: height,
36+
width: width,
37+
contentType: contentType,
38+
description: description,
39+
);
40+
return AttachedFile._(mediaItem);
41+
}
42+
43+
/// Creates an [AttachedFile] from a [MediaItem].
44+
///
45+
/// If the [MediaItem] was created using [MediaItem.fromNetwork] and doesn't
46+
/// have bytes yet, this method will fetch the file from the network URL.
47+
///
48+
/// Example:
49+
/// ```dart
50+
/// final mediaItem = MediaItem.fromNetwork('https://example.com/image.png');
51+
/// final attachedFile = await AttachedFile.fromMediaItem(mediaItem);
52+
/// ```
53+
static Future<AttachedFile> fromMediaItem(MediaItem mediaItem) async {
54+
// If bytes are already present (e.g., from MediaItem.fromFile), use them directly
55+
if (mediaItem.bytes != null) {
56+
return AttachedFile._(mediaItem);
57+
}
58+
59+
// If no bytes, fetch from the network URL
60+
final uri = Uri.parse(mediaItem.url);
61+
final response = await http.get(uri);
62+
63+
// Extract filename from the URL or use a default
64+
final name =
65+
uri.pathSegments.isNotEmpty ? uri.pathSegments.last : 'file.txt';
66+
67+
// Create a new MediaItem with the fetched bytes and attachment:// URL
68+
final media = MediaItem.fromNetwork(
69+
'attachment://$name',
70+
spoiler: mediaItem.spoiler,
71+
proxyUrl: mediaItem.proxyUrl,
72+
height: mediaItem.height,
73+
width: mediaItem.width,
74+
contentType: mediaItem.contentType,
75+
description: mediaItem.description,
76+
)..bytes = response.bodyBytes;
77+
78+
return AttachedFile._(media);
79+
}
80+
81+
/// Creates an [AttachedFile] by fetching a file from a network URL.
82+
///
83+
/// This method downloads the file from the specified [url] and prepares it
84+
/// for attachment to a Discord message. The file is automatically converted
85+
/// to use Discord's `attachment://` protocol with the provided [name].
86+
///
87+
/// Example:
88+
/// ```dart
89+
/// final attachedFile = await AttachedFile.fromNetwork(
90+
/// 'https://example.com/data/data.json',
91+
/// 'data.json',
92+
/// spoiler: true,
93+
/// );
94+
///
95+
/// final builder = MessageBuilder()
96+
/// ..addText('Check out these datas!')
97+
/// ..addFile(attachedFile);
98+
/// ```
99+
static Future<AttachedFile> fromNetwork(
100+
String url,
101+
String name, {
102+
bool? spoiler,
103+
String? proxyUrl,
104+
int? height,
105+
int? width,
106+
String? contentType,
107+
String? description,
108+
}) async {
109+
// Fetch bytes from the network URL
110+
final uri = Uri.parse(url);
111+
final response = await http.get(uri);
112+
113+
// Create a MediaItem with the fetched bytes
114+
final media = MediaItem.fromNetwork(
115+
'attachment://$name',
116+
spoiler: spoiler,
117+
proxyUrl: proxyUrl,
118+
height: height,
119+
width: width,
120+
contentType: contentType,
121+
description: description,
122+
)
123+
..bytes = response.bodyBytes
124+
..spoiler = spoiler;
125+
126+
return AttachedFile._(media);
127+
}
128+
129+
@override
130+
Map<String, dynamic> toJson() {
131+
return {'type': type.value, ...item.toJson()};
132+
}
133+
}

0 commit comments

Comments
 (0)