diff --git a/lib/constants.dart b/lib/constants.dart index ac7dba313..e96356e3a 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -1,3 +1,5 @@ +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:yaru/constants.dart'; @@ -146,6 +148,7 @@ const kSelectedPageId = 'selectedPageId'; const kRadioIndex = 'radioIndex'; const kPodcastIndex = 'podcastIndex'; const kNeverShowImportFails = 'neverShowImportFails'; +const kEnableDiscordRPC = 'enableDiscordRPC'; const kLastCountryCode = 'lastCountryCode'; const kLastLanguageCode = 'lastLanguageCode'; const kSearchResult = 'searchResult'; @@ -185,3 +188,7 @@ const kAlbumArtHeaders = { const kAudioHeaderDescriptionWidth = 400.0; const kShowLeadingThreshold = 3000; + +// TODO(#946): make discord work inside the snap +// or leave it for linux disabled if this won't work +bool kDiscordEnabledOnPlatform = !Platform.isLinux; diff --git a/lib/expose/expose_service.dart b/lib/expose/expose_service.dart index a89a7c607..913a98c6f 100644 --- a/lib/expose/expose_service.dart +++ b/lib/expose/expose_service.dart @@ -3,16 +3,16 @@ import 'package:flutter_discord_rpc/flutter_discord_rpc.dart'; import '../constants.dart'; class ExposeService { - ExposeService({required FlutterDiscordRPC discordRPC}) + ExposeService({required FlutterDiscordRPC? discordRPC}) : _discordRPC = discordRPC; - final FlutterDiscordRPC _discordRPC; + final FlutterDiscordRPC? _discordRPC; - Future exposeTitleOnline({ + Future? exposeTitleOnline({ required String songDetails, required String state, }) { - return _discordRPC.setActivity( + return _discordRPC?.setActivity( activity: RPCActivity( assets: RPCAssets( largeText: songDetails, diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 251369b4d..1d931982e 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -347,6 +347,10 @@ "skipToLivStream": "Zur Live-Übertragung springen", "searchSimilarStation": "Ähnlichen Sender suchen", "clicks": "Clicks", + "exposeOnlineHeadline": "Veröffentliche deine Höraktivität online", + "exposeToDiscordTitle": "Discord", + "exposeToDiscordSubTitle": "Der Künstler und Titel des Lieds/Radio-Senders/Podcast das du gerade hörst wird online geteilt. Benötigt App-Neustart.", + "featureDisabledOnPlatform": "Diese Funktion ist momentan nicht für dieses Betriebssystem aktiviert.", "regionNone": "Keine", "onlineArtError": "Die Albumkunst-Online-Suche ist momentan nicht verfügbar", "regionAfghanistan": "Afghanistan", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 24279e772..9f6126b28 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -346,6 +346,10 @@ "searchSimilarStation": "Search similar station", "onlineArtError": "Online art lookup is currently not available", "clicks": "Clicks", + "exposeOnlineHeadline": "Expose your listening activity online", + "exposeToDiscordTitle": "Discord", + "exposeToDiscordSubTitle": "The artist and title of the song/station/podcast you are currently listening to are shared. Requires app restart.", + "featureDisabledOnPlatform": "This feature is currently disabled for this operating system.", "regionNone": "None", "regionAfghanistan": "Afghanistan", "regionAlandislands": "Alandislands", diff --git a/lib/main.dart b/lib/main.dart index 9a871e317..7509dcc5e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -58,14 +58,25 @@ Future main(List args) async { final sharedPreferences = await SharedPreferences.getInstance(); final version = (await PackageInfo.fromPlatform()).version; - await FlutterDiscordRPC.initialize(kDiscordApplicationId); - FlutterDiscordRPC.instance.connect(); + final enableDiscord = kDiscordEnabledOnPlatform && + sharedPreferences.get(kEnableDiscordRPC) == true; + if (enableDiscord) { + await FlutterDiscordRPC.initialize(kDiscordApplicationId); + FlutterDiscordRPC.instance.connect(); + di.registerLazySingleton( + () => FlutterDiscordRPC.instance, + dispose: (s) { + s.disconnect(); + s.dispose(); + }, + ); + } registerServicesAndViewModels( sharedPreferences: sharedPreferences, args: args, version: version, - discordRPC: FlutterDiscordRPC.instance, + enableDiscord: enableDiscord, ); runApp( @@ -77,9 +88,9 @@ Future main(List args) async { void registerServicesAndViewModels({ required SharedPreferences sharedPreferences, - required FlutterDiscordRPC discordRPC, required List args, required String version, + required bool enableDiscord, }) { di ..registerLazySingleton(() => sharedPreferences) @@ -93,15 +104,10 @@ void registerServicesAndViewModels({ ), dispose: (s) => s.dispose(), ) - ..registerLazySingleton( - () => discordRPC, - dispose: (s) { - s.disconnect(); - s.dispose(); - }, - ) ..registerLazySingleton( - () => ExposeService(discordRPC: di()), + () => ExposeService( + discordRPC: enableDiscord ? di() : null, + ), ) ..registerLazySingleton( () => PlayerService( diff --git a/lib/settings/settings_model.dart b/lib/settings/settings_model.dart index b942e1636..0f8aab90c 100644 --- a/lib/settings/settings_model.dart +++ b/lib/settings/settings_model.dart @@ -27,6 +27,9 @@ class SettingsModel extends SafeChangeNotifier { void setNeverShowFailedImports(bool value) => _service.setNeverShowFailedImports(value); + bool get enableDiscordRPC => _service.enableDiscordRPC; + void setEnableDiscordRPC(bool value) => _service.setEnableDiscordRPC(value); + bool get usePodcastIndex => _service.usePodcastIndex; Future setUsePodcastIndex(bool value) async => _service.setUsePodcastIndex(value); diff --git a/lib/settings/settings_service.dart b/lib/settings/settings_service.dart index eed4b0627..2144e8346 100644 --- a/lib/settings/settings_service.dart +++ b/lib/settings/settings_service.dart @@ -10,9 +10,9 @@ class SettingsService { : _preferences = sharedPreferences; final SharedPreferences _preferences; - final _propertiesChangedController = StreamController.broadcast(); Stream get propertiesChanged => _propertiesChangedController.stream; + int get themeIndex => _preferences.getInt(kThemeIndex) ?? 0; void setThemeIndex(int value) { _preferences.setInt(kThemeIndex, value).then( @@ -33,6 +33,16 @@ class SettingsService { ); } + bool get enableDiscordRPC => _preferences.getBool(kEnableDiscordRPC) ?? false; + + void setEnableDiscordRPC(bool value) { + _preferences.setBool(kEnableDiscordRPC, value).then( + (saved) { + if (saved) _propertiesChangedController.add(true); + }, + ); + } + bool recentPatchNotesDisposed(String version) => _preferences.getString(kPatchNotesDisposed) == version; diff --git a/lib/settings/view/settings_page.dart b/lib/settings/view/settings_page.dart index 39ade71aa..fa60ce13e 100644 --- a/lib/settings/view/settings_page.dart +++ b/lib/settings/view/settings_page.dart @@ -44,6 +44,7 @@ class SettingsPage extends StatelessWidget { _ThemeSection(), _PodcastSection(), _LocalAudioSection(), + _ExposeOnlineSection(), _AboutSection(), ], ), @@ -412,3 +413,40 @@ class _LicenseTile extends StatelessWidget { ); } } + +class _ExposeOnlineSection extends StatelessWidget with WatchItMixin { + const _ExposeOnlineSection(); + + @override + Widget build(BuildContext context) { + final l10n = context.l10n; + return YaruSection( + headline: Text(l10n.exposeOnlineHeadline), + margin: const EdgeInsets.only( + top: kYaruPagePadding, + right: kYaruPagePadding, + left: kYaruPagePadding, + ), + child: Column( + children: [ + YaruTile( + title: Text(l10n.exposeToDiscordTitle), + subtitle: Text( + kDiscordEnabledOnPlatform + ? l10n.exposeToDiscordSubTitle + : l10n.featureDisabledOnPlatform, + ), + trailing: CommonSwitch( + value: kDiscordEnabledOnPlatform + ? watchPropertyValue((SettingsModel m) => m.enableDiscordRPC) + : false, + onChanged: kDiscordEnabledOnPlatform + ? di().setEnableDiscordRPC + : null, + ), + ), + ], + ), + ); + } +} diff --git a/needs_translation.json b/needs_translation.json index f88d3f218..f9e010e80 100644 --- a/needs_translation.json +++ b/needs_translation.json @@ -23,6 +23,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -301,6 +305,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -555,7 +563,11 @@ "es": [ "onlineArtError", - "clicks" + "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform" ], "fr": [ @@ -573,6 +585,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -829,7 +845,11 @@ "skipToLivStream", "searchSimilarStation", "onlineArtError", - "clicks" + "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform" ], "nl": [ @@ -1076,6 +1096,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -1392,6 +1416,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -1859,6 +1887,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -2326,6 +2358,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -2608,6 +2644,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -2864,7 +2904,11 @@ "skipToLivStream", "searchSimilarStation", "onlineArtError", - "clicks" + "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform" ], "sv": [ @@ -3072,6 +3116,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -3348,6 +3396,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -3606,7 +3658,11 @@ "skipToLivStream", "searchSimilarStation", "onlineArtError", - "clicks" + "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform" ], "zh_CN": [ @@ -3615,7 +3671,11 @@ "skipToLivStream", "searchSimilarStation", "onlineArtError", - "clicks" + "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform" ], "zh_HK": [ @@ -3634,6 +3694,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands", @@ -3902,6 +3966,10 @@ "searchSimilarStation", "onlineArtError", "clicks", + "exposeOnlineHeadline", + "exposeToDiscordTitle", + "exposeToDiscordSubTitle", + "featureDisabledOnPlatform", "regionNone", "regionAfghanistan", "regionAlandislands",