Skip to content

Commit ef22e82

Browse files
306 rework attachments in interaction for better dev (#308)
* feat: deleted message media, who isn't used (use Asset instead) * feat: Use Asset * feat: created general asset for img uses * feat: export Asset * feat: rework this func * feat: renamed to MessageFile * feat: renamed to MediaItem (like discord API) * feat: renamed to media instead of asset * feat: mixed message_file.dart and media_item.dart :)
1 parent f70b517 commit ef22e82

File tree

8 files changed

+108
-176
lines changed

8 files changed

+108
-176
lines changed

lib/api.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ export 'package:mineral/src/api/common/commands/command_option_type.dart';
2929
export 'package:mineral/src/api/common/commands/command_type.dart';
3030
export 'package:mineral/src/api/common/components/component.dart';
3131
export 'package:mineral/src/api/common/components/component_type.dart';
32-
export 'package:mineral/src/api/common/components/message/message_button.dart';
32+
export 'package:mineral/src/api/common/components/media_item.dart';
3333
// Commons
3434
export 'package:mineral/src/api/common/components/message/message_builder.dart';
35+
export 'package:mineral/src/api/common/components/message/message_button.dart';
3536
export 'package:mineral/src/api/common/components/message/message_file.dart';
3637
export 'package:mineral/src/api/common/components/message/message_gallery.dart';
37-
export 'package:mineral/src/api/common/components/message/message_media.dart';
3838
export 'package:mineral/src/api/common/components/message/message_row_builder.dart';
3939
export 'package:mineral/src/api/common/components/message/message_section.dart';
4040
export 'package:mineral/src/api/common/components/message/message_separator.dart';
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import 'dart:io';
2+
import 'dart:typed_data';
3+
4+
final class MediaItem {
5+
Uint8List? bytes;
6+
final String url;
7+
bool? spoiler;
8+
final String? proxyUrl;
9+
final int? height;
10+
final int? width;
11+
final String? contentType;
12+
final String? description;
13+
14+
MediaItem(this.url, {this.spoiler, this.proxyUrl, this.height, this.width, this.contentType, this.description});
15+
16+
factory MediaItem.file(File file, String name, {bool? spoiler, String? proxyUrl, int? height, int? width, String? contentType, String? description}) {
17+
if (!file.existsSync()) {
18+
throw ArgumentError('File ${file.path} does not exist');
19+
}
20+
21+
if (name.isEmpty) {
22+
throw ArgumentError("Name can't be empty.");
23+
}
24+
25+
final bytes = file.readAsBytesSync();
26+
27+
return MediaItem(
28+
'attachment://$name',
29+
spoiler: spoiler,
30+
proxyUrl: proxyUrl,
31+
height: height,
32+
width: width,
33+
contentType: contentType,
34+
description: description,
35+
)..bytes = bytes;
36+
}
37+
38+
Map<String, dynamic> toJson() {
39+
return {
40+
if (description != null) 'description': description,
41+
'url': url,
42+
if (bytes != null) 'bytes': bytes!,
43+
if (spoiler != null) 'spoiler': spoiler,
44+
'media': {
45+
'url': url,
46+
if (proxyUrl != null) 'proxy_url': proxyUrl,
47+
if (height != null) 'height': height,
48+
if (width != null) 'width': width,
49+
if (contentType != null) 'content_type': contentType,
50+
},
51+
};
52+
}
53+
}

lib/src/api/common/components/message/message_builder.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ final class MessageBuilder {
7676
_components.add(gallery);
7777
}
7878

79-
void file(Attachment file) {
79+
void file(MessageFile file) {
8080
_components.add(file);
8181
}
8282

Lines changed: 10 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,26 @@
1-
import 'dart:io';
2-
import 'dart:typed_data';
3-
41
import 'package:http/http.dart' as http;
52
import 'package:mineral/api.dart';
63

7-
final class Attachment implements Component {
4+
final class MessageFile implements Component {
85
ComponentType get type => ComponentType.file;
96

10-
static final Map<String, Uint8List> _cachedAttachments = {};
11-
12-
Uint8List? bytes;
13-
final String _path;
14-
final bool? _spoiler;
15-
16-
Attachment(this._path, {bool? spoiler}) : _spoiler = spoiler;
17-
18-
factory Attachment.path(String path, {bool? spoiler, bool cache = false}) {
19-
if (cache && _cachedAttachments.containsKey(path)) {
20-
return Attachment(path, spoiler: spoiler)
21-
..bytes = _cachedAttachments[path]!;
22-
}
7+
MediaItem item;
238

24-
final file = File(path);
25-
final bytes = file.readAsBytesSync();
26-
27-
return Attachment(path, spoiler: spoiler)..bytes = bytes;
28-
}
29-
30-
static Future<Attachment> network(String url,
31-
{bool? spoiler, bool cache = false}) async {
32-
if (cache && _cachedAttachments.containsKey(url)) {
33-
return Attachment(url, spoiler: spoiler)
34-
..bytes = _cachedAttachments[url]!;
35-
}
9+
MessageFile(this.item);
3610

11+
static Future<MessageFile> network(String url, {bool? spoiler}) async {
3712
final uri = Uri.parse(url);
3813
final response = await http.get(uri);
14+
final name = uri.pathSegments.isNotEmpty ? uri.pathSegments.last : 'file.txt';
15+
final media = MediaItem('attachment://$name')
16+
..bytes = response.bodyBytes
17+
..spoiler = spoiler;
3918

40-
_cachedAttachments[url] = response.bodyBytes;
41-
42-
return Attachment(uri.path, spoiler: spoiler)..bytes = response.bodyBytes;
19+
return MessageFile(media);
4320
}
4421

4522
@override
4623
Map<String, dynamic> toJson() {
47-
return {
48-
'type': type.value,
49-
'file': {
50-
'url': _path,
51-
'bytes': bytes,
52-
},
53-
if (_spoiler != null) 'spoiler': _spoiler,
54-
};
24+
return {'type': type.value, ...item.toJson()};
5525
}
5626
}
Lines changed: 2 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
1-
import 'dart:io';
2-
import 'dart:typed_data';
31
import 'package:mineral/api.dart';
42

53
final class MessageGallery implements Component {
64
ComponentType get type => ComponentType.mediaGallery;
7-
final List<GalleryItem> _items;
5+
final List<MediaItem> _items;
86

9-
MessageGallery({required List<GalleryItem> items}) : _items = items;
7+
MessageGallery({required List<MediaItem> items}) : _items = items;
108

119
@override
1210
Map<String, dynamic> toJson() {
@@ -16,66 +14,3 @@ final class MessageGallery implements Component {
1614
};
1715
}
1816
}
19-
20-
final class GalleryItem {
21-
final MessageMedia _media;
22-
final String? _description;
23-
final bool? _spoiler;
24-
Uint8List? _bytes;
25-
26-
GalleryItem(
27-
String url, {
28-
String? proxyUrl,
29-
int? height,
30-
int? width,
31-
String? contentType,
32-
String? description,
33-
bool? spoiler,
34-
}) : _media = MessageMedia(
35-
url,
36-
proxyUrl: proxyUrl,
37-
height: height,
38-
width: width,
39-
contentType: contentType,
40-
),
41-
_description = description,
42-
_spoiler = spoiler;
43-
44-
Map<String, dynamic> toJson() {
45-
return {
46-
'media': {
47-
'url': _media.url,
48-
if (_media.proxyUrl != null) 'proxy_url': _media.proxyUrl,
49-
if (_media.height != null) 'height': _media.height,
50-
if (_media.width != null) 'width': _media.width,
51-
if (_media.contentType != null) 'content_type': _media.contentType,
52-
},
53-
if (_bytes != null) 'bytes': _bytes!,
54-
if (_description != null) 'description': _description,
55-
if (_spoiler != null) 'spoiler': _spoiler,
56-
};
57-
}
58-
59-
60-
/// ```dart
61-
/// final file = File("assets/logo.png");
62-
// final myImage = GalleryItem.fromFile(file, "test.png");
63-
/// ```
64-
///
65-
/// WARN: Please make sure you put the correct file extension in the name.
66-
/// Used to put a image file to discord's gallery instead of an url.
67-
factory GalleryItem.fromFile(File file, String name) {
68-
if (!file.existsSync()) {
69-
throw ArgumentError('File ${file.path} does not exist');
70-
}
71-
72-
if (name.isEmpty) {
73-
throw ArgumentError("Name can't be empty.");
74-
}
75-
76-
final bytes = file.readAsBytesSync();
77-
78-
return GalleryItem('attachment://$name')
79-
.._bytes = bytes;
80-
}
81-
}

lib/src/api/common/components/message/message_media.dart

Lines changed: 0 additions & 15 deletions
This file was deleted.

lib/src/api/common/components/message/message_thumbnail.dart

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,15 @@ import 'package:mineral/api.dart';
22

33
final class MessageThumbnail implements Component {
44
ComponentType get type => ComponentType.thumbnail;
5+
final MediaItem media;
56

6-
final MessageMedia _media;
7-
final String? _description;
8-
final bool? _spoiler;
9-
10-
MessageThumbnail(
11-
MessageMedia media, {
12-
String? description,
13-
bool? spoiler,
14-
}) : _media = media,
15-
_description = description,
16-
_spoiler = spoiler;
7+
MessageThumbnail(this.media);
178

189
@override
1910
Map<String, dynamic> toJson() {
2011
return {
2112
'type': type.value,
22-
'media': {
23-
'url': _media.url,
24-
if (_media.proxyUrl != null) 'proxy_url': _media.proxyUrl,
25-
if (_media.height != null) 'height': _media.height,
26-
if (_media.width != null) 'width': _media.width,
27-
if (_media.contentType != null) 'content_type': _media.contentType,
28-
},
29-
if (_description != null) 'description': _description,
30-
if (_spoiler != null) 'spoiler': _spoiler,
13+
...media.toJson(),
3114
};
3215
}
3316
}
Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
import 'package:http/http.dart' as http;
22
import 'package:mineral/api.dart';
33

4-
typedef AttachmentResult = (
5-
List<Map<String, dynamic>>,
6-
List<http.MultipartFile>
7-
);
4+
typedef AttachmentResult = (List<Map<String, dynamic>>, List<http.MultipartFile>);
85

96
AttachmentResult makeAttachmentFromBuilder(MessageBuilder builder) {
107
final components = builder.build();
@@ -14,40 +11,23 @@ AttachmentResult makeAttachmentFromBuilder(MessageBuilder builder) {
1411
final comp = components[i];
1512

1613
if (comp['type'] == ComponentType.file.value) {
17-
final filePath = comp['file']['url'];
18-
final filename = filePath.split('/').last;
19-
20-
final multipartFile = http.MultipartFile.fromBytes(
21-
'files[${files.length}]',
22-
comp['file']['bytes'],
23-
filename: filename,
24-
);
25-
26-
files.add(multipartFile);
27-
comp['file']['url'] = 'attachment://$filename';
28-
comp['file']['bytes'] = null;
14+
final file = _prepareAsset(comp, files.length);
15+
16+
if (file != null) {
17+
files.add(file);
18+
}
19+
2920
continue;
3021
}
3122

3223
if (comp['type'] == ComponentType.mediaGallery.value) {
3324
final items = comp['items'] as List<dynamic>?;
3425
if (items != null) {
3526
for (final item in items) {
36-
final media = item['media'] as Map<String, dynamic>?;
37-
final url = media?['url'] as String?;
38-
39-
if (url != null && url.startsWith('attachment://') && item['bytes'] != null) {
40-
final filename = url.replaceFirst('attachment://', '');
41-
final bytes = item['bytes'];
42-
43-
if (bytes != null) {
44-
final multipartFile = http.MultipartFile.fromBytes(
45-
'files[${files.length}]',
46-
bytes,
47-
filename: filename,
48-
);
49-
files.add(multipartFile);
50-
}
27+
final file = _prepareAsset(item, files.length);
28+
29+
if (file != null) {
30+
files.add(file);
5131
}
5232
}
5333
}
@@ -56,3 +36,29 @@ AttachmentResult makeAttachmentFromBuilder(MessageBuilder builder) {
5636

5737
return (components, files);
5838
}
39+
40+
http.MultipartFile? _prepareAsset(dynamic payload, int filesLength) {
41+
final media = payload['media'] as Map<String, dynamic>?;
42+
final url = media?['url'] as String?;
43+
44+
if (url != null && url.startsWith('attachment://') && payload['bytes'] != null) {
45+
final filename = url.replaceFirst('attachment://', '');
46+
47+
final multipartFile = http.MultipartFile.fromBytes(
48+
'files[$filesLength]',
49+
payload['bytes'],
50+
filename: filename,
51+
);
52+
53+
payload['url'] = 'attachment://$filename';
54+
payload['file'] = {
55+
'url': 'attachment://$filename',
56+
'name': filename,
57+
};
58+
payload['bytes'] = null;
59+
60+
return multipartFile;
61+
}
62+
63+
return null;
64+
}

0 commit comments

Comments
 (0)