diff --git a/lib/provider/discord_provider.dart b/lib/provider/discord_provider.dart index 1e819af0..23be0bc3 100644 --- a/lib/provider/discord_provider.dart +++ b/lib/provider/discord_provider.dart @@ -6,6 +6,7 @@ import 'package:spotify/spotify.dart'; import 'package:spotube/extensions/artist_simple.dart'; import 'package:spotube/provider/audio_player/audio_player.dart'; import 'package:spotube/provider/user_preferences/user_preferences_provider.dart'; +import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/utils/platform.dart'; class DiscordNotifier extends AsyncNotifier { @@ -13,17 +14,39 @@ class DiscordNotifier extends AsyncNotifier { FutureOr build() async { final enabled = ref.watch( userPreferencesProvider.select((s) => s.discordPresence && kIsDesktop)); - final playback = ref.read(audioPlayerProvider); - final subscription = - FlutterDiscordRPC.instance.isConnectedStream.listen((connected) async { - if (connected && playback.activeTrack != null) { - await updatePresence(playback.activeTrack!); - } - }); + var lastPosition = audioPlayer.position; + + final subscriptions = + [ + FlutterDiscordRPC.instance.isConnectedStream.listen((connected) async { + final playback = ref.read(audioPlayerProvider); + if (connected && playback.activeTrack != null) { + await updatePresence(playback.activeTrack!); + } + }), + audioPlayer.playerStateStream.listen((state) async { + final playback = ref.read(audioPlayerProvider); + if (playback.activeTrack == null) return; + + await updatePresence(ref.read(audioPlayerProvider).activeTrack!); + }), + audioPlayer.positionStream.listen((position) async { + final playback = ref.read(audioPlayerProvider); + if (playback.activeTrack != null) { + final diff = position.inMilliseconds - lastPosition.inMilliseconds; + if (diff > 500 || diff < -500) { + await updatePresence(ref.read(audioPlayerProvider).activeTrack!); + } + } + lastPosition = position; + }) + ]; ref.onDispose(() async { - subscription.cancel(); + for (final subscription in subscriptions) { + subscription.cancel(); + } await close(); await FlutterDiscordRPC.instance.dispose(); }); @@ -37,15 +60,18 @@ class DiscordNotifier extends AsyncNotifier { } Future updatePresence(Track track) async { - await clear(); - final artistNames = track.artists?.asString() ?? ""; + final artistNames = track.artists?.asString(); + final isPlaying = audioPlayer.isPlaying; + final position = audioPlayer.position; + await FlutterDiscordRPC.instance.setActivity( activity: RPCActivity( - details: "${track.name} by $artistNames", - state: "Vibing in Music", - assets: const RPCAssets( - largeImage: "spotube-logo-foreground", - largeText: "Spotube", + details: track.name, + state: artistNames != null ? "by $artistNames" : null, + assets: RPCAssets( + largeImage: + track.album?.images?.first.url ?? "spotube-logo-foreground", + largeText: track.album?.name ?? "Unknown album", smallImage: "spotube-logo-foreground", smallText: "Spotube", ), @@ -57,7 +83,7 @@ class DiscordNotifier extends AsyncNotifier { ), ], timestamps: RPCTimestamps( - start: DateTime.now().millisecondsSinceEpoch, + start: isPlaying ? DateTime.now().millisecondsSinceEpoch - position.inMilliseconds : null, ), ), ); @@ -73,4 +99,4 @@ class DiscordNotifier extends AsyncNotifier { } final discordProvider = - AsyncNotifierProvider(() => DiscordNotifier()); + AsyncNotifierProvider(() => DiscordNotifier()); \ No newline at end of file