mirror of
https://github.com/gabehf/Fladder.git
synced 2026-03-08 23:18:16 -07:00
feat: UI 2.0 and other Improvements (#357)
Co-authored-by: PartyDonut <PartyDonut@users.noreply.github.com>
This commit is contained in:
parent
9ca06eaa37
commit
e7b5bb40ff
169 changed files with 4584 additions and 3626 deletions
|
|
@ -2,79 +2,83 @@ import 'package:flutter/material.dart';
|
|||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import 'package:fladder/models/settings/home_settings_model.dart';
|
||||
import 'package:fladder/providers/settings/home_settings_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/option_dialogue.dart';
|
||||
|
||||
List<Widget> buildClientSettingsAdvanced(BuildContext context, WidgetRef ref) {
|
||||
return [
|
||||
return settingsListGroup(
|
||||
context,
|
||||
SettingsLabelDivider(label: context.localized.advanced),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsLayoutSizesTitle),
|
||||
subLabel: Text(context.localized.settingsLayoutSizesDesc),
|
||||
onTap: () async {
|
||||
final newItems = await openMultiSelectOptions<ViewSize>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutSizesTitle,
|
||||
items: ViewSize.values,
|
||||
allowMultiSelection: true,
|
||||
selected: ref.read(homeSettingsProvider.select((value) => value.layoutStates.toList())),
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
title: Text(type.label(context)),
|
||||
[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsLayoutSizesTitle),
|
||||
subLabel: Text(context.localized.settingsLayoutSizesDesc),
|
||||
onTap: () async {
|
||||
final newItems = await openMultiSelectOptions<ViewSize>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutSizesTitle,
|
||||
items: ViewSize.values,
|
||||
allowMultiSelection: true,
|
||||
selected: ref.read(homeSettingsProvider.select((value) => value.layoutStates.toList())),
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
title: Text(type.label(context)),
|
||||
),
|
||||
);
|
||||
ref.read(homeSettingsProvider.notifier).setViewSize(newItems.toSet());
|
||||
},
|
||||
trailing: Card(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
shadowColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(ref
|
||||
.watch(homeSettingsProvider.select((value) => value.layoutStates.toList()))
|
||||
.map((e) => e.label(context))
|
||||
.join(', ')),
|
||||
),
|
||||
);
|
||||
ref.read(homeSettingsProvider.notifier).setViewSize(newItems.toSet());
|
||||
},
|
||||
trailing: Card(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
shadowColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(ref
|
||||
.watch(homeSettingsProvider.select((value) => value.layoutStates.toList()))
|
||||
.map((e) => e.label(context))
|
||||
.join(', ')),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsLayoutModesTitle),
|
||||
subLabel: Text(context.localized.settingsLayoutModesDesc),
|
||||
onTap: () async {
|
||||
final newItems = await openMultiSelectOptions<LayoutMode>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutModesTitle,
|
||||
items: LayoutMode.values,
|
||||
allowMultiSelection: true,
|
||||
selected: ref.read(homeSettingsProvider.select((value) => value.screenLayouts.toList())),
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
title: Text(type.label(context)),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsLayoutModesTitle),
|
||||
subLabel: Text(context.localized.settingsLayoutModesDesc),
|
||||
onTap: () async {
|
||||
final newItems = await openMultiSelectOptions<LayoutMode>(
|
||||
context,
|
||||
label: context.localized.settingsLayoutModesTitle,
|
||||
items: LayoutMode.values,
|
||||
allowMultiSelection: true,
|
||||
selected: ref.read(homeSettingsProvider.select((value) => value.screenLayouts.toList())),
|
||||
itemBuilder: (type, selected, tap) => CheckboxListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
value: selected,
|
||||
onChanged: (value) => tap(),
|
||||
title: Text(type.label(context)),
|
||||
),
|
||||
);
|
||||
ref.read(homeSettingsProvider.notifier).setLayoutModes(newItems.toSet());
|
||||
},
|
||||
trailing: Card(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
shadowColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(ref
|
||||
.watch(homeSettingsProvider.select((value) => value.screenLayouts.toList()))
|
||||
.map((e) => e.label(context))
|
||||
.join(', ')),
|
||||
),
|
||||
);
|
||||
ref.read(homeSettingsProvider.notifier).setLayoutModes(newItems.toSet());
|
||||
},
|
||||
trailing: Card(
|
||||
color: Theme.of(context).colorScheme.primaryContainer,
|
||||
shadowColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(ref
|
||||
.watch(homeSettingsProvider.select((value) => value.screenLayouts.toList()))
|
||||
.map((e) => e.label(context))
|
||||
.join(', ')),
|
||||
),
|
||||
),
|
||||
),
|
||||
];
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,89 +7,92 @@ import 'package:fladder/providers/settings/client_settings_provider.dart';
|
|||
import 'package:fladder/providers/settings/home_settings_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/widgets/shared/enum_selection.dart';
|
||||
|
||||
List<Widget> buildClientSettingsDashboard(BuildContext context, WidgetRef ref) {
|
||||
final clientSettings = ref.watch(clientSettingsProvider);
|
||||
return [
|
||||
return settingsListGroup(
|
||||
context,
|
||||
SettingsLabelDivider(label: context.localized.dashboard),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsHomeBannerTitle),
|
||||
subLabel: Text(context.localized.settingsHomeBannerDescription),
|
||||
trailing: EnumBox(
|
||||
current: ref.watch(
|
||||
homeSettingsProvider.select(
|
||||
(value) => value.homeBanner.label(context),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context) => HomeBanner.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () =>
|
||||
ref.read(homeSettingsProvider.notifier).update((context) => context.copyWith(homeBanner: entry)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
if (ref.watch(homeSettingsProvider.select((value) => value.homeBanner)) != HomeBanner.hide)
|
||||
[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsHomeBannerInformationTitle),
|
||||
subLabel: Text(context.localized.settingsHomeBannerInformationDesc),
|
||||
label: Text(context.localized.settingsHomeBannerTitle),
|
||||
subLabel: Text(context.localized.settingsHomeBannerDescription),
|
||||
trailing: EnumBox(
|
||||
current: ref.watch(
|
||||
homeSettingsProvider.select((value) => value.carouselSettings.label(context)),
|
||||
homeSettingsProvider.select(
|
||||
(value) => value.homeBanner.label(context),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context) => HomeCarouselSettings.values
|
||||
itemBuilder: (context) => HomeBanner.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () => ref
|
||||
.read(homeSettingsProvider.notifier)
|
||||
.update((context) => context.copyWith(carouselSettings: entry)),
|
||||
onTap: () =>
|
||||
ref.read(homeSettingsProvider.notifier).update((context) => context.copyWith(homeBanner: entry)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsHomeNextUpTitle),
|
||||
subLabel: Text(context.localized.settingsHomeNextUpDesc),
|
||||
trailing: EnumBox(
|
||||
current: ref.watch(
|
||||
homeSettingsProvider.select(
|
||||
(value) => value.nextUp.label(context),
|
||||
if (ref.watch(homeSettingsProvider.select((value) => value.homeBanner)) != HomeBanner.hide)
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsHomeBannerInformationTitle),
|
||||
subLabel: Text(context.localized.settingsHomeBannerInformationDesc),
|
||||
trailing: EnumBox(
|
||||
current: ref.watch(
|
||||
homeSettingsProvider.select((value) => value.carouselSettings.label(context)),
|
||||
),
|
||||
itemBuilder: (context) => HomeCarouselSettings.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () => ref
|
||||
.read(homeSettingsProvider.notifier)
|
||||
.update((context) => context.copyWith(carouselSettings: entry)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context) => HomeNextUp.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () =>
|
||||
ref.read(homeSettingsProvider.notifier).update((context) => context.copyWith(nextUp: entry)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsHomeNextUpTitle),
|
||||
subLabel: Text(context.localized.settingsHomeNextUpDesc),
|
||||
trailing: EnumBox(
|
||||
current: ref.watch(
|
||||
homeSettingsProvider.select(
|
||||
(value) => value.nextUp.label(context),
|
||||
),
|
||||
),
|
||||
itemBuilder: (context) => HomeNextUp.values
|
||||
.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Text(entry.label(context)),
|
||||
onTap: () =>
|
||||
ref.read(homeSettingsProvider.notifier).update((context) => context.copyWith(nextUp: entry)),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.clientSettingsShowAllCollectionsTitle),
|
||||
subLabel: Text(context.localized.clientSettingsShowAllCollectionsDesc),
|
||||
onTap: () => ref
|
||||
.read(clientSettingsProvider.notifier)
|
||||
.update((current) => current.copyWith(showAllCollectionTypes: !current.showAllCollectionTypes)),
|
||||
trailing: Switch(
|
||||
value: clientSettings.showAllCollectionTypes,
|
||||
onChanged: (value) => ref
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.clientSettingsShowAllCollectionsTitle),
|
||||
subLabel: Text(context.localized.clientSettingsShowAllCollectionsDesc),
|
||||
onTap: () => ref
|
||||
.read(clientSettingsProvider.notifier)
|
||||
.update((current) => current.copyWith(showAllCollectionTypes: value)),
|
||||
.update((current) => current.copyWith(showAllCollectionTypes: !current.showAllCollectionTypes)),
|
||||
trailing: Switch(
|
||||
value: clientSettings.showAllCollectionTypes,
|
||||
onChanged: (value) => ref
|
||||
.read(clientSettingsProvider.notifier)
|
||||
.update((current) => current.copyWith(showAllCollectionTypes: value)),
|
||||
),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
];
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,10 @@ import 'package:fladder/providers/sync_provider.dart';
|
|||
import 'package:fladder/providers/user_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
|
||||
import 'package:fladder/screens/shared/default_alert_dialog.dart';
|
||||
import 'package:fladder/screens/shared/input_fields.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/util/size_formatting.dart';
|
||||
|
||||
|
|
@ -24,121 +25,122 @@ List<Widget> buildClientSettingsDownload(BuildContext context, WidgetRef ref, Fu
|
|||
|
||||
return [
|
||||
if (canSync && !kIsWeb) ...[
|
||||
SettingsLabelDivider(label: context.localized.downloadsTitle),
|
||||
if (AdaptiveLayout.of(context).isDesktop) ...[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.downloadsPath),
|
||||
subLabel: Text(currentFolder ?? "-"),
|
||||
onTap: currentFolder != null
|
||||
? () async => await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.localized.pathEditTitle),
|
||||
content: Text(context.localized.pathEditDesc),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
String? selectedDirectory = await FilePicker.platform.getDirectoryPath(
|
||||
dialogTitle: context.localized.pathEditSelect, initialDirectory: currentFolder);
|
||||
if (selectedDirectory != null) {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(selectedDirectory);
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(context.localized.change),
|
||||
)
|
||||
],
|
||||
...settingsListGroup(context, SettingsLabelDivider(label: context.localized.downloadsTitle), [
|
||||
if (AdaptiveLayout.of(context).isDesktop) ...[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.downloadsPath),
|
||||
subLabel: Text(currentFolder ?? "-"),
|
||||
onTap: currentFolder != null
|
||||
? () async => await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.localized.pathEditTitle),
|
||||
content: Text(context.localized.pathEditDesc),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
String? selectedDirectory = await FilePicker.platform.getDirectoryPath(
|
||||
dialogTitle: context.localized.pathEditSelect, initialDirectory: currentFolder);
|
||||
if (selectedDirectory != null) {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(selectedDirectory);
|
||||
}
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(context.localized.change),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: () async {
|
||||
String? selectedDirectory = await FilePicker.platform.getDirectoryPath(
|
||||
dialogTitle: context.localized.pathEditSelect, initialDirectory: currentFolder);
|
||||
if (selectedDirectory != null) {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(selectedDirectory);
|
||||
}
|
||||
},
|
||||
trailing: currentFolder?.isNotEmpty == true
|
||||
? IconButton(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
onPressed: () async => await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.localized.pathClearTitle),
|
||||
content: Text(context.localized.pathEditDesc),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(null);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(context.localized.clear),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
icon: const Icon(IconsaxPlusLinear.folder_minus),
|
||||
)
|
||||
: () async {
|
||||
String? selectedDirectory = await FilePicker.platform
|
||||
.getDirectoryPath(dialogTitle: context.localized.pathEditSelect, initialDirectory: currentFolder);
|
||||
if (selectedDirectory != null) {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(selectedDirectory);
|
||||
: null,
|
||||
),
|
||||
],
|
||||
FutureBuilder(
|
||||
future: ref.watch(syncProvider.notifier).directorySize,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data ?? 0;
|
||||
return SettingsListTile(
|
||||
label: Text(context.localized.downloadsSyncedData),
|
||||
subLabel: Text(data.byteFormat ?? ""),
|
||||
trailing: FilledButton(
|
||||
onPressed: () {
|
||||
showDefaultAlertDialog(
|
||||
context,
|
||||
context.localized.downloadsClearTitle,
|
||||
context.localized.downloadsClearDesc,
|
||||
(context) async {
|
||||
await ref.read(syncProvider.notifier).clear();
|
||||
setState(() {});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
context.localized.clear,
|
||||
(context) => Navigator.of(context).pop(),
|
||||
context.localized.cancel,
|
||||
);
|
||||
},
|
||||
child: Text(context.localized.clear),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.clientSettingsRequireWifiTitle),
|
||||
subLabel: Text(context.localized.clientSettingsRequireWifiDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setRequireWifi(!clientSettings.requireWifi),
|
||||
trailing: Switch(
|
||||
value: clientSettings.requireWifi,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setRequireWifi(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.maxConcurrentDownloadsTitle),
|
||||
subLabel: Text(context.localized.maxConcurrentDownloadsDesc),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
controller: TextEditingController(text: clientSettings.maxConcurrentDownloads.toString()),
|
||||
onSubmitted: (value) {
|
||||
if (value != null) {
|
||||
ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(
|
||||
maxConcurrentDownloads: value,
|
||||
),
|
||||
);
|
||||
|
||||
ref.read(backgroundDownloaderProvider.notifier).setMaxConcurrent(value);
|
||||
}
|
||||
},
|
||||
trailing: currentFolder?.isNotEmpty == true
|
||||
? IconButton(
|
||||
color: Theme.of(context).colorScheme.error,
|
||||
onPressed: () async => await showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: Text(context.localized.pathClearTitle),
|
||||
content: Text(context.localized.pathEditDesc),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
ref.read(clientSettingsProvider.notifier).setSyncPath(null);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text(context.localized.clear),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
icon: const Icon(IconsaxPlusLinear.folder_minus),
|
||||
)
|
||||
: null,
|
||||
)),
|
||||
),
|
||||
],
|
||||
FutureBuilder(
|
||||
future: ref.watch(syncProvider.notifier).directorySize,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data ?? 0;
|
||||
return SettingsListTile(
|
||||
label: Text(context.localized.downloadsSyncedData),
|
||||
subLabel: Text(data.byteFormat ?? ""),
|
||||
trailing: FilledButton(
|
||||
onPressed: () {
|
||||
showDefaultAlertDialog(
|
||||
context,
|
||||
context.localized.downloadsClearTitle,
|
||||
context.localized.downloadsClearDesc,
|
||||
(context) async {
|
||||
await ref.read(syncProvider.notifier).clear();
|
||||
setState(() {});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
context.localized.clear,
|
||||
(context) => Navigator.of(context).pop(),
|
||||
context.localized.cancel,
|
||||
);
|
||||
},
|
||||
child: Text(context.localized.clear),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.clientSettingsRequireWifiTitle),
|
||||
subLabel: Text(context.localized.clientSettingsRequireWifiDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setRequireWifi(!clientSettings.requireWifi),
|
||||
trailing: Switch(
|
||||
value: clientSettings.requireWifi,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setRequireWifi(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.maxConcurrentDownloadsTitle),
|
||||
subLabel: Text(context.localized.maxConcurrentDownloadsDesc),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
controller: TextEditingController(text: clientSettings.maxConcurrentDownloads.toString()),
|
||||
onSubmitted: (value) {
|
||||
if (value != null) {
|
||||
ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(
|
||||
maxConcurrentDownloads: value,
|
||||
),
|
||||
);
|
||||
|
||||
ref.read(backgroundDownloaderProvider.notifier).setMaxConcurrent(value);
|
||||
}
|
||||
},
|
||||
)),
|
||||
),
|
||||
const Divider(),
|
||||
]),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
|
||||
import 'package:fladder/util/color_extensions.dart';
|
||||
import 'package:fladder/util/custom_color_themes.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
|
|
@ -13,8 +14,7 @@ import 'package:fladder/util/theme_mode_extension.dart';
|
|||
|
||||
List<Widget> buildClientSettingsTheme(BuildContext context, WidgetRef ref) {
|
||||
final clientSettings = ref.watch(clientSettingsProvider);
|
||||
return [
|
||||
SettingsLabelDivider(label: context.localized.theme),
|
||||
return settingsListGroup(context, SettingsLabelDivider(label: context.localized.theme), [
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.mode),
|
||||
subLabel: Text(clientSettings.themeMode.label(context)),
|
||||
|
|
@ -107,6 +107,5 @@ List<Widget> buildClientSettingsTheme(BuildContext context, WidgetRef ref) {
|
|||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setAmoledBlack(value),
|
||||
),
|
||||
),
|
||||
const Divider(),
|
||||
];
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import 'dart:developer';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
|
@ -8,8 +6,9 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|||
import 'package:fladder/providers/settings/client_settings_provider.dart';
|
||||
import 'package:fladder/screens/settings/settings_list_tile.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_label_divider.dart';
|
||||
import 'package:fladder/screens/settings/widgets/settings_list_group.dart';
|
||||
import 'package:fladder/screens/shared/input_fields.dart';
|
||||
import 'package:fladder/util/adaptive_layout.dart';
|
||||
import 'package:fladder/util/adaptive_layout/adaptive_layout.dart';
|
||||
import 'package:fladder/util/localization_helper.dart';
|
||||
import 'package:fladder/widgets/shared/enum_selection.dart';
|
||||
import 'package:fladder/widgets/shared/fladder_slider.dart';
|
||||
|
|
@ -22,136 +21,136 @@ List<Widget> buildClientSettingsVisual(
|
|||
) {
|
||||
final clientSettings = ref.watch(clientSettingsProvider);
|
||||
Locale currentLocale = WidgetsBinding.instance.platformDispatcher.locale;
|
||||
return [
|
||||
return settingsListGroup(
|
||||
context,
|
||||
SettingsLabelDivider(label: context.localized.settingsVisual),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.displayLanguage),
|
||||
trailing: Localizations.override(
|
||||
context: context,
|
||||
locale: ref.watch(clientSettingsProvider.select((value) => (value.selectedLocale ?? currentLocale))),
|
||||
child: Builder(builder: (context) {
|
||||
String language = "Unknown";
|
||||
try {
|
||||
language = context.localized.nativeName;
|
||||
} catch (e) {
|
||||
log(e.toString());
|
||||
}
|
||||
return EnumBox(
|
||||
current: language,
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
...AppLocalizations.supportedLocales.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Localizations.override(
|
||||
context: context,
|
||||
locale: entry,
|
||||
child: Builder(builder: (context) {
|
||||
return Text("${context.localized.nativeName} (${entry.languageCode.toUpperCase()})");
|
||||
}),
|
||||
[
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.displayLanguage),
|
||||
trailing: Localizations.override(
|
||||
context: context,
|
||||
locale: ref.watch(clientSettingsProvider.select((value) => (value.selectedLocale ?? currentLocale))),
|
||||
child: Builder(builder: (context) {
|
||||
String language = "Unknown";
|
||||
try {
|
||||
language = context.localized.nativeName;
|
||||
} catch (_) {}
|
||||
return EnumBox(
|
||||
current: language,
|
||||
itemBuilder: (context) {
|
||||
return [
|
||||
...AppLocalizations.supportedLocales.map(
|
||||
(entry) => PopupMenuItem(
|
||||
value: entry,
|
||||
child: Localizations.override(
|
||||
context: context,
|
||||
locale: entry,
|
||||
child: Builder(builder: (context) {
|
||||
return Text("${context.localized.nativeName} (${entry.languageCode.toUpperCase()})");
|
||||
}),
|
||||
),
|
||||
onTap: () => ref
|
||||
.read(clientSettingsProvider.notifier)
|
||||
.update((state) => state.copyWith(selectedLocale: entry)),
|
||||
),
|
||||
onTap: () => ref
|
||||
.read(clientSettingsProvider.notifier)
|
||||
.update((state) => state.copyWith(selectedLocale: entry)),
|
||||
)
|
||||
];
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsBlurredPlaceholderTitle),
|
||||
subLabel: Text(context.localized.settingsBlurredPlaceholderDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setBlurPlaceholders(!clientSettings.blurPlaceHolders),
|
||||
trailing: Switch(
|
||||
value: clientSettings.blurPlaceHolders,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setBlurPlaceholders(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsBlurEpisodesTitle),
|
||||
subLabel: Text(context.localized.settingsBlurEpisodesDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setBlurEpisodes(!clientSettings.blurUpcomingEpisodes),
|
||||
trailing: Switch(
|
||||
value: clientSettings.blurUpcomingEpisodes,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setBlurEpisodes(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsEnableOsMediaControls),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setMediaKeys(!clientSettings.enableMediaKeys),
|
||||
trailing: Switch(
|
||||
value: clientSettings.enableMediaKeys,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setMediaKeys(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsNextUpCutoffDays),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
suffix: context.localized.days,
|
||||
controller: nextUpDaysEditor,
|
||||
onSubmitted: (value) {
|
||||
if (value != null) {
|
||||
ref.read(clientSettingsProvider.notifier).update((current) => current.copyWith(
|
||||
nextUpDateCutoff: Duration(days: value),
|
||||
));
|
||||
}
|
||||
},
|
||||
)),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.libraryPageSizeTitle),
|
||||
subLabel: Text(context.localized.libraryPageSizeDesc),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
controller: libraryPageSizeController,
|
||||
placeHolder: "500",
|
||||
onSubmitted: (value) => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(libraryPageSize: value),
|
||||
),
|
||||
)
|
||||
];
|
||||
},
|
||||
);
|
||||
}),
|
||||
)),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsBlurredPlaceholderTitle),
|
||||
subLabel: Text(context.localized.settingsBlurredPlaceholderDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setBlurPlaceholders(!clientSettings.blurPlaceHolders),
|
||||
trailing: Switch(
|
||||
value: clientSettings.blurPlaceHolders,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setBlurPlaceholders(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsBlurEpisodesTitle),
|
||||
subLabel: Text(context.localized.settingsBlurEpisodesDesc),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setBlurEpisodes(!clientSettings.blurUpcomingEpisodes),
|
||||
trailing: Switch(
|
||||
value: clientSettings.blurUpcomingEpisodes,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setBlurEpisodes(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsEnableOsMediaControls),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).setMediaKeys(!clientSettings.enableMediaKeys),
|
||||
trailing: Switch(
|
||||
value: clientSettings.enableMediaKeys,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).setMediaKeys(value),
|
||||
),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsNextUpCutoffDays),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
suffix: context.localized.days,
|
||||
controller: nextUpDaysEditor,
|
||||
onSubmitted: (value) {
|
||||
if (value != null) {
|
||||
ref.read(clientSettingsProvider.notifier).update((current) => current.copyWith(
|
||||
nextUpDateCutoff: Duration(days: value),
|
||||
));
|
||||
}
|
||||
},
|
||||
)),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.libraryPageSizeTitle),
|
||||
subLabel: Text(context.localized.libraryPageSizeDesc),
|
||||
trailing: SizedBox(
|
||||
width: 100,
|
||||
child: IntInputField(
|
||||
controller: libraryPageSizeController,
|
||||
placeHolder: "500",
|
||||
onSubmitted: (value) => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(libraryPageSize: value),
|
||||
),
|
||||
)),
|
||||
),
|
||||
SettingsListTile(
|
||||
label: Text(AdaptiveLayout.of(context).isDesktop
|
||||
? context.localized.settingsShowScaleSlider
|
||||
: context.localized.settingsPosterPinch),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(pinchPosterZoom: !current.pinchPosterZoom),
|
||||
),
|
||||
trailing: Switch(
|
||||
value: clientSettings.pinchPosterZoom,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(pinchPosterZoom: value),
|
||||
SettingsListTile(
|
||||
label: Text(AdaptiveLayout.of(context).isDesktop
|
||||
? context.localized.settingsShowScaleSlider
|
||||
: context.localized.settingsPosterPinch),
|
||||
onTap: () => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(pinchPosterZoom: !current.pinchPosterZoom),
|
||||
),
|
||||
trailing: Switch(
|
||||
value: clientSettings.pinchPosterZoom,
|
||||
onChanged: (value) => ref.read(clientSettingsProvider.notifier).update(
|
||||
(current) => current.copyWith(pinchPosterZoom: value),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsPosterSize),
|
||||
trailing: Text(
|
||||
clientSettings.posterSize.toString(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
Column(
|
||||
children: [
|
||||
SettingsListTile(
|
||||
label: Text(context.localized.settingsPosterSize),
|
||||
trailing: Text(
|
||||
clientSettings.posterSize.toString(),
|
||||
style: Theme.of(context).textTheme.bodyLarge,
|
||||
),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: FladderSlider(
|
||||
min: 0.5,
|
||||
max: 1.5,
|
||||
value: clientSettings.posterSize,
|
||||
divisions: 20,
|
||||
onChanged: (value) =>
|
||||
ref.read(clientSettingsProvider.notifier).update((current) => current.copyWith(posterSize: value)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: FladderSlider(
|
||||
min: 0.5,
|
||||
max: 1.5,
|
||||
value: clientSettings.posterSize,
|
||||
divisions: 20,
|
||||
onChanged: (value) =>
|
||||
ref.read(clientSettingsProvider.notifier).update((current) => current.copyWith(posterSize: value)),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
];
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue