From 25c3346941b12f392bd8ee673da05d13c56a1bb9 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 22 May 2025 07:26:25 +0530 Subject: [PATCH 1/2] feat: Replace theme dialog with segmented buttons (#82) Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- lib/settings/view/theme_settings_page.dart | 120 ++++++--------------- 1 file changed, 34 insertions(+), 86 deletions(-) diff --git a/lib/settings/view/theme_settings_page.dart b/lib/settings/view/theme_settings_page.dart index 0bb746b..315e4fa 100644 --- a/lib/settings/view/theme_settings_page.dart +++ b/lib/settings/view/theme_settings_page.dart @@ -30,48 +30,45 @@ class ThemeSettingsPage extends HookConsumerWidget { ), tiles: [ // choose system , light or dark theme - SettingsTile.navigation( + SettingsTile( title: const Text('Theme Mode'), - description: Text.rich( - TextSpan( - text: themeSettings.themeMode == ThemeMode.system - ? 'Using mode from ' - : 'Using ', - children: [ - TextSpan( - text: themeSettings.themeMode.pascalCase, - style: TextStyle( - color: primaryColor, - ), - ), - if (themeSettings.themeMode != ThemeMode.system) - const TextSpan(text: ' mode'), - ], - ), - ), - leading: const Icon(Icons.color_lens), - trailing: themeSettings.themeMode == ThemeMode.system - ? const Icon(Icons.auto_awesome) - : themeSettings.themeMode == ThemeMode.light - ? const Icon(Icons.light_mode) - : const Icon(Icons.dark_mode), - onPressed: (context) async { - final themeMode = await showDialog( - context: context, - builder: (context) { - return ModeSelectionDialog( - themeMode: themeSettings.themeMode, - ); - }, - ); - if (themeMode != null) { + description: SegmentedButton( + expandedInsets: const EdgeInsets.only(top: 8.0), + showSelectedIcon: true, + selectedIcon: const Icon(Icons.check), + selected: {themeSettings.themeMode}, + onSelectionChanged: (newSelection) { ref.read(appSettingsProvider.notifier).update( appSettings.copyWith.themeSettings( - themeMode: themeMode, + themeMode: newSelection.first, ), ); - } - }, + }, + segments: [ + ButtonSegment( + value: ThemeMode.light, + icon: Icon(Icons.light_mode), + label: const Text('Light'), + ), + ButtonSegment( + value: ThemeMode.system, + icon: Icon(Icons.auto_awesome), + label: const Text('System'), + ), + ButtonSegment( + value: ThemeMode.dark, + icon: Icon(Icons.dark_mode), + label: const Text('Dark'), + ), + ], + ), + leading: Icon( + themeSettings.themeMode == ThemeMode.light + ? Icons.light_mode + : themeSettings.themeMode == ThemeMode.dark + ? Icons.dark_mode + : Icons.auto_awesome, + ), ), // high contrast mode @@ -210,52 +207,3 @@ extension StringExtension on String { return Color(int.parse('0xff$substring(1)')); } } - -class ModeSelectionDialog extends HookConsumerWidget { - final ThemeMode themeMode; - - const ModeSelectionDialog({ - super.key, - required this.themeMode, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final selectedTheme = useState(themeMode); - // a wrap of chips to show the available modes with icons - return AlertDialog( - title: const Text('Select Theme Mode'), - content: Wrap( - spacing: 8.0, - runSpacing: 8.0, - children: ThemeMode.values - .map( - (mode) => ChoiceChip( - avatar: switch (mode) { - ThemeMode.system => const Icon(Icons.auto_awesome), - ThemeMode.light => const Icon(Icons.light_mode), - ThemeMode.dark => const Icon(Icons.dark_mode), - }, - showCheckmark: false, - label: Text(mode.pascalCase), - selected: mode == selectedTheme.value, - onSelected: (selected) { - if (selected) { - selectedTheme.value = mode; - } - }, - ), - ) - .toList(), - ), - actions: [ - CancelButton(), - OkButton( - onPressed: () { - Navigator.pop(context, selectedTheme.value); - }, - ), - ], - ); - } -} From 5c7be5cbe4e0ee96fa8ba46af4abc632e6f36ea1 Mon Sep 17 00:00:00 2001 From: "Dr.Blank" Date: Thu, 22 May 2025 08:24:59 +0530 Subject: [PATCH 2/2] feat: Add settings to control play button visibility on home shelves (#81) Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> --- lib/pages/home_page.dart | 16 + lib/router/constants.dart | 5 + lib/router/router.dart | 8 + lib/settings/models/app_settings.dart | 14 + lib/settings/models/app_settings.freezed.dart | 295 +++++++++++++++++- lib/settings/models/app_settings.g.dart | 31 ++ lib/settings/view/app_settings_page.dart | 10 + .../view/home_page_settings_page.dart | 103 ++++++ lib/shared/widgets/shelves/book_shelf.dart | 3 + lib/shared/widgets/shelves/home_shelf.dart | 3 + 10 files changed, 481 insertions(+), 7 deletions(-) create mode 100644 lib/settings/view/home_page_settings_page.dart diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index f9b0310..3ba1d98 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -6,6 +6,8 @@ import 'package:vaani/api/api_provider.dart'; import 'package:vaani/main.dart'; import 'package:vaani/router/router.dart'; import 'package:vaani/settings/api_settings_provider.dart'; +import 'package:vaani/settings/app_settings_provider.dart' + show appSettingsProvider; import '../shared/widgets/shelves/home_shelf.dart'; @@ -17,6 +19,8 @@ class HomePage extends HookConsumerWidget { final views = ref.watch(personalizedViewProvider); final apiSettings = ref.watch(apiSettingsProvider); final scrollController = useScrollController(); + final appSettings = ref.watch(appSettingsProvider); + final homePageSettings = appSettings.homePageSettings; return Scaffold( appBar: AppBar( title: GestureDetector( @@ -63,9 +67,21 @@ class HomePage extends HookConsumerWidget { // .where((element) => !element.id.contains('discover')) .map((shelf) { appLogger.fine('building shelf ${shelf.label}'); + // check if showPlayButton is enabled for the shelf + // using the id of the shelf + final showPlayButton = switch (shelf.id) { + 'continue-listening' => + homePageSettings.showPlayButtonOnContinueListeningShelf, + 'continue-series' => + homePageSettings.showPlayButtonOnContinueSeriesShelf, + 'listen-again' => + homePageSettings.showPlayButtonOnListenAgainShelf, + _ => homePageSettings.showPlayButtonOnAllRemainingShelves, + }; return HomeShelf( title: shelf.label, shelf: shelf, + showPlayButton: showPlayButton, ); }).toList(); return RefreshIndicator( diff --git a/lib/router/constants.dart b/lib/router/constants.dart index f36d706..79c4556 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -52,6 +52,11 @@ class Routes { name: 'shakeDetectorSettings', parentRoute: settings, ); + static const homePageSettings = _SimpleRoute( + pathName: 'homePage', + name: 'homePageSettings', + parentRoute: settings, + ); // search and explore static const search = _SimpleRoute( diff --git a/lib/router/router.dart b/lib/router/router.dart index 5e9f71e..eda348e 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -18,6 +18,7 @@ import 'package:vaani/settings/view/notification_settings_page.dart'; import 'package:vaani/settings/view/player_settings_page.dart'; import 'package:vaani/settings/view/shake_detector_settings_page.dart'; import 'package:vaani/settings/view/theme_settings_page.dart'; +import 'package:vaani/settings/view/home_page_settings_page.dart'; import 'scaffold_with_nav_bar.dart'; import 'transitions/slide.dart'; @@ -213,6 +214,13 @@ class MyAppRouter { const ShakeDetectorSettingsPage(), ), ), + GoRoute( + path: Routes.homePageSettings.pathName, + name: Routes.homePageSettings.name, + pageBuilder: defaultPageBuilder( + const HomePageSettingsPage(), + ), + ), ], ), GoRoute( diff --git a/lib/settings/models/app_settings.dart b/lib/settings/models/app_settings.dart index e486ac4..fe1f7be 100644 --- a/lib/settings/models/app_settings.dart +++ b/lib/settings/models/app_settings.dart @@ -19,6 +19,7 @@ class AppSettings with _$AppSettings { @Default(NotificationSettings()) NotificationSettings notificationSettings, @Default(ShakeDetectionSettings()) ShakeDetectionSettings shakeDetectionSettings, + @Default(HomePageSettings()) HomePageSettings homePageSettings, }) = _AppSettings; factory AppSettings.fromJson(Map json) => @@ -230,3 +231,16 @@ enum ShakeAction { } enum ShakeDetectedFeedback { vibrate, beep } + +@freezed +class HomePageSettings with _$HomePageSettings { + const factory HomePageSettings({ + @Default(true) bool showPlayButtonOnContinueListeningShelf, + @Default(false) bool showPlayButtonOnContinueSeriesShelf, + @Default(false) bool showPlayButtonOnAllRemainingShelves, + @Default(false) bool showPlayButtonOnListenAgainShelf, + }) = _HomePageSettings; + + factory HomePageSettings.fromJson(Map json) => + _$HomePageSettingsFromJson(json); +} diff --git a/lib/settings/models/app_settings.freezed.dart b/lib/settings/models/app_settings.freezed.dart index fc52047..17dea47 100644 --- a/lib/settings/models/app_settings.freezed.dart +++ b/lib/settings/models/app_settings.freezed.dart @@ -29,6 +29,7 @@ mixin _$AppSettings { throw _privateConstructorUsedError; ShakeDetectionSettings get shakeDetectionSettings => throw _privateConstructorUsedError; + HomePageSettings get homePageSettings => throw _privateConstructorUsedError; /// Serializes this AppSettings to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -52,7 +53,8 @@ abstract class $AppSettingsCopyWith<$Res> { SleepTimerSettings sleepTimerSettings, DownloadSettings downloadSettings, NotificationSettings notificationSettings, - ShakeDetectionSettings shakeDetectionSettings}); + ShakeDetectionSettings shakeDetectionSettings, + HomePageSettings homePageSettings}); $ThemeSettingsCopyWith<$Res> get themeSettings; $PlayerSettingsCopyWith<$Res> get playerSettings; @@ -60,6 +62,7 @@ abstract class $AppSettingsCopyWith<$Res> { $DownloadSettingsCopyWith<$Res> get downloadSettings; $NotificationSettingsCopyWith<$Res> get notificationSettings; $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; + $HomePageSettingsCopyWith<$Res> get homePageSettings; } /// @nodoc @@ -83,6 +86,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> Object? downloadSettings = null, Object? notificationSettings = null, Object? shakeDetectionSettings = null, + Object? homePageSettings = null, }) { return _then(_value.copyWith( themeSettings: null == themeSettings @@ -109,6 +113,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> ? _value.shakeDetectionSettings : shakeDetectionSettings // ignore: cast_nullable_to_non_nullable as ShakeDetectionSettings, + homePageSettings: null == homePageSettings + ? _value.homePageSettings + : homePageSettings // ignore: cast_nullable_to_non_nullable + as HomePageSettings, ) as $Val); } @@ -174,6 +182,16 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings> return _then(_value.copyWith(shakeDetectionSettings: value) as $Val); }); } + + /// Create a copy of AppSettings + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $HomePageSettingsCopyWith<$Res> get homePageSettings { + return $HomePageSettingsCopyWith<$Res>(_value.homePageSettings, (value) { + return _then(_value.copyWith(homePageSettings: value) as $Val); + }); + } } /// @nodoc @@ -190,7 +208,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> SleepTimerSettings sleepTimerSettings, DownloadSettings downloadSettings, NotificationSettings notificationSettings, - ShakeDetectionSettings shakeDetectionSettings}); + ShakeDetectionSettings shakeDetectionSettings, + HomePageSettings homePageSettings}); @override $ThemeSettingsCopyWith<$Res> get themeSettings; @@ -204,6 +223,8 @@ abstract class _$$AppSettingsImplCopyWith<$Res> $NotificationSettingsCopyWith<$Res> get notificationSettings; @override $ShakeDetectionSettingsCopyWith<$Res> get shakeDetectionSettings; + @override + $HomePageSettingsCopyWith<$Res> get homePageSettings; } /// @nodoc @@ -225,6 +246,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res> Object? downloadSettings = null, Object? notificationSettings = null, Object? shakeDetectionSettings = null, + Object? homePageSettings = null, }) { return _then(_$AppSettingsImpl( themeSettings: null == themeSettings @@ -251,6 +273,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res> ? _value.shakeDetectionSettings : shakeDetectionSettings // ignore: cast_nullable_to_non_nullable as ShakeDetectionSettings, + homePageSettings: null == homePageSettings + ? _value.homePageSettings + : homePageSettings // ignore: cast_nullable_to_non_nullable + as HomePageSettings, )); } } @@ -264,7 +290,8 @@ class _$AppSettingsImpl implements _AppSettings { this.sleepTimerSettings = const SleepTimerSettings(), this.downloadSettings = const DownloadSettings(), this.notificationSettings = const NotificationSettings(), - this.shakeDetectionSettings = const ShakeDetectionSettings()}); + this.shakeDetectionSettings = const ShakeDetectionSettings(), + this.homePageSettings = const HomePageSettings()}); factory _$AppSettingsImpl.fromJson(Map json) => _$$AppSettingsImplFromJson(json); @@ -287,10 +314,13 @@ class _$AppSettingsImpl implements _AppSettings { @override @JsonKey() final ShakeDetectionSettings shakeDetectionSettings; + @override + @JsonKey() + final HomePageSettings homePageSettings; @override String toString() { - return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, sleepTimerSettings: $sleepTimerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings)'; + return 'AppSettings(themeSettings: $themeSettings, playerSettings: $playerSettings, sleepTimerSettings: $sleepTimerSettings, downloadSettings: $downloadSettings, notificationSettings: $notificationSettings, shakeDetectionSettings: $shakeDetectionSettings, homePageSettings: $homePageSettings)'; } @override @@ -309,7 +339,9 @@ class _$AppSettingsImpl implements _AppSettings { (identical(other.notificationSettings, notificationSettings) || other.notificationSettings == notificationSettings) && (identical(other.shakeDetectionSettings, shakeDetectionSettings) || - other.shakeDetectionSettings == shakeDetectionSettings)); + other.shakeDetectionSettings == shakeDetectionSettings) && + (identical(other.homePageSettings, homePageSettings) || + other.homePageSettings == homePageSettings)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -321,7 +353,8 @@ class _$AppSettingsImpl implements _AppSettings { sleepTimerSettings, downloadSettings, notificationSettings, - shakeDetectionSettings); + shakeDetectionSettings, + homePageSettings); /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -346,7 +379,8 @@ abstract class _AppSettings implements AppSettings { final SleepTimerSettings sleepTimerSettings, final DownloadSettings downloadSettings, final NotificationSettings notificationSettings, - final ShakeDetectionSettings shakeDetectionSettings}) = _$AppSettingsImpl; + final ShakeDetectionSettings shakeDetectionSettings, + final HomePageSettings homePageSettings}) = _$AppSettingsImpl; factory _AppSettings.fromJson(Map json) = _$AppSettingsImpl.fromJson; @@ -363,6 +397,8 @@ abstract class _AppSettings implements AppSettings { NotificationSettings get notificationSettings; @override ShakeDetectionSettings get shakeDetectionSettings; + @override + HomePageSettings get homePageSettings; /// Create a copy of AppSettings /// with the given fields replaced by the non-null parameter values. @@ -2827,3 +2863,248 @@ abstract class _ShakeDetectionSettings implements ShakeDetectionSettings { _$$ShakeDetectionSettingsImplCopyWith<_$ShakeDetectionSettingsImpl> get copyWith => throw _privateConstructorUsedError; } + +HomePageSettings _$HomePageSettingsFromJson(Map json) { + return _HomePageSettings.fromJson(json); +} + +/// @nodoc +mixin _$HomePageSettings { + bool get showPlayButtonOnContinueListeningShelf => + throw _privateConstructorUsedError; + bool get showPlayButtonOnContinueSeriesShelf => + throw _privateConstructorUsedError; + bool get showPlayButtonOnAllRemainingShelves => + throw _privateConstructorUsedError; + bool get showPlayButtonOnListenAgainShelf => + throw _privateConstructorUsedError; + + /// Serializes this HomePageSettings to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of HomePageSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $HomePageSettingsCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $HomePageSettingsCopyWith<$Res> { + factory $HomePageSettingsCopyWith( + HomePageSettings value, $Res Function(HomePageSettings) then) = + _$HomePageSettingsCopyWithImpl<$Res, HomePageSettings>; + @useResult + $Res call( + {bool showPlayButtonOnContinueListeningShelf, + bool showPlayButtonOnContinueSeriesShelf, + bool showPlayButtonOnAllRemainingShelves, + bool showPlayButtonOnListenAgainShelf}); +} + +/// @nodoc +class _$HomePageSettingsCopyWithImpl<$Res, $Val extends HomePageSettings> + implements $HomePageSettingsCopyWith<$Res> { + _$HomePageSettingsCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of HomePageSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? showPlayButtonOnContinueListeningShelf = null, + Object? showPlayButtonOnContinueSeriesShelf = null, + Object? showPlayButtonOnAllRemainingShelves = null, + Object? showPlayButtonOnListenAgainShelf = null, + }) { + return _then(_value.copyWith( + showPlayButtonOnContinueListeningShelf: null == + showPlayButtonOnContinueListeningShelf + ? _value.showPlayButtonOnContinueListeningShelf + : showPlayButtonOnContinueListeningShelf // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnContinueSeriesShelf: null == + showPlayButtonOnContinueSeriesShelf + ? _value.showPlayButtonOnContinueSeriesShelf + : showPlayButtonOnContinueSeriesShelf // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnAllRemainingShelves: null == + showPlayButtonOnAllRemainingShelves + ? _value.showPlayButtonOnAllRemainingShelves + : showPlayButtonOnAllRemainingShelves // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnListenAgainShelf: null == showPlayButtonOnListenAgainShelf + ? _value.showPlayButtonOnListenAgainShelf + : showPlayButtonOnListenAgainShelf // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$HomePageSettingsImplCopyWith<$Res> + implements $HomePageSettingsCopyWith<$Res> { + factory _$$HomePageSettingsImplCopyWith(_$HomePageSettingsImpl value, + $Res Function(_$HomePageSettingsImpl) then) = + __$$HomePageSettingsImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {bool showPlayButtonOnContinueListeningShelf, + bool showPlayButtonOnContinueSeriesShelf, + bool showPlayButtonOnAllRemainingShelves, + bool showPlayButtonOnListenAgainShelf}); +} + +/// @nodoc +class __$$HomePageSettingsImplCopyWithImpl<$Res> + extends _$HomePageSettingsCopyWithImpl<$Res, _$HomePageSettingsImpl> + implements _$$HomePageSettingsImplCopyWith<$Res> { + __$$HomePageSettingsImplCopyWithImpl(_$HomePageSettingsImpl _value, + $Res Function(_$HomePageSettingsImpl) _then) + : super(_value, _then); + + /// Create a copy of HomePageSettings + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? showPlayButtonOnContinueListeningShelf = null, + Object? showPlayButtonOnContinueSeriesShelf = null, + Object? showPlayButtonOnAllRemainingShelves = null, + Object? showPlayButtonOnListenAgainShelf = null, + }) { + return _then(_$HomePageSettingsImpl( + showPlayButtonOnContinueListeningShelf: null == + showPlayButtonOnContinueListeningShelf + ? _value.showPlayButtonOnContinueListeningShelf + : showPlayButtonOnContinueListeningShelf // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnContinueSeriesShelf: null == + showPlayButtonOnContinueSeriesShelf + ? _value.showPlayButtonOnContinueSeriesShelf + : showPlayButtonOnContinueSeriesShelf // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnAllRemainingShelves: null == + showPlayButtonOnAllRemainingShelves + ? _value.showPlayButtonOnAllRemainingShelves + : showPlayButtonOnAllRemainingShelves // ignore: cast_nullable_to_non_nullable + as bool, + showPlayButtonOnListenAgainShelf: null == showPlayButtonOnListenAgainShelf + ? _value.showPlayButtonOnListenAgainShelf + : showPlayButtonOnListenAgainShelf // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$HomePageSettingsImpl implements _HomePageSettings { + const _$HomePageSettingsImpl( + {this.showPlayButtonOnContinueListeningShelf = true, + this.showPlayButtonOnContinueSeriesShelf = false, + this.showPlayButtonOnAllRemainingShelves = false, + this.showPlayButtonOnListenAgainShelf = false}); + + factory _$HomePageSettingsImpl.fromJson(Map json) => + _$$HomePageSettingsImplFromJson(json); + + @override + @JsonKey() + final bool showPlayButtonOnContinueListeningShelf; + @override + @JsonKey() + final bool showPlayButtonOnContinueSeriesShelf; + @override + @JsonKey() + final bool showPlayButtonOnAllRemainingShelves; + @override + @JsonKey() + final bool showPlayButtonOnListenAgainShelf; + + @override + String toString() { + return 'HomePageSettings(showPlayButtonOnContinueListeningShelf: $showPlayButtonOnContinueListeningShelf, showPlayButtonOnContinueSeriesShelf: $showPlayButtonOnContinueSeriesShelf, showPlayButtonOnAllRemainingShelves: $showPlayButtonOnAllRemainingShelves, showPlayButtonOnListenAgainShelf: $showPlayButtonOnListenAgainShelf)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$HomePageSettingsImpl && + (identical(other.showPlayButtonOnContinueListeningShelf, + showPlayButtonOnContinueListeningShelf) || + other.showPlayButtonOnContinueListeningShelf == + showPlayButtonOnContinueListeningShelf) && + (identical(other.showPlayButtonOnContinueSeriesShelf, + showPlayButtonOnContinueSeriesShelf) || + other.showPlayButtonOnContinueSeriesShelf == + showPlayButtonOnContinueSeriesShelf) && + (identical(other.showPlayButtonOnAllRemainingShelves, + showPlayButtonOnAllRemainingShelves) || + other.showPlayButtonOnAllRemainingShelves == + showPlayButtonOnAllRemainingShelves) && + (identical(other.showPlayButtonOnListenAgainShelf, + showPlayButtonOnListenAgainShelf) || + other.showPlayButtonOnListenAgainShelf == + showPlayButtonOnListenAgainShelf)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + showPlayButtonOnContinueListeningShelf, + showPlayButtonOnContinueSeriesShelf, + showPlayButtonOnAllRemainingShelves, + showPlayButtonOnListenAgainShelf); + + /// Create a copy of HomePageSettings + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$HomePageSettingsImplCopyWith<_$HomePageSettingsImpl> get copyWith => + __$$HomePageSettingsImplCopyWithImpl<_$HomePageSettingsImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$HomePageSettingsImplToJson( + this, + ); + } +} + +abstract class _HomePageSettings implements HomePageSettings { + const factory _HomePageSettings( + {final bool showPlayButtonOnContinueListeningShelf, + final bool showPlayButtonOnContinueSeriesShelf, + final bool showPlayButtonOnAllRemainingShelves, + final bool showPlayButtonOnListenAgainShelf}) = _$HomePageSettingsImpl; + + factory _HomePageSettings.fromJson(Map json) = + _$HomePageSettingsImpl.fromJson; + + @override + bool get showPlayButtonOnContinueListeningShelf; + @override + bool get showPlayButtonOnContinueSeriesShelf; + @override + bool get showPlayButtonOnAllRemainingShelves; + @override + bool get showPlayButtonOnListenAgainShelf; + + /// Create a copy of HomePageSettings + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$HomePageSettingsImplCopyWith<_$HomePageSettingsImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/lib/settings/models/app_settings.g.dart b/lib/settings/models/app_settings.g.dart index 45bb74b..131458c 100644 --- a/lib/settings/models/app_settings.g.dart +++ b/lib/settings/models/app_settings.g.dart @@ -32,6 +32,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map json) => ? const ShakeDetectionSettings() : ShakeDetectionSettings.fromJson( json['shakeDetectionSettings'] as Map), + homePageSettings: json['homePageSettings'] == null + ? const HomePageSettings() + : HomePageSettings.fromJson( + json['homePageSettings'] as Map), ); Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => @@ -42,6 +46,7 @@ Map _$$AppSettingsImplToJson(_$AppSettingsImpl instance) => 'downloadSettings': instance.downloadSettings, 'notificationSettings': instance.notificationSettings, 'shakeDetectionSettings': instance.shakeDetectionSettings, + 'homePageSettings': instance.homePageSettings, }; _$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map json) => @@ -351,3 +356,29 @@ const _$ShakeDetectedFeedbackEnumMap = { ShakeDetectedFeedback.vibrate: 'vibrate', ShakeDetectedFeedback.beep: 'beep', }; + +_$HomePageSettingsImpl _$$HomePageSettingsImplFromJson( + Map json) => + _$HomePageSettingsImpl( + showPlayButtonOnContinueListeningShelf: + json['showPlayButtonOnContinueListeningShelf'] as bool? ?? true, + showPlayButtonOnContinueSeriesShelf: + json['showPlayButtonOnContinueSeriesShelf'] as bool? ?? false, + showPlayButtonOnAllRemainingShelves: + json['showPlayButtonOnAllRemainingShelves'] as bool? ?? false, + showPlayButtonOnListenAgainShelf: + json['showPlayButtonOnListenAgainShelf'] as bool? ?? false, + ); + +Map _$$HomePageSettingsImplToJson( + _$HomePageSettingsImpl instance) => + { + 'showPlayButtonOnContinueListeningShelf': + instance.showPlayButtonOnContinueListeningShelf, + 'showPlayButtonOnContinueSeriesShelf': + instance.showPlayButtonOnContinueSeriesShelf, + 'showPlayButtonOnAllRemainingShelves': + instance.showPlayButtonOnAllRemainingShelves, + 'showPlayButtonOnListenAgainShelf': + instance.showPlayButtonOnListenAgainShelf, + }; diff --git a/lib/settings/view/app_settings_page.dart b/lib/settings/view/app_settings_page.dart index aebe867..15386fe 100644 --- a/lib/settings/view/app_settings_page.dart +++ b/lib/settings/view/app_settings_page.dart @@ -120,6 +120,16 @@ class AppSettingsPage extends HookConsumerWidget { context.pushNamed(Routes.notificationSettings.name); }, ), + SettingsTile.navigation( + leading: const Icon(Icons.home_filled), + title: const Text('Home Page Settings'), + description: const Text( + 'Customize the home page', + ), + onPressed: (context) { + context.pushNamed(Routes.homePageSettings.name); + }, + ), ], ), diff --git a/lib/settings/view/home_page_settings_page.dart b/lib/settings/view/home_page_settings_page.dart new file mode 100644 index 0000000..327044d --- /dev/null +++ b/lib/settings/view/home_page_settings_page.dart @@ -0,0 +1,103 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:flutter_settings_ui/flutter_settings_ui.dart'; +import 'package:vaani/settings/app_settings_provider.dart'; +import 'package:vaani/settings/view/simple_settings_page.dart' + show SimpleSettingsPage; + +class HomePageSettingsPage extends HookConsumerWidget { + const HomePageSettingsPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final appSettings = ref.watch(appSettingsProvider); + final appSettingsNotifier = ref.read(appSettingsProvider.notifier); + + return SimpleSettingsPage( + title: Text('Home Page Settings'), + sections: [ + SettingsSection( + title: const Text('Quick Play'), + margin: const EdgeInsetsDirectional.symmetric( + horizontal: 16.0, + vertical: 8.0, + ), + tiles: [ + SettingsTile.switchTile( + initialValue: appSettings + .homePageSettings.showPlayButtonOnContinueListeningShelf, + title: const Text('Continue Listening'), + leading: const Icon(Icons.play_arrow), + description: const Text( + 'Show play button for books in currently listening shelf', + ), + onToggle: (value) { + appSettingsNotifier.update( + appSettings.copyWith( + homePageSettings: appSettings.homePageSettings.copyWith( + showPlayButtonOnContinueListeningShelf: value, + ), + ), + ); + }, + ), + SettingsTile.switchTile( + title: const Text('Continue Series'), + leading: const Icon(Icons.play_arrow), + description: const Text( + 'Show play button for books in continue series shelf', + ), + initialValue: appSettings + .homePageSettings.showPlayButtonOnContinueSeriesShelf, + onToggle: (value) { + appSettingsNotifier.update( + appSettings.copyWith( + homePageSettings: appSettings.homePageSettings.copyWith( + showPlayButtonOnContinueSeriesShelf: value, + ), + ), + ); + }, + ), + SettingsTile.switchTile( + title: const Text('Other shelves'), + leading: const Icon(Icons.all_inclusive), + description: const Text( + 'Show play button for all books in all remaining shelves', + ), + initialValue: appSettings + .homePageSettings.showPlayButtonOnAllRemainingShelves, + onToggle: (value) { + appSettingsNotifier.update( + appSettings.copyWith( + homePageSettings: appSettings.homePageSettings.copyWith( + showPlayButtonOnAllRemainingShelves: value, + ), + ), + ); + }, + ), + SettingsTile.switchTile( + title: const Text('Listen Again'), + leading: const Icon(Icons.replay), + description: const Text( + 'Show play button for all books in listen again shelf', + ), + initialValue: + appSettings.homePageSettings.showPlayButtonOnListenAgainShelf, + onToggle: (value) { + appSettingsNotifier.update( + appSettings.copyWith( + homePageSettings: appSettings.homePageSettings.copyWith( + showPlayButtonOnListenAgainShelf: value, + ), + ), + ); + }, + ), + ], + ), + ], + ); + } +} diff --git a/lib/shared/widgets/shelves/book_shelf.dart b/lib/shared/widgets/shelves/book_shelf.dart index 4490b99..4fad4be 100644 --- a/lib/shared/widgets/shelves/book_shelf.dart +++ b/lib/shared/widgets/shelves/book_shelf.dart @@ -25,10 +25,12 @@ class BookHomeShelf extends HookConsumerWidget { super.key, required this.shelf, required this.title, + this.showPlayButton = false, }); final String title; final LibraryItemShelf shelf; + final bool showPlayButton; @override Widget build(BuildContext context, WidgetRef ref) { @@ -41,6 +43,7 @@ class BookHomeShelf extends HookConsumerWidget { item: item, key: ValueKey(shelf.id + item.id), heroTagSuffix: shelf.id, + showPlayButton: showPlayButton, ), _ => Container(), }, diff --git a/lib/shared/widgets/shelves/home_shelf.dart b/lib/shared/widgets/shelves/home_shelf.dart index ed22f8d..9a59a54 100644 --- a/lib/shared/widgets/shelves/home_shelf.dart +++ b/lib/shared/widgets/shelves/home_shelf.dart @@ -15,10 +15,12 @@ class HomeShelf extends HookConsumerWidget { super.key, required this.shelf, required this.title, + this.showPlayButton = false, }); final String title; final Shelf shelf; + final bool showPlayButton; @override Widget build(BuildContext context, WidgetRef ref) { @@ -26,6 +28,7 @@ class HomeShelf extends HookConsumerWidget { ShelfType.book => BookHomeShelf( title: title, shelf: shelf.asLibraryItemShelf, + showPlayButton: showPlayButton, ), ShelfType.authors => AuthorHomeShelf( title: title,