more gracefully handle failed audio messages
This commit is contained in:
parent
c93004f060
commit
84dd903bc4
1 changed files with 53 additions and 22 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import "dart:async";
|
import "dart:async";
|
||||||
|
|
||||||
import "package:audioplayers/audioplayers.dart" as audioplayers;
|
import "package:audioplayers/audioplayers.dart" as audioplayers;
|
||||||
|
import "package:flutter/services.dart";
|
||||||
import "package:material_ui/material_ui.dart";
|
import "package:material_ui/material_ui.dart";
|
||||||
import "package:flutter_hooks/flutter_hooks.dart";
|
import "package:flutter_hooks/flutter_hooks.dart";
|
||||||
import "package:hooks_riverpod/hooks_riverpod.dart";
|
import "package:hooks_riverpod/hooks_riverpod.dart";
|
||||||
|
|
@ -20,6 +21,7 @@ class const AudioPlayer(
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final player = useMemoized(audioplayers.AudioPlayer.new);
|
final player = useMemoized(audioplayers.AudioPlayer.new);
|
||||||
final loaded = useState(false);
|
final loaded = useState(false);
|
||||||
|
final unsupported = useState(false);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
scheduleMicrotask(() async {
|
scheduleMicrotask(() async {
|
||||||
|
|
@ -29,7 +31,16 @@ class const AudioPlayer(
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
// Keeps the audio loaded after it finishes, so it can be replayed
|
// Keeps the audio loaded after it finishes, so it can be replayed
|
||||||
await player.setReleaseMode(.stop);
|
await player.setReleaseMode(.stop);
|
||||||
await player.setSource(audioplayers.DeviceFileSource(audio.path));
|
try {
|
||||||
|
// AVFoundation infers the format from the extension, which the cached file lacks
|
||||||
|
await player.setSource(
|
||||||
|
audioplayers.DeviceFileSource(audio.path, mimeType: info?.mimeType),
|
||||||
|
);
|
||||||
|
} on PlatformException catch (_) {
|
||||||
|
// The platform can't play this format, like Ogg on Apple platforms
|
||||||
|
if (context.mounted) unsupported.value = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (context.mounted) loaded.value = true;
|
if (context.mounted) loaded.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -50,32 +61,52 @@ class const AudioPlayer(
|
||||||
).requireData;
|
).requireData;
|
||||||
final playing = state == .playing;
|
final playing = state == .playing;
|
||||||
|
|
||||||
|
final downloadButton = IconButton(
|
||||||
|
onPressed: () => context.saveAttachment(
|
||||||
|
ref,
|
||||||
|
uri,
|
||||||
|
encrypted: encrypted,
|
||||||
|
filename: filename,
|
||||||
|
),
|
||||||
|
tooltip: "Download",
|
||||||
|
icon: Icon(Icons.download),
|
||||||
|
);
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: .symmetric(horizontal: 8),
|
padding: .symmetric(horizontal: 8),
|
||||||
child: PlayerControls(
|
child: unsupported.value
|
||||||
playing: playing,
|
? Row(
|
||||||
position: position,
|
children: [
|
||||||
duration: duration,
|
Padding(
|
||||||
onPlayPause: playing ? player.pause : player.resume,
|
padding: .all(12),
|
||||||
onSeek: player.seek,
|
child: Icon(
|
||||||
loading: !loaded.value,
|
Icons.music_off,
|
||||||
size: info?.size,
|
color: Theme.of(context).colorScheme.error,
|
||||||
actions: .new([
|
),
|
||||||
SizedBox(width: 4),
|
),
|
||||||
IconButton(
|
Expanded(
|
||||||
onPressed: () => context.saveAttachment(
|
child: Text(
|
||||||
ref,
|
"Can't play this audio format",
|
||||||
uri,
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
encrypted: encrypted,
|
color: Theme.of(context).colorScheme.error,
|
||||||
filename: filename,
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
downloadButton,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: PlayerControls(
|
||||||
|
playing: playing,
|
||||||
|
position: position,
|
||||||
|
duration: duration,
|
||||||
|
onPlayPause: playing ? player.pause : player.resume,
|
||||||
|
onSeek: player.seek,
|
||||||
|
loading: !loaded.value,
|
||||||
|
size: info?.size,
|
||||||
|
actions: .new([SizedBox(width: 4), downloadButton]),
|
||||||
),
|
),
|
||||||
tooltip: "Download",
|
|
||||||
icon: Icon(Icons.download),
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue