Skip to content

Commit a614da2

Browse files
authored
chore: media classes (#107)
* chore: Refactor media handling and localization updates - Updated SafeNetworkImage to handle empty URLs. - Removed TODO comments in ChatDownloadService and ChatMessageBubbleContent. - Introduced MediaFileX extension for file type validation. - Deleted obsolete media_x.dart file and moved relevant code to media_file_x.dart. - Added new LocalMedia and StationMedia classes for better media management. - Refactored PlayerManager to work with UniqueMedia instead of Media. - Updated player views to accommodate new media classes. - Enhanced localization with new strings for media queue management. - Updated radio browser and favorites list to utilize StationMedia. - Ensured all media-related components are consistent with the new structure. * chore: Refactor PlayerManager and PlayerFullView to streamline media handling and remove unused imports * chore: Refactor chat download service initialization and update attachment indicators in message views
1 parent 3708388 commit a614da2

27 files changed

+568
-316
lines changed

lib/common/view/safe_network_image.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class SafeNetworkImage extends StatelessWidget {
4848
Icon(YaruIcons.user, size: height != null ? height! * 0.7 : null),
4949
);
5050

51-
if (url == null) return fallBack;
51+
if (url == null || url!.isEmpty) return fallBack;
5252

5353
try {
5454
if (url!.endsWith('.svg')) {

lib/events/chat_download_service.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ class ChatDownloadService {
2626
return path != null && File(path).existsSync() ? path : null;
2727
}
2828

29-
Future<void> init() async {}
30-
31-
// TODO: use dio to download then decrypt with client, to show the download progress
3229
Future<void> safeFile({
3330
required Event event,
3431
required String confirmButtonText,

lib/events/view/chat_message_attachment_indicator.dart

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@ class ChatMessageAttachmentIndicator extends StatelessWidget with WatchItMixin {
1010
const ChatMessageAttachmentIndicator({
1111
super.key,
1212
required this.event,
13-
this.iconSize = 15.0,
1413
this.color,
1514
});
1615

1716
final Event event;
18-
final double iconSize;
1917
final Color? color;
2018

2119
@override
@@ -31,9 +29,8 @@ class ChatMessageAttachmentIndicator extends StatelessWidget with WatchItMixin {
3129
child: Icon(
3230
YaruIcons.download_filled,
3331
color: context.colorScheme.primary,
34-
size: iconSize,
3532
),
3633
)
37-
: Icon(YaruIcons.download, size: iconSize, color: color);
34+
: Icon(YaruIcons.download, color: color);
3835
}
3936
}

lib/events/view/chat_message_bubble_content.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import '../chat_download_manager.dart';
1717
import 'chat_event_status_icon.dart';
1818
import 'chat_image.dart';
1919
import 'chat_map.dart';
20+
import 'chat_message_attachment_indicator.dart';
2021
import 'chat_message_image_full_screen_dialog.dart';
2122
import 'chat_message_media_avatar.dart';
2223
import 'chat_message_menu.dart';
@@ -170,7 +171,6 @@ class ChatMessageBubbleContent extends StatelessWidget with PlayerControlMixin {
170171
),
171172
),
172173
),
173-
// TODO: #5
174174
(MessageTypes.Video, true) => ChatImage(
175175
fit: BoxFit.contain,
176176
event: event,
@@ -196,7 +196,6 @@ class ChatMessageBubbleContent extends StatelessWidget with PlayerControlMixin {
196196
onReplyOriginClick:
197197
onReplyOriginClick,
198198
),
199-
// TODO: #5
200199
(
201200
MessageTypes.Audio ||
202201
MessageTypes.File ||
@@ -237,9 +236,10 @@ class ChatMessageBubbleContent extends StatelessWidget with PlayerControlMixin {
237236
confirmButtonText:
238237
l10n.saveFile,
239238
),
240-
icon: const Icon(
241-
YaruIcons.download,
242-
),
239+
icon:
240+
ChatMessageAttachmentIndicator(
241+
event: event,
242+
),
243243
),
244244
if (event.messageType ==
245245
MessageTypes.Audio ||
@@ -251,7 +251,7 @@ class ChatMessageBubbleContent extends StatelessWidget with PlayerControlMixin {
251251
playMatrixMedia(
252252
context,
253253
event: event,
254-
addInQueue: true,
254+
newPlaylist: false,
255255
),
256256
icon: const Icon(
257257
YaruIcons.music_queue,

lib/events/view/chat_message_image_full_screen_dialog.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import '../../extensions/date_time_x.dart';
1717
import '../../extensions/event_x.dart';
1818
import '../../l10n/l10n.dart';
1919
import '../chat_download_manager.dart';
20+
import 'chat_message_attachment_indicator.dart';
2021

2122
class ChatMessageImageFullScreenDialog extends StatefulWidget {
2223
const ChatMessageImageFullScreenDialog({super.key, required this.event});
@@ -106,7 +107,7 @@ class _ChatMessageImageFullScreenDialogState
106107
dialogTitle: l10n.saveFile,
107108
confirmButtonText: l10n.saveFile,
108109
),
109-
icon: const Icon(YaruIcons.download),
110+
icon: ChatMessageAttachmentIndicator(event: widget.event),
110111
),
111112
],
112113
),

lib/extensions/media_file_x.dart

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import 'dart:io';
2+
3+
import 'package:mime/mime.dart';
4+
5+
extension MediaFileX on File {
6+
bool get isPlayable => path.isPlayable;
7+
}
8+
9+
final _resolver = MimeTypeResolver();
10+
11+
extension _ValidPathX on String {
12+
bool get isPlayable {
13+
for (var v in _SpecialMimeTypes.values) {
14+
_resolver
15+
..addExtension(v.extension, v.mimeType)
16+
..addMagicNumber(v.headerBytes, v.mimeType);
17+
}
18+
19+
final mime = _resolver.lookup(this);
20+
21+
return (mime?.contains('audio') ?? false) ||
22+
(mime?.contains('video') ?? false);
23+
}
24+
}
25+
26+
enum _SpecialMimeTypes {
27+
opusAudio;
28+
29+
String get mimeType => switch (this) {
30+
opusAudio => 'audio/opus',
31+
};
32+
33+
String get extension => switch (this) {
34+
opusAudio => 'opus',
35+
};
36+
37+
List<int> get headerBytes => switch (this) {
38+
opusAudio => [
39+
0x4F, // O
40+
0x67, // g
41+
0x67, // g
42+
0x53, // S
43+
],
44+
};
45+
}

lib/extensions/media_x.dart

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

lib/l10n/app_en.arb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3161,5 +3161,28 @@
31613161
"radioStations": "Radio stations",
31623162
"@radioStations": {},
31633163
"noRadioBrowserConnected": "No Radio Browser connected",
3164-
"@noRadioBrowserConnected": {}
3164+
"@noRadioBrowserConnected": {},
3165+
"appendMediaToQueueDescription": "{title} is already inside the queue. Do you want to append it to the end of the queue?",
3166+
"@appendMediaToQueueDescription": {
3167+
"type": "text",
3168+
"placeholders": {
3169+
"title": {
3170+
"type": "String"
3171+
}
3172+
}
3173+
},
3174+
"appendMediaToQueueTitle": "Append media to queue",
3175+
"@appendMediaToQueueTitle": {},
3176+
"appendMediaToQueue": "Append media to queue: {title}",
3177+
"@appendMediaToQueue": {
3178+
"type": "text",
3179+
"placeholders": {
3180+
"title": {
3181+
"type": "String"
3182+
}
3183+
}
3184+
},
3185+
"playNowButton": "Play now",
3186+
"@playNowButton": {},
3187+
"appendMediaToQueueButton": "Append to queue"
31653188
}

0 commit comments

Comments
 (0)