mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2025-12-23 11:29:30 +00:00
downloads and offline playback
This commit is contained in:
parent
1c95d1e4bb
commit
c24541f1cd
38 changed files with 1590 additions and 109 deletions
|
|
@ -6,7 +6,7 @@ part of 'api_settings_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$apiSettingsHash() => r'b009ae0d14203a15abaa497287fc68f57eb86bde';
|
||||
String _$apiSettingsHash() => r'26e7e09e7369bac9fbf0589da9fd97d1f15b7926';
|
||||
|
||||
/// See also [ApiSettings].
|
||||
@ProviderFor(ApiSettings)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,20 @@ final _box = AvailableHiveBoxes.userPrefsBox;
|
|||
|
||||
final _logger = Logger('AppSettingsProvider');
|
||||
|
||||
model.AppSettings readFromBoxOrCreate() {
|
||||
// see if the settings are already in the box
|
||||
if (_box.isNotEmpty) {
|
||||
final foundSettings = _box.getAt(0);
|
||||
_logger.fine('found settings in box: $foundSettings');
|
||||
return foundSettings;
|
||||
} else {
|
||||
// create a new settings object
|
||||
const settings = model.AppSettings();
|
||||
_logger.fine('created new settings: $settings');
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class AppSettings extends _$AppSettings {
|
||||
@override
|
||||
|
|
@ -22,20 +36,6 @@ class AppSettings extends _$AppSettings {
|
|||
return state;
|
||||
}
|
||||
|
||||
model.AppSettings readFromBoxOrCreate() {
|
||||
// see if the settings are already in the box
|
||||
if (_box.isNotEmpty) {
|
||||
final foundSettings = _box.getAt(0);
|
||||
_logger.fine('found settings in box: $foundSettings');
|
||||
return foundSettings;
|
||||
} else {
|
||||
// create a new settings object
|
||||
const settings = model.AppSettings();
|
||||
_logger.fine('created new settings: $settings');
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
// write the settings to the box
|
||||
void writeToBox() {
|
||||
_box.clear();
|
||||
|
|
@ -50,4 +50,8 @@ class AppSettings extends _$AppSettings {
|
|||
void updateState(model.AppSettings newSettings) {
|
||||
state = newSettings;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
state = const model.AppSettings();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'app_settings_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$appSettingsHash() => r'6716bc568850ffd373fd8572c5781beefafbb9ee';
|
||||
String _$appSettingsHash() => r'99bd35aff3c02252a4013c674fd885e841a7f703';
|
||||
|
||||
/// See also [AppSettings].
|
||||
@ProviderFor(AppSettings)
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ part 'app_settings.g.dart';
|
|||
class AppSettings with _$AppSettings {
|
||||
const factory AppSettings({
|
||||
@Default(true) bool isDarkMode,
|
||||
@Default(false) bool useMaterialThemeOnItemPage,
|
||||
@Default(true) bool useMaterialThemeOnItemPage,
|
||||
@Default(PlayerSettings()) PlayerSettings playerSettings,
|
||||
@Default(DownloadSettings()) DownloadSettings downloadSettings,
|
||||
}) = _AppSettings;
|
||||
|
||||
factory AppSettings.fromJson(Map<String, dynamic> json) =>
|
||||
|
|
@ -105,3 +106,18 @@ class SleepTimerSettings with _$SleepTimerSettings {
|
|||
factory SleepTimerSettings.fromJson(Map<String, dynamic> json) =>
|
||||
_$SleepTimerSettingsFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
class DownloadSettings with _$DownloadSettings {
|
||||
const factory DownloadSettings({
|
||||
@Default(true) bool requiresWiFi,
|
||||
@Default(3) int retries,
|
||||
@Default(true) bool allowPause,
|
||||
@Default(3) int maxConcurrent,
|
||||
@Default(3) int maxConcurrentByHost,
|
||||
@Default(3) int maxConcurrentByGroup,
|
||||
}) = _DownloadSettings;
|
||||
|
||||
factory DownloadSettings.fromJson(Map<String, dynamic> json) =>
|
||||
_$DownloadSettingsFromJson(json);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ mixin _$AppSettings {
|
|||
bool get isDarkMode => throw _privateConstructorUsedError;
|
||||
bool get useMaterialThemeOnItemPage => throw _privateConstructorUsedError;
|
||||
PlayerSettings get playerSettings => throw _privateConstructorUsedError;
|
||||
DownloadSettings get downloadSettings => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
|
|
@ -39,9 +40,11 @@ abstract class $AppSettingsCopyWith<$Res> {
|
|||
$Res call(
|
||||
{bool isDarkMode,
|
||||
bool useMaterialThemeOnItemPage,
|
||||
PlayerSettings playerSettings});
|
||||
PlayerSettings playerSettings,
|
||||
DownloadSettings downloadSettings});
|
||||
|
||||
$PlayerSettingsCopyWith<$Res> get playerSettings;
|
||||
$DownloadSettingsCopyWith<$Res> get downloadSettings;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
|
@ -60,6 +63,7 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
|
|||
Object? isDarkMode = null,
|
||||
Object? useMaterialThemeOnItemPage = null,
|
||||
Object? playerSettings = null,
|
||||
Object? downloadSettings = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
isDarkMode: null == isDarkMode
|
||||
|
|
@ -74,6 +78,10 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
|
|||
? _value.playerSettings
|
||||
: playerSettings // ignore: cast_nullable_to_non_nullable
|
||||
as PlayerSettings,
|
||||
downloadSettings: null == downloadSettings
|
||||
? _value.downloadSettings
|
||||
: downloadSettings // ignore: cast_nullable_to_non_nullable
|
||||
as DownloadSettings,
|
||||
) as $Val);
|
||||
}
|
||||
|
||||
|
|
@ -84,6 +92,14 @@ class _$AppSettingsCopyWithImpl<$Res, $Val extends AppSettings>
|
|||
return _then(_value.copyWith(playerSettings: value) as $Val);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DownloadSettingsCopyWith<$Res> get downloadSettings {
|
||||
return $DownloadSettingsCopyWith<$Res>(_value.downloadSettings, (value) {
|
||||
return _then(_value.copyWith(downloadSettings: value) as $Val);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
|
@ -97,10 +113,13 @@ abstract class _$$AppSettingsImplCopyWith<$Res>
|
|||
$Res call(
|
||||
{bool isDarkMode,
|
||||
bool useMaterialThemeOnItemPage,
|
||||
PlayerSettings playerSettings});
|
||||
PlayerSettings playerSettings,
|
||||
DownloadSettings downloadSettings});
|
||||
|
||||
@override
|
||||
$PlayerSettingsCopyWith<$Res> get playerSettings;
|
||||
@override
|
||||
$DownloadSettingsCopyWith<$Res> get downloadSettings;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
|
@ -117,6 +136,7 @@ class __$$AppSettingsImplCopyWithImpl<$Res>
|
|||
Object? isDarkMode = null,
|
||||
Object? useMaterialThemeOnItemPage = null,
|
||||
Object? playerSettings = null,
|
||||
Object? downloadSettings = null,
|
||||
}) {
|
||||
return _then(_$AppSettingsImpl(
|
||||
isDarkMode: null == isDarkMode
|
||||
|
|
@ -131,6 +151,10 @@ class __$$AppSettingsImplCopyWithImpl<$Res>
|
|||
? _value.playerSettings
|
||||
: playerSettings // ignore: cast_nullable_to_non_nullable
|
||||
as PlayerSettings,
|
||||
downloadSettings: null == downloadSettings
|
||||
? _value.downloadSettings
|
||||
: downloadSettings // ignore: cast_nullable_to_non_nullable
|
||||
as DownloadSettings,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -140,8 +164,9 @@ class __$$AppSettingsImplCopyWithImpl<$Res>
|
|||
class _$AppSettingsImpl implements _AppSettings {
|
||||
const _$AppSettingsImpl(
|
||||
{this.isDarkMode = true,
|
||||
this.useMaterialThemeOnItemPage = false,
|
||||
this.playerSettings = const PlayerSettings()});
|
||||
this.useMaterialThemeOnItemPage = true,
|
||||
this.playerSettings = const PlayerSettings(),
|
||||
this.downloadSettings = const DownloadSettings()});
|
||||
|
||||
factory _$AppSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$AppSettingsImplFromJson(json);
|
||||
|
|
@ -155,10 +180,13 @@ class _$AppSettingsImpl implements _AppSettings {
|
|||
@override
|
||||
@JsonKey()
|
||||
final PlayerSettings playerSettings;
|
||||
@override
|
||||
@JsonKey()
|
||||
final DownloadSettings downloadSettings;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettings(isDarkMode: $isDarkMode, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, playerSettings: $playerSettings)';
|
||||
return 'AppSettings(isDarkMode: $isDarkMode, useMaterialThemeOnItemPage: $useMaterialThemeOnItemPage, playerSettings: $playerSettings, downloadSettings: $downloadSettings)';
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -173,13 +201,15 @@ class _$AppSettingsImpl implements _AppSettings {
|
|||
other.useMaterialThemeOnItemPage ==
|
||||
useMaterialThemeOnItemPage) &&
|
||||
(identical(other.playerSettings, playerSettings) ||
|
||||
other.playerSettings == playerSettings));
|
||||
other.playerSettings == playerSettings) &&
|
||||
(identical(other.downloadSettings, downloadSettings) ||
|
||||
other.downloadSettings == downloadSettings));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, isDarkMode, useMaterialThemeOnItemPage, playerSettings);
|
||||
int get hashCode => Object.hash(runtimeType, isDarkMode,
|
||||
useMaterialThemeOnItemPage, playerSettings, downloadSettings);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
|
|
@ -199,7 +229,8 @@ abstract class _AppSettings implements AppSettings {
|
|||
const factory _AppSettings(
|
||||
{final bool isDarkMode,
|
||||
final bool useMaterialThemeOnItemPage,
|
||||
final PlayerSettings playerSettings}) = _$AppSettingsImpl;
|
||||
final PlayerSettings playerSettings,
|
||||
final DownloadSettings downloadSettings}) = _$AppSettingsImpl;
|
||||
|
||||
factory _AppSettings.fromJson(Map<String, dynamic> json) =
|
||||
_$AppSettingsImpl.fromJson;
|
||||
|
|
@ -211,6 +242,8 @@ abstract class _AppSettings implements AppSettings {
|
|||
@override
|
||||
PlayerSettings get playerSettings;
|
||||
@override
|
||||
DownloadSettings get downloadSettings;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$AppSettingsImplCopyWith<_$AppSettingsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
|
|
@ -1340,3 +1373,256 @@ abstract class _SleepTimerSettings implements SleepTimerSettings {
|
|||
_$$SleepTimerSettingsImplCopyWith<_$SleepTimerSettingsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
DownloadSettings _$DownloadSettingsFromJson(Map<String, dynamic> json) {
|
||||
return _DownloadSettings.fromJson(json);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
mixin _$DownloadSettings {
|
||||
bool get requiresWiFi => throw _privateConstructorUsedError;
|
||||
int get retries => throw _privateConstructorUsedError;
|
||||
bool get allowPause => throw _privateConstructorUsedError;
|
||||
int get maxConcurrent => throw _privateConstructorUsedError;
|
||||
int get maxConcurrentByHost => throw _privateConstructorUsedError;
|
||||
int get maxConcurrentByGroup => throw _privateConstructorUsedError;
|
||||
|
||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||
@JsonKey(ignore: true)
|
||||
$DownloadSettingsCopyWith<DownloadSettings> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $DownloadSettingsCopyWith<$Res> {
|
||||
factory $DownloadSettingsCopyWith(
|
||||
DownloadSettings value, $Res Function(DownloadSettings) then) =
|
||||
_$DownloadSettingsCopyWithImpl<$Res, DownloadSettings>;
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool requiresWiFi,
|
||||
int retries,
|
||||
bool allowPause,
|
||||
int maxConcurrent,
|
||||
int maxConcurrentByHost,
|
||||
int maxConcurrentByGroup});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$DownloadSettingsCopyWithImpl<$Res, $Val extends DownloadSettings>
|
||||
implements $DownloadSettingsCopyWith<$Res> {
|
||||
_$DownloadSettingsCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? requiresWiFi = null,
|
||||
Object? retries = null,
|
||||
Object? allowPause = null,
|
||||
Object? maxConcurrent = null,
|
||||
Object? maxConcurrentByHost = null,
|
||||
Object? maxConcurrentByGroup = null,
|
||||
}) {
|
||||
return _then(_value.copyWith(
|
||||
requiresWiFi: null == requiresWiFi
|
||||
? _value.requiresWiFi
|
||||
: requiresWiFi // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
retries: null == retries
|
||||
? _value.retries
|
||||
: retries // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
allowPause: null == allowPause
|
||||
? _value.allowPause
|
||||
: allowPause // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
maxConcurrent: null == maxConcurrent
|
||||
? _value.maxConcurrent
|
||||
: maxConcurrent // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
maxConcurrentByHost: null == maxConcurrentByHost
|
||||
? _value.maxConcurrentByHost
|
||||
: maxConcurrentByHost // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
maxConcurrentByGroup: null == maxConcurrentByGroup
|
||||
? _value.maxConcurrentByGroup
|
||||
: maxConcurrentByGroup // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
) as $Val);
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$DownloadSettingsImplCopyWith<$Res>
|
||||
implements $DownloadSettingsCopyWith<$Res> {
|
||||
factory _$$DownloadSettingsImplCopyWith(_$DownloadSettingsImpl value,
|
||||
$Res Function(_$DownloadSettingsImpl) then) =
|
||||
__$$DownloadSettingsImplCopyWithImpl<$Res>;
|
||||
@override
|
||||
@useResult
|
||||
$Res call(
|
||||
{bool requiresWiFi,
|
||||
int retries,
|
||||
bool allowPause,
|
||||
int maxConcurrent,
|
||||
int maxConcurrentByHost,
|
||||
int maxConcurrentByGroup});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$DownloadSettingsImplCopyWithImpl<$Res>
|
||||
extends _$DownloadSettingsCopyWithImpl<$Res, _$DownloadSettingsImpl>
|
||||
implements _$$DownloadSettingsImplCopyWith<$Res> {
|
||||
__$$DownloadSettingsImplCopyWithImpl(_$DownloadSettingsImpl _value,
|
||||
$Res Function(_$DownloadSettingsImpl) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? requiresWiFi = null,
|
||||
Object? retries = null,
|
||||
Object? allowPause = null,
|
||||
Object? maxConcurrent = null,
|
||||
Object? maxConcurrentByHost = null,
|
||||
Object? maxConcurrentByGroup = null,
|
||||
}) {
|
||||
return _then(_$DownloadSettingsImpl(
|
||||
requiresWiFi: null == requiresWiFi
|
||||
? _value.requiresWiFi
|
||||
: requiresWiFi // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
retries: null == retries
|
||||
? _value.retries
|
||||
: retries // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
allowPause: null == allowPause
|
||||
? _value.allowPause
|
||||
: allowPause // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
maxConcurrent: null == maxConcurrent
|
||||
? _value.maxConcurrent
|
||||
: maxConcurrent // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
maxConcurrentByHost: null == maxConcurrentByHost
|
||||
? _value.maxConcurrentByHost
|
||||
: maxConcurrentByHost // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
maxConcurrentByGroup: null == maxConcurrentByGroup
|
||||
? _value.maxConcurrentByGroup
|
||||
: maxConcurrentByGroup // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
class _$DownloadSettingsImpl implements _DownloadSettings {
|
||||
const _$DownloadSettingsImpl(
|
||||
{this.requiresWiFi = true,
|
||||
this.retries = 3,
|
||||
this.allowPause = true,
|
||||
this.maxConcurrent = 3,
|
||||
this.maxConcurrentByHost = 3,
|
||||
this.maxConcurrentByGroup = 3});
|
||||
|
||||
factory _$DownloadSettingsImpl.fromJson(Map<String, dynamic> json) =>
|
||||
_$$DownloadSettingsImplFromJson(json);
|
||||
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool requiresWiFi;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int retries;
|
||||
@override
|
||||
@JsonKey()
|
||||
final bool allowPause;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int maxConcurrent;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int maxConcurrentByHost;
|
||||
@override
|
||||
@JsonKey()
|
||||
final int maxConcurrentByGroup;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'DownloadSettings(requiresWiFi: $requiresWiFi, retries: $retries, allowPause: $allowPause, maxConcurrent: $maxConcurrent, maxConcurrentByHost: $maxConcurrentByHost, maxConcurrentByGroup: $maxConcurrentByGroup)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$DownloadSettingsImpl &&
|
||||
(identical(other.requiresWiFi, requiresWiFi) ||
|
||||
other.requiresWiFi == requiresWiFi) &&
|
||||
(identical(other.retries, retries) || other.retries == retries) &&
|
||||
(identical(other.allowPause, allowPause) ||
|
||||
other.allowPause == allowPause) &&
|
||||
(identical(other.maxConcurrent, maxConcurrent) ||
|
||||
other.maxConcurrent == maxConcurrent) &&
|
||||
(identical(other.maxConcurrentByHost, maxConcurrentByHost) ||
|
||||
other.maxConcurrentByHost == maxConcurrentByHost) &&
|
||||
(identical(other.maxConcurrentByGroup, maxConcurrentByGroup) ||
|
||||
other.maxConcurrentByGroup == maxConcurrentByGroup));
|
||||
}
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType, requiresWiFi, retries,
|
||||
allowPause, maxConcurrent, maxConcurrentByHost, maxConcurrentByGroup);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$DownloadSettingsImplCopyWith<_$DownloadSettingsImpl> get copyWith =>
|
||||
__$$DownloadSettingsImplCopyWithImpl<_$DownloadSettingsImpl>(
|
||||
this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$$DownloadSettingsImplToJson(
|
||||
this,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _DownloadSettings implements DownloadSettings {
|
||||
const factory _DownloadSettings(
|
||||
{final bool requiresWiFi,
|
||||
final int retries,
|
||||
final bool allowPause,
|
||||
final int maxConcurrent,
|
||||
final int maxConcurrentByHost,
|
||||
final int maxConcurrentByGroup}) = _$DownloadSettingsImpl;
|
||||
|
||||
factory _DownloadSettings.fromJson(Map<String, dynamic> json) =
|
||||
_$DownloadSettingsImpl.fromJson;
|
||||
|
||||
@override
|
||||
bool get requiresWiFi;
|
||||
@override
|
||||
int get retries;
|
||||
@override
|
||||
bool get allowPause;
|
||||
@override
|
||||
int get maxConcurrent;
|
||||
@override
|
||||
int get maxConcurrentByHost;
|
||||
@override
|
||||
int get maxConcurrentByGroup;
|
||||
@override
|
||||
@JsonKey(ignore: true)
|
||||
_$$DownloadSettingsImplCopyWith<_$DownloadSettingsImpl> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,15 @@ _$AppSettingsImpl _$$AppSettingsImplFromJson(Map<String, dynamic> json) =>
|
|||
_$AppSettingsImpl(
|
||||
isDarkMode: json['isDarkMode'] as bool? ?? true,
|
||||
useMaterialThemeOnItemPage:
|
||||
json['useMaterialThemeOnItemPage'] as bool? ?? false,
|
||||
json['useMaterialThemeOnItemPage'] as bool? ?? true,
|
||||
playerSettings: json['playerSettings'] == null
|
||||
? const PlayerSettings()
|
||||
: PlayerSettings.fromJson(
|
||||
json['playerSettings'] as Map<String, dynamic>),
|
||||
downloadSettings: json['downloadSettings'] == null
|
||||
? const DownloadSettings()
|
||||
: DownloadSettings.fromJson(
|
||||
json['downloadSettings'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
|
||||
|
|
@ -22,6 +26,7 @@ Map<String, dynamic> _$$AppSettingsImplToJson(_$AppSettingsImpl instance) =>
|
|||
'isDarkMode': instance.isDarkMode,
|
||||
'useMaterialThemeOnItemPage': instance.useMaterialThemeOnItemPage,
|
||||
'playerSettings': instance.playerSettings,
|
||||
'downloadSettings': instance.downloadSettings,
|
||||
};
|
||||
|
||||
_$PlayerSettingsImpl _$$PlayerSettingsImplFromJson(Map<String, dynamic> json) =>
|
||||
|
|
@ -155,3 +160,26 @@ const _$SleepTimerShakeSenseModeEnumMap = {
|
|||
SleepTimerShakeSenseMode.always: 'always',
|
||||
SleepTimerShakeSenseMode.nearEnds: 'nearEnds',
|
||||
};
|
||||
|
||||
_$DownloadSettingsImpl _$$DownloadSettingsImplFromJson(
|
||||
Map<String, dynamic> json) =>
|
||||
_$DownloadSettingsImpl(
|
||||
requiresWiFi: json['requiresWiFi'] as bool? ?? true,
|
||||
retries: (json['retries'] as num?)?.toInt() ?? 3,
|
||||
allowPause: json['allowPause'] as bool? ?? true,
|
||||
maxConcurrent: (json['maxConcurrent'] as num?)?.toInt() ?? 3,
|
||||
maxConcurrentByHost: (json['maxConcurrentByHost'] as num?)?.toInt() ?? 3,
|
||||
maxConcurrentByGroup:
|
||||
(json['maxConcurrentByGroup'] as num?)?.toInt() ?? 3,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$$DownloadSettingsImplToJson(
|
||||
_$DownloadSettingsImpl instance) =>
|
||||
<String, dynamic>{
|
||||
'requiresWiFi': instance.requiresWiFi,
|
||||
'retries': instance.retries,
|
||||
'allowPause': instance.allowPause,
|
||||
'maxConcurrent': instance.maxConcurrent,
|
||||
'maxConcurrentByHost': instance.maxConcurrentByHost,
|
||||
'maxConcurrentByGroup': instance.maxConcurrentByGroup,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_settings_ui/flutter_settings_ui.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
|
@ -7,6 +10,7 @@ import 'package:whispering_pages/api/authenticated_user_provider.dart';
|
|||
import 'package:whispering_pages/api/server_provider.dart';
|
||||
import 'package:whispering_pages/router/router.dart';
|
||||
import 'package:whispering_pages/settings/app_settings_provider.dart';
|
||||
import 'package:whispering_pages/settings/models/app_settings.dart' as model;
|
||||
|
||||
class AppSettingsPage extends HookConsumerWidget {
|
||||
const AppSettingsPage({
|
||||
|
|
@ -20,7 +24,6 @@ class AppSettingsPage extends HookConsumerWidget {
|
|||
final registeredServersAsList = registeredServers.toList();
|
||||
final availableUsers = ref.watch(authenticatedUserProvider);
|
||||
final serverURIController = useTextEditingController();
|
||||
final formKey = GlobalKey<FormState>();
|
||||
final sleepTimerSettings = appSettings.playerSettings.sleepTimerSettings;
|
||||
|
||||
return Scaffold(
|
||||
|
|
@ -124,6 +127,149 @@ class AppSettingsPage extends HookConsumerWidget {
|
|||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Backup and Restore section
|
||||
SettingsSection(
|
||||
margin: const EdgeInsetsDirectional.symmetric(
|
||||
horizontal: 16.0,
|
||||
vertical: 8.0,
|
||||
),
|
||||
title: Text(
|
||||
'Backup and Restore',
|
||||
style: Theme.of(context).textTheme.titleLarge,
|
||||
),
|
||||
tiles: [
|
||||
SettingsTile(
|
||||
title: const Text('Copy to Clipboard'),
|
||||
leading: const Icon(Icons.copy),
|
||||
description: const Text(
|
||||
'Copy the app settings to the clipboard',
|
||||
),
|
||||
onPressed: (context) async {
|
||||
// copy to clipboard
|
||||
await Clipboard.setData(
|
||||
ClipboardData(
|
||||
text: jsonEncode(appSettings.toJson()),
|
||||
),
|
||||
);
|
||||
// show toast
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Settings copied to clipboard'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingsTile(
|
||||
title: const Text('Restore'),
|
||||
leading: const Icon(Icons.restore),
|
||||
description: const Text(
|
||||
'Restore the app settings from the backup',
|
||||
),
|
||||
onPressed: (context) {
|
||||
final formKey = GlobalKey<FormState>();
|
||||
// show a dialog to get the backup
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Restore Backup'),
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: TextFormField(
|
||||
controller: serverURIController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Backup',
|
||||
hintText: 'Paste the backup here',
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please paste the backup here';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
if (formKey.currentState!.validate()) {
|
||||
final backup = serverURIController.text;
|
||||
final newSettings = model.AppSettings.fromJson(
|
||||
// decode the backup as json
|
||||
jsonDecode(backup),
|
||||
);
|
||||
ref
|
||||
.read(appSettingsProvider.notifier)
|
||||
.updateState(newSettings);
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Settings restored'),
|
||||
),
|
||||
);
|
||||
// clear the backup
|
||||
serverURIController.clear();
|
||||
}
|
||||
},
|
||||
child: const Text('Restore'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
// a button to reset the app settings
|
||||
SettingsTile(
|
||||
title: const Text('Reset App Settings'),
|
||||
leading: const Icon(Icons.settings_backup_restore),
|
||||
description: const Text(
|
||||
'Reset the app settings to the default values',
|
||||
),
|
||||
onPressed: (context) async {
|
||||
// confirm the reset
|
||||
final res = await showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Reset App Settings'),
|
||||
content: const Text(
|
||||
'Are you sure you want to reset the app settings?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(false);
|
||||
},
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: const Text('Reset'),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
// if the user confirms the reset
|
||||
if (res == true) {
|
||||
ref.read(appSettingsProvider.notifier).reset();
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue