From 11073a64c3f837f0cc2d6482ed2c2392821e0078 Mon Sep 17 00:00:00 2001 From: Feichtmeier Date: Sat, 16 Nov 2024 19:46:14 +0100 Subject: [PATCH] feat: add elapsed in bottom player time if activated in the settings Fixes #753 --- lib/constants.dart | 1 + lib/l10n/app_de.arb | 2 + lib/l10n/app_en.arb | 2 + lib/player/view/player_title_and_artist.dart | 11 ++++ lib/player/view/player_track.dart | 62 ++++++++++++++++++++ lib/settings/settings_model.dart | 4 ++ lib/settings/settings_service.dart | 5 ++ lib/settings/view/theme_section.dart | 10 ++++ needs_translation.json | 34 +++++++++++ 9 files changed, 131 insertions(+) diff --git a/lib/constants.dart b/lib/constants.dart index a023b4a57..ca94514e5 100644 --- a/lib/constants.dart +++ b/lib/constants.dart @@ -176,6 +176,7 @@ const kAscendingFeeds = 'ascendingfeed:::'; const kPatchNotesDisposed = 'kPatchNotesDisposed'; const kCloseBtnAction = 'closeBtnAction'; const kUseMoreAnimations = 'useMoreAnimations'; +const kShowPositionDuration = 'showPositionDuration'; const shops = { 'https://us.7digital.com/': '7digital', diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 4719d2a75..224c15f22 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -199,6 +199,8 @@ "theme": "Thema", "useMoreAnimationsTitle": "Nutze mehr Animationen", "useMoreAnimationsDescription": "Dies wird die CPU-Nutzung erhöhen, was auf älteren System unerwünscht sein könnte.", + "showPositionDurationTitle": "Zeige Position / Dauer im unteren Player", + "showPositionDurationDescription": "Dies wird andernfalls trotzdem beim Track-Hover oder Vollansicht-Player angezeigt.", "license": "Lizenz", "dependencies": "Abhängigkeiten", "light": "Hell", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 13a58ea11..979ed17fd 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -199,6 +199,8 @@ "theme": "Theme", "useMoreAnimationsTitle": "Use more animations", "useMoreAnimationsDescription": "This will slightly increase the CPU usage, which might be undesired on older hardware.", + "showPositionDurationTitle": "Show position / duration in bottom player", + "showPositionDurationDescription": "It is otherwise always shown on track hover and in the full screen player.", "license": "License", "dependencies": "Dependencies", "light": "Light", diff --git a/lib/player/view/player_title_and_artist.dart b/lib/player/view/player_title_and_artist.dart index d0b41704f..29f8ceb46 100644 --- a/lib/player/view/player_title_and_artist.dart +++ b/lib/player/view/player_title_and_artist.dart @@ -14,7 +14,9 @@ import '../../local_audio/view/album_page.dart'; import '../../local_audio/view/artist_page.dart'; import '../../podcasts/podcast_model.dart'; import '../../radio/view/station_page.dart'; +import '../../settings/settings_model.dart'; import '../player_model.dart'; +import 'player_track.dart'; import 'player_view.dart'; class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin { @@ -32,6 +34,8 @@ class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin { final icyTitle = watchPropertyValue((PlayerModel m) => m.mpvMetaData?.icyTitle); + final showPositionDuration = + watchPropertyValue((SettingsModel m) => m.showPositionDuration); final appModel = di(); final libraryModel = di(); @@ -113,6 +117,13 @@ class PlayerTitleAndArtist extends StatelessWidget with WatchItMixin { ), ), ), + if (playerPosition == PlayerPosition.bottom && + audio?.audioType != AudioType.radio && + showPositionDuration) + const Padding( + padding: EdgeInsets.only(top: 2, bottom: 5), + child: PlayerSimpleTrack(), + ), ], ); } diff --git a/lib/player/view/player_track.dart b/lib/player/view/player_track.dart index d53616bfa..e59da8ae4 100644 --- a/lib/player/view/player_track.dart +++ b/lib/player/view/player_track.dart @@ -159,3 +159,65 @@ class PlayerTrack extends StatelessWidget with WatchItMixin { ); } } + +class PlayerSimpleTrack extends StatelessWidget with WatchItMixin { + const PlayerSimpleTrack({ + super.key, + this.active = true, + }); + + final bool active; + + @override + Widget build(BuildContext context) { + final theme = context.theme; + final position = watchPropertyValue((PlayerModel m) => m.position); + final duration = watchPropertyValue((PlayerModel m) => m.duration); + final textStyle = + TextStyle(fontSize: 10, color: !active ? theme.disabledColor : null); + + final positionWidth = + (position?.inHours != null && position!.inHours > 0) ? 48.0 : 35.0; + final durationWidth = + (duration?.inHours != null && duration!.inHours > 0) ? 48.0 : 35.0; + + const slashWidth = 5.0; + + const height = 13.0; + + return SizedBox( + width: positionWidth + durationWidth + slashWidth, + height: height, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + RepaintBoundary( + child: SizedBox( + width: positionWidth, + height: height, + child: Text( + (position ?? Duration.zero).formattedTime, + style: textStyle, + ), + ), + ), + SizedBox( + height: height, + width: slashWidth, + child: Text('/', style: textStyle)), + RepaintBoundary( + child: SizedBox( + width: durationWidth, + height: height, + child: Text( + (duration ?? Duration.zero).formattedTime, + style: textStyle, + textAlign: TextAlign.end, + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/settings/settings_model.dart b/lib/settings/settings_model.dart index 224cfa639..2bbe6e80d 100644 --- a/lib/settings/settings_model.dart +++ b/lib/settings/settings_model.dart @@ -100,6 +100,10 @@ class SettingsModel extends SafeChangeNotifier { void setCloseBtnActionIndex(CloseBtnAction value) => _service.setCloseBtnActionIndex(value); + bool get showPositionDuration => _service.showPositionDuration; + Future setShowPositionDuration(bool value) async => + _service.setShowPositionDuration(value); + void init() => _propertiesChangedSub ??= _service.propertiesChanged.listen((_) => notifyListeners()); diff --git a/lib/settings/settings_service.dart b/lib/settings/settings_service.dart index 028529f47..e62e1a884 100644 --- a/lib/settings/settings_service.dart +++ b/lib/settings/settings_service.dart @@ -91,6 +91,11 @@ class SettingsService { Future setDownloadsCustomDir(String directory) async => _preferences.setString(kDownloadsCustomDir, directory).then(notify); + bool get showPositionDuration => + _preferences.getBool(kShowPositionDuration) ?? false; + Future setShowPositionDuration(bool value) async => + _preferences.setBool(kShowPositionDuration, value).then(notify); + CloseBtnAction get closeBtnActionIndex => _preferences.getString(kCloseBtnAction) == null ? CloseBtnAction.alwaysAsk diff --git a/lib/settings/view/theme_section.dart b/lib/settings/view/theme_section.dart index 3940b47c1..958f0cd1a 100644 --- a/lib/settings/view/theme_section.dart +++ b/lib/settings/view/theme_section.dart @@ -17,6 +17,7 @@ class ThemeSection extends StatelessWidget with WatchItMixin { final model = di(); final l10n = context.l10n; final themeIndex = watchPropertyValue((SettingsModel m) => m.themeIndex); + return YaruSection( margin: const EdgeInsets.only( left: kYaruPagePadding, @@ -65,6 +66,15 @@ class ThemeSection extends StatelessWidget with WatchItMixin { watchPropertyValue((SettingsModel m) => m.useMoreAnimations), ), ), + YaruTile( + title: Text(l10n.showPositionDurationTitle), + subtitle: Text(l10n.showPositionDurationDescription), + trailing: CommonSwitch( + onChanged: di().setShowPositionDuration, + value: watchPropertyValue( + (SettingsModel m) => m.showPositionDuration), + ), + ), ], ), ); diff --git a/needs_translation.json b/needs_translation.json index 70017af42..ee2d46d3c 100644 --- a/needs_translation.json +++ b/needs_translation.json @@ -8,6 +8,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "radioTagDisclaimerTitle", "radioTagDisclaimerSubTitle", @@ -302,6 +304,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "duration", "radioTagDisclaimerTitle", @@ -597,6 +601,8 @@ "es": [ "saveAndAuthorize", + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -614,6 +620,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "alwaysAsk", "hideToTray", @@ -890,6 +898,8 @@ ], "it": [ + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -995,6 +1005,8 @@ "theme", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "license", "dependencies", "light", @@ -1438,6 +1450,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "reorder", "move", "pinAlbum", @@ -1812,6 +1826,8 @@ "theme", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "license", "dependencies", "light", @@ -2296,6 +2312,8 @@ "theme", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "license", "dependencies", "light", @@ -2725,6 +2743,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "language", "duration", @@ -3019,6 +3039,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -3059,6 +3081,8 @@ "stations", "copyToClipBoard", "insertedIntoQueue", + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -3076,6 +3100,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "radioTagDisclaimerTitle", "radioTagDisclaimerSubTitle", @@ -3364,6 +3390,8 @@ "saveAndAuthorize", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -3376,6 +3404,8 @@ "saveAndAuthorize", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "exposeToLastfmTitle", "exposeToLastfmSubTitle", "lastfmApiKey", @@ -3393,6 +3423,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "schedulePlaybackStopTimer", "alwaysAsk", @@ -3678,6 +3710,8 @@ "disconnectedFrom", "useMoreAnimationsTitle", "useMoreAnimationsDescription", + "showPositionDurationTitle", + "showPositionDurationDescription", "unPinAlbum", "schedulePlaybackStopTimer", "alwaysAsk",