Compare commits

...

2 commits

Author SHA1 Message Date
Dr.Blank
5c7be5cbe4
feat: Add settings to control play button visibility on home shelves (#81)
Some checks failed
Flutter CI & Release / Test (push) Has been cancelled
Flutter CI & Release / Build Android APKs (push) Has been cancelled
Flutter CI & Release / build_linux (push) Has been cancelled
Flutter CI & Release / Create GitHub Release (push) Has been cancelled
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-05-22 08:24:59 +05:30
Dr.Blank
25c3346941
feat: Replace theme dialog with segmented buttons (#82)
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
2025-05-22 07:26:25 +05:30
11 changed files with 515 additions and 93 deletions

View file

@ -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(

View file

@ -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(

View file

@ -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(

View file

@ -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<String, dynamic> 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<String, dynamic> json) =>
_$HomePageSettingsFromJson(json);
}

View file

@ -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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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<HomePageSettings> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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;
}

View file

@ -32,6 +32,10 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map<String, dynamic> json) =>
? const ShakeDetectionSettings()
: ShakeDetectionSettings.fromJson(
json['shakeDetectionSettings'] as Map<String, dynamic>),
homePageSettings: json['homePageSettings'] == null
? const HomePageSettings()
: HomePageSettings.fromJson(
json['homePageSettings'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
@ -42,6 +46,7 @@ Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
'downloadSettings': instance.downloadSettings,
'notificationSettings': instance.notificationSettings,
'shakeDetectionSettings': instance.shakeDetectionSettings,
'homePageSettings': instance.homePageSettings,
};
_$ThemeSettingsImpl _$$ThemeSettingsImplFromJson(Map<String, dynamic> json) =>
@ -351,3 +356,29 @@ const _$ShakeDetectedFeedbackEnumMap = {
ShakeDetectedFeedback.vibrate: 'vibrate',
ShakeDetectedFeedback.beep: 'beep',
};
_$HomePageSettingsImpl _$$HomePageSettingsImplFromJson(
Map<String, dynamic> 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<String, dynamic> _$$HomePageSettingsImplToJson(
_$HomePageSettingsImpl instance) =>
<String, dynamic>{
'showPlayButtonOnContinueListeningShelf':
instance.showPlayButtonOnContinueListeningShelf,
'showPlayButtonOnContinueSeriesShelf':
instance.showPlayButtonOnContinueSeriesShelf,
'showPlayButtonOnAllRemainingShelves':
instance.showPlayButtonOnAllRemainingShelves,
'showPlayButtonOnListenAgainShelf':
instance.showPlayButtonOnListenAgainShelf,
};

View file

@ -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);
},
),
],
),

View file

@ -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,
),
),
);
},
),
],
),
],
);
}
}

View file

@ -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<ThemeMode>(
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);
},
),
],
);
}
}

View file

@ -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(),
},

View file

@ -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,