mirror of
https://github.com/namidaco/namida.git
synced 2026-03-13 08:12:29 +08:00
210 lines
7.2 KiB
Dart
210 lines
7.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'package:namida/base/setting_subpage_provider.dart';
|
|
import 'package:namida/class/route.dart';
|
|
import 'package:namida/controller/navigator_controller.dart';
|
|
import 'package:namida/core/constants.dart';
|
|
import 'package:namida/core/enums.dart';
|
|
import 'package:namida/core/extensions.dart';
|
|
import 'package:namida/core/icon_fonts/broken_icons.dart';
|
|
import 'package:namida/core/translations/language.dart';
|
|
import 'package:namida/core/utils.dart';
|
|
import 'package:namida/ui/pages/settings_page.dart';
|
|
import 'package:namida/ui/widgets/settings/advanced_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/backup_restore_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/customization_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/extra_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/indexer_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/playback_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/theme_settings.dart';
|
|
import 'package:namida/ui/widgets/settings/youtube_settings.dart';
|
|
|
|
mixin SettingKeysBase {
|
|
NamidaFeaturesAvailablityBase? get availability => null;
|
|
}
|
|
|
|
extension _SettSearcherUtils on SettingSubpageEnum {
|
|
CustomCollapsedListTile? toSettingSubPageDetails({Enum? initialItem}) {
|
|
switch (this) {
|
|
case SettingSubpageEnum.theme:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.themeSettings,
|
|
subtitle: lang.themeSettingsSubtitle,
|
|
icon: Broken.brush_2,
|
|
page: () => ThemeSetting(initialItem: initialItem),
|
|
);
|
|
case SettingSubpageEnum.indexer:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.indexer,
|
|
subtitle: lang.indexerSubtitle,
|
|
icon: Broken.component,
|
|
page: () => IndexerSettings(initialItem: initialItem),
|
|
);
|
|
|
|
case SettingSubpageEnum.playback:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.playbackSetting,
|
|
subtitle: lang.playbackSettingSubtitle,
|
|
icon: Broken.play_cricle,
|
|
page: () => PlaybackSettings(initialItem: initialItem),
|
|
);
|
|
case SettingSubpageEnum.customization:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.customizations,
|
|
subtitle: lang.customizationsSubtitle,
|
|
icon: Broken.brush_1,
|
|
page: () => CustomizationSettings(initialItem: initialItem),
|
|
);
|
|
|
|
case SettingSubpageEnum.youtube:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.youtube,
|
|
subtitle: lang.youtubeSettingsSubtitle,
|
|
icon: Broken.video,
|
|
page: () => YoutubeSettings(initialItem: initialItem),
|
|
);
|
|
|
|
case SettingSubpageEnum.extra:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.extras,
|
|
subtitle: lang.extrasSubtitle,
|
|
icon: Broken.command_square,
|
|
page: () => ExtrasSettings(initialItem: initialItem),
|
|
);
|
|
case SettingSubpageEnum.backupRestore:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.backupAndRestore,
|
|
subtitle: lang.backupAndRestoreSubtitle,
|
|
icon: Broken.refresh_circle,
|
|
page: () => BackupAndRestore(initialItem: initialItem),
|
|
);
|
|
|
|
case SettingSubpageEnum.advanced:
|
|
return CustomCollapsedListTile(
|
|
title: () => lang.advancedSettings,
|
|
subtitle: lang.advancedSettingsSubtitle,
|
|
icon: Broken.hierarchy_3,
|
|
page: () => AdvancedSettings(initialItem: initialItem),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
class SettingSearchResultItem {
|
|
final SettingSubpageEnum? page;
|
|
final Enum key;
|
|
final List<String> titles;
|
|
|
|
const SettingSearchResultItem({
|
|
required this.page,
|
|
required this.key,
|
|
required this.titles,
|
|
});
|
|
}
|
|
|
|
class SettingsSearchController {
|
|
static final SettingsSearchController inst = SettingsSearchController._internal();
|
|
SettingsSearchController._internal();
|
|
|
|
final _map = <SettingSubpageEnum, Map<int, GlobalKey>>{};
|
|
var _allWidgets = <(SettingSubpageProvider, Map<SettingKeysBase, List<String>>)>[];
|
|
final searchResults = <SettingSubpageEnum, List<SettingSearchResultItem>>{}.obs;
|
|
final subpagesDetails = <SettingSubpageEnum, CustomCollapsedListTile?>{};
|
|
|
|
RxBaseCore<bool> get canShowSearch => _canShowSearch;
|
|
final _canShowSearch = false.obs;
|
|
|
|
void closeSearch() {
|
|
_allWidgets.clear();
|
|
searchResults.clear();
|
|
_canShowSearch.value = false;
|
|
}
|
|
|
|
GlobalKey getSettingWidgetGlobalKey(SettingSubpageEnum settingPage, Enum key) {
|
|
final keyIndex = key.index;
|
|
final c = SettingsSearchController.inst;
|
|
final r = settingPage;
|
|
c._map[r] ??= {};
|
|
c._map[r]![keyIndex] ??= GlobalKey();
|
|
return c._map[r]![keyIndex]!;
|
|
}
|
|
|
|
void onSearchTap({required bool isOpen}) {
|
|
if (isOpen) {
|
|
const theme = ThemeSetting();
|
|
const indexer = IndexerSettings();
|
|
const playback = PlaybackSettings();
|
|
const customization = CustomizationSettings();
|
|
const youtube = YoutubeSettings();
|
|
const extras = ExtrasSettings();
|
|
const backupAndRestore = BackupAndRestore();
|
|
const advanced = AdvancedSettings();
|
|
_allWidgets = [
|
|
(theme, theme.lookupMap),
|
|
(indexer, indexer.lookupMap),
|
|
(playback, playback.lookupMap),
|
|
(customization, customization.lookupMap),
|
|
(youtube, youtube.lookupMap),
|
|
(extras, extras.lookupMap),
|
|
(backupAndRestore, backupAndRestore.lookupMap),
|
|
(advanced, advanced.lookupMap),
|
|
];
|
|
for (int i = 0; i < _allWidgets.length; i++) {
|
|
var p = _allWidgets[i];
|
|
subpagesDetails[p.$1.settingPage] = p.$1.settingPage.toSettingSubPageDetails();
|
|
}
|
|
_canShowSearch.value = true;
|
|
} else {
|
|
closeSearch();
|
|
}
|
|
}
|
|
|
|
void onSearchChanged(String val) {
|
|
final res = <SettingSubpageEnum, List<SettingSearchResultItem>>{};
|
|
_allWidgets.loop((widget) {
|
|
for (final e in widget.$2.entries) {
|
|
final match = e.value.any((element) => element.cleanUpForComparison.contains(val.cleanUpForComparison));
|
|
if (match) {
|
|
final p = widget.$1.settingPage;
|
|
res.addForce(
|
|
p,
|
|
SettingSearchResultItem(
|
|
page: p,
|
|
key: e.key as Enum,
|
|
titles: e.value,
|
|
),
|
|
);
|
|
}
|
|
}
|
|
});
|
|
searchResults.value = res;
|
|
}
|
|
|
|
Future<void> onResultTap({
|
|
required SettingSubpageEnum? settingPage,
|
|
required Enum key,
|
|
required BuildContext context,
|
|
}) async {
|
|
onSearchTap(isOpen: false);
|
|
|
|
final details = subpagesDetails[settingPage];
|
|
final page = settingPage?.toSettingSubPageDetails(initialItem: key)?.page;
|
|
if (NamidaNavigator.inst.currentRoute?.route == RouteType.SETTINGS_subpage) {
|
|
// -- navigate back if inside subpage.
|
|
// -- we can skip and just jump, but we
|
|
// -- need the blink animation & bgColor to update.
|
|
await NamidaNavigator.inst.popPage(waitForAnimation: true);
|
|
}
|
|
if (page != null) {
|
|
SettingsSubPage(
|
|
title: () => details?.title() ?? '',
|
|
child: page(),
|
|
).navigate();
|
|
}
|
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
|
final c = _map[settingPage]?[key.index]?.currentContext;
|
|
if (c != null) Scrollable.ensureVisible(c, alignment: 0.3);
|
|
});
|
|
}
|
|
}
|