feat: toggle for discord rpc

This commit is contained in:
Kingkor Roy Tirtho 2023-12-08 13:27:31 +06:00
parent b92583d0df
commit 24a2294512
10 changed files with 125 additions and 61 deletions

View File

@ -108,4 +108,5 @@ abstract class SpotubeIcons {
static const noEye = FeatherIcons.eyeOff; static const noEye = FeatherIcons.eyeOff;
static const normalize = FeatherIcons.barChart2; static const normalize = FeatherIcons.barChart2;
static const wikipedia = SimpleIcons.wikipedia; static const wikipedia = SimpleIcons.wikipedia;
static const discord = SimpleIcons.discord;
} }

View File

@ -280,5 +280,6 @@
"login": "Login", "login": "Login",
"login_with_your_lastfm": "Login with your Last.fm account", "login_with_your_lastfm": "Login with your Last.fm account",
"scrobble_to_lastfm": "Scrobble to Last.fm", "scrobble_to_lastfm": "Scrobble to Last.fm",
"go_to_album": "Go to Album" "go_to_album": "Go to Album",
"discord_rich_presence": "Discord Rich Presence"
} }

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/settings/section_card_with_heading.dart'; import 'package:spotube/components/settings/section_card_with_heading.dart';
@ -50,6 +51,13 @@ class SettingsDesktopSection extends HookConsumerWidget {
value: preferences.systemTitleBar, value: preferences.systemTitleBar,
onChanged: preferencesNotifier.setSystemTitleBar, onChanged: preferencesNotifier.setSystemTitleBar,
), ),
if (!DesktopTools.platform.isMacOS)
SwitchListTile(
secondary: const Icon(SpotubeIcons.discord),
title: Text(context.l10n.discord_rich_presence),
value: preferences.discordPresence,
onChanged: preferencesNotifier.setDiscordPresence,
),
], ],
); );
} }

View File

@ -0,0 +1,70 @@
import 'package:dart_discord_rpc/dart_discord_rpc.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart';
import 'package:spotube/provider/user_preferences/user_preferences_provider.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
class Discord extends ChangeNotifier {
final DiscordRPC? discordRPC;
final bool isEnabled;
Discord(this.isEnabled)
: discordRPC = (DesktopTools.platform.isWindows ||
DesktopTools.platform.isLinux) &&
isEnabled
? DiscordRPC(applicationId: Env.discordAppId)
: null {
discordRPC?.start(autoRegister: true);
}
void updatePresence(Track track) {
clear();
final artistNames =
TypeConversionUtils.artists_X_String(track.artists ?? <Artist>[]);
discordRPC?.updatePresence(
DiscordPresence(
details: "Song: ${track.name} by $artistNames",
state: "Vibing in Music",
startTimeStamp: DateTime.now().millisecondsSinceEpoch,
largeImageKey: "spotube-logo-foreground",
largeImageText: "Spotube",
smallImageKey: "spotube-logo-foreground",
smallImageText: "Spotube",
),
);
}
void clear() {
discordRPC?.clearPresence();
}
void shutdown() {
discordRPC?.shutDown();
}
@override
void dispose() {
clear();
shutdown();
super.dispose();
}
}
final discordProvider = ChangeNotifierProvider(
(ref) {
final isEnabled =
ref.watch(userPreferencesProvider.select((s) => s.discordPresence));
final playback = ref.read(ProxyPlaylistNotifier.provider);
final discord = Discord(isEnabled);
if (playback.activeTrack != null) {
discord.updatePresence(playback.activeTrack!);
}
return discord;
},
);

View File

@ -24,7 +24,7 @@ import 'package:spotube/provider/user_preferences/user_preferences_provider.dart
import 'package:spotube/provider/user_preferences/user_preferences_state.dart'; import 'package:spotube/provider/user_preferences/user_preferences_state.dart';
import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/services/audio_player/audio_player.dart';
import 'package:spotube/services/audio_services/audio_services.dart'; import 'package:spotube/services/audio_services/audio_services.dart';
import 'package:spotube/services/discord/discord.dart'; import 'package:spotube/provider/discord_provider.dart';
import 'package:spotube/services/sourced_track/exceptions.dart'; import 'package:spotube/services/sourced_track/exceptions.dart';
import 'package:spotube/services/sourced_track/models/source_info.dart'; import 'package:spotube/services/sourced_track/models/source_info.dart';
import 'package:spotube/services/sourced_track/sourced_track.dart'; import 'package:spotube/services/sourced_track/sourced_track.dart';
@ -64,6 +64,7 @@ class ProxyPlaylistNotifier extends PersistedStateNotifier<ProxyPlaylist>
ProxyPlaylist get playlist => state; ProxyPlaylist get playlist => state;
BlackListNotifier get blacklist => BlackListNotifier get blacklist =>
ref.read(BlackListNotifier.provider.notifier); ref.read(BlackListNotifier.provider.notifier);
Discord get discord => ref.read(discordProvider);
static final provider = static final provider =
StateNotifierProvider<ProxyPlaylistNotifier, ProxyPlaylist>( StateNotifierProvider<ProxyPlaylistNotifier, ProxyPlaylist>(

View File

@ -110,6 +110,10 @@ class UserPreferencesNotifier extends PersistedStateNotifier<UserPreferences> {
} }
} }
void setDiscordPresence(bool discordPresence) {
state = state.copyWith(discordPresence: discordPresence);
}
void setAmoledDarkTheme(bool isAmoled) { void setAmoledDarkTheme(bool isAmoled) {
state = state.copyWith(amoledDarkTheme: isAmoled); state = state.copyWith(amoledDarkTheme: isAmoled);
} }

View File

@ -198,6 +198,9 @@ final class UserPreferences {
) )
final SourceCodecs downloadMusicCodec; final SourceCodecs downloadMusicCodec;
@JsonKey(defaultValue: true)
final bool discordPresence;
UserPreferences({ UserPreferences({
required this.audioQuality, required this.audioQuality,
required this.albumColorSync, required this.albumColorSync,
@ -219,6 +222,7 @@ final class UserPreferences {
required this.audioSource, required this.audioSource,
required this.streamMusicCodec, required this.streamMusicCodec,
required this.downloadMusicCodec, required this.downloadMusicCodec,
required this.discordPresence,
}); });
factory UserPreferences.withDefaults() { factory UserPreferences.withDefaults() {
@ -255,6 +259,7 @@ final class UserPreferences {
SourceCodecs? downloadMusicCodec, SourceCodecs? downloadMusicCodec,
SourceCodecs? streamMusicCodec, SourceCodecs? streamMusicCodec,
bool? systemTitleBar, bool? systemTitleBar,
bool? discordPresence,
}) { }) {
return UserPreferences( return UserPreferences(
themeMode: themeMode ?? this.themeMode, themeMode: themeMode ?? this.themeMode,
@ -277,6 +282,7 @@ final class UserPreferences {
normalizeAudio: normalizeAudio ?? this.normalizeAudio, normalizeAudio: normalizeAudio ?? this.normalizeAudio,
streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec, streamMusicCodec: streamMusicCodec ?? this.streamMusicCodec,
systemTitleBar: systemTitleBar ?? this.systemTitleBar, systemTitleBar: systemTitleBar ?? this.systemTitleBar,
discordPresence: discordPresence ?? this.discordPresence,
); );
} }
} }

View File

@ -63,6 +63,7 @@ UserPreferences _$UserPreferencesFromJson(Map<String, dynamic> json) =>
_$SourceCodecsEnumMap, json['downloadMusicCodec'], _$SourceCodecsEnumMap, json['downloadMusicCodec'],
unknownValue: SourceCodecs.m4a) ?? unknownValue: SourceCodecs.m4a) ??
SourceCodecs.m4a, SourceCodecs.m4a,
discordPresence: json['discordPresence'] as bool? ?? true,
); );
Map<String, dynamic> _$UserPreferencesToJson(UserPreferences instance) => Map<String, dynamic> _$UserPreferencesToJson(UserPreferences instance) =>
@ -88,6 +89,7 @@ Map<String, dynamic> _$UserPreferencesToJson(UserPreferences instance) =>
'audioSource': _$AudioSourceEnumMap[instance.audioSource]!, 'audioSource': _$AudioSourceEnumMap[instance.audioSource]!,
'streamMusicCodec': _$SourceCodecsEnumMap[instance.streamMusicCodec]!, 'streamMusicCodec': _$SourceCodecsEnumMap[instance.streamMusicCodec]!,
'downloadMusicCodec': _$SourceCodecsEnumMap[instance.downloadMusicCodec]!, 'downloadMusicCodec': _$SourceCodecsEnumMap[instance.downloadMusicCodec]!,
'discordPresence': instance.discordPresence,
}; };
const _$SourceQualitiesEnumMap = { const _$SourceQualitiesEnumMap = {

View File

@ -1,44 +0,0 @@
import 'package:dart_discord_rpc/dart_discord_rpc.dart';
import 'package:flutter_desktop_tools/flutter_desktop_tools.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/utils/type_conversion_utils.dart';
class Discord {
final DiscordRPC? discordRPC;
Discord()
: discordRPC =
DesktopTools.platform.isWindows || DesktopTools.platform.isLinux
? DiscordRPC(applicationId: Env.discordAppId)
: null {
discordRPC?.start(autoRegister: true);
}
void updatePresence(Track track) {
clear();
final artistNames =
TypeConversionUtils.artists_X_String(track.artists ?? <Artist>[]);
discordRPC?.updatePresence(
DiscordPresence(
details: "Song: ${track.name} by $artistNames",
state: "Vibing in Music",
startTimeStamp: DateTime.now().millisecondsSinceEpoch,
largeImageKey: "spotube-logo-foreground",
largeImageText: "Spotube",
smallImageKey: "spotube-logo-foreground",
smallImageText: "Spotube",
),
);
}
void clear() {
discordRPC?.clearPresence();
}
void shutdown() {
discordRPC?.shutDown();
}
}
final discord = Discord();

View File

@ -1,61 +1,76 @@
{ {
"ar": [ "ar": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"bn": [ "bn": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"ca": [ "ca": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"de": [ "de": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"es": [ "es": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"fa": [ "fa": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"fr": [ "fr": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"hi": [ "hi": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"ja": [ "ja": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"pl": [ "pl": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"pt": [ "pt": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"ru": [ "ru": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"tr": [ "tr": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"uk": [ "uk": [
"go_to_album" "go_to_album",
"discord_rich_presence"
], ],
"zh": [ "zh": [
"go_to_album" "go_to_album",
"discord_rich_presence"
] ]
} }