nc-photos/app/lib/widget/settings.dart

262 lines
9.5 KiB
Dart
Raw Normal View History

2022-07-29 00:59:26 +08:00
import 'dart:async';
2021-04-10 12:28:12 +08:00
import 'package:flutter/material.dart';
2023-06-06 21:39:58 +08:00
import 'package:flutter_bloc/flutter_bloc.dart';
2021-04-10 12:28:12 +08:00
import 'package:logging/logging.dart';
2021-07-25 13:00:38 +08:00
import 'package:nc_photos/app_localizations.dart';
2023-06-06 21:39:58 +08:00
import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/debug_util.dart';
2021-04-10 12:28:12 +08:00
import 'package:nc_photos/k.dart' as k;
2021-06-23 16:15:25 +08:00
import 'package:nc_photos/language_util.dart' as language_util;
2022-04-09 03:16:10 +08:00
import 'package:nc_photos/mobile/platform.dart'
if (dart.library.html) 'package:nc_photos/web/platform.dart' as platform;
import 'package:nc_photos/platform/features.dart' as features;
2022-04-09 03:16:10 +08:00
import 'package:nc_photos/platform/notification.dart';
2023-06-06 21:39:58 +08:00
import 'package:nc_photos/stream_util.dart';
2022-07-08 17:38:24 +08:00
import 'package:nc_photos/url_launcher_util.dart';
import 'package:nc_photos/widget/list_tile_center_leading.dart';
2023-08-05 03:12:29 +08:00
import 'package:nc_photos/widget/settings/collection_settings.dart';
2023-05-30 00:55:10 +08:00
import 'package:nc_photos/widget/settings/developer_settings.dart';
2023-08-14 23:07:09 +08:00
import 'package:nc_photos/widget/settings/enhancement_settings.dart';
import 'package:nc_photos/widget/settings/expert_settings.dart';
2023-06-06 21:39:58 +08:00
import 'package:nc_photos/widget/settings/language_settings.dart';
2023-07-27 23:14:50 +08:00
import 'package:nc_photos/widget/settings/metadata_settings.dart';
2023-08-09 22:45:32 +08:00
import 'package:nc_photos/widget/settings/misc_settings.dart';
2023-07-28 00:51:57 +08:00
import 'package:nc_photos/widget/settings/photos_settings.dart';
2023-06-10 18:44:02 +08:00
import 'package:nc_photos/widget/settings/settings_list_caption.dart';
import 'package:nc_photos/widget/settings/theme_settings.dart';
2023-08-05 03:11:41 +08:00
import 'package:nc_photos/widget/settings/viewer_settings.dart';
2022-12-16 23:01:04 +08:00
import 'package:np_codegen/np_codegen.dart';
2021-04-10 12:28:12 +08:00
2022-12-16 23:01:04 +08:00
part 'settings.g.dart';
2021-04-10 12:28:12 +08:00
class Settings extends StatefulWidget {
static const routeName = "/settings";
2024-10-28 20:35:40 +08:00
static Route buildRoute(RouteSettings settings) => MaterialPageRoute(
2023-08-14 23:21:18 +08:00
builder: (_) => const Settings(),
2024-10-28 20:35:40 +08:00
settings: settings,
2021-07-24 04:05:57 +08:00
);
2023-08-14 23:21:18 +08:00
const Settings({super.key});
2021-04-10 12:28:12 +08:00
@override
2023-08-14 23:21:18 +08:00
State<StatefulWidget> createState() => _SettingsState();
2021-04-10 12:28:12 +08:00
}
2022-12-16 23:01:04 +08:00
@npLog
2021-04-10 12:28:12 +08:00
class _SettingsState extends State<Settings> {
@override
2023-07-28 00:53:40 +08:00
Widget build(BuildContext context) {
final translator = L10n.global().translator;
2023-08-14 23:21:18 +08:00
return Scaffold(
body: CustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text(L10n.global().settingsWidgetTitle),
),
SliverList(
delegate: SliverChildListDelegate(
[
ValueStreamBuilder<language_util.AppLanguage>(
stream: context.read<PrefController>().language,
builder: (context, snapshot) => ListTile(
leading: const ListTileCenterLeading(
child: Icon(Icons.translate_outlined),
),
title: Text(L10n.global().settingsLanguageTitle),
subtitle: Text(snapshot.requireData.nativeName),
onTap: () {
Navigator.of(context)
.pushNamed(LanguageSettings.routeName);
},
2023-06-06 21:39:58 +08:00
),
2022-08-08 14:35:37 +08:00
),
2023-07-27 23:17:04 +08:00
_SubPageItem(
2023-08-14 23:21:18 +08:00
leading: const Icon(Icons.palette_outlined),
label: L10n.global().settingsThemeTitle,
description: L10n.global().settingsThemeDescription,
pageBuilder: () => const ThemeSettings(),
),
_SubPageItem(
leading: const Icon(Icons.local_offer_outlined),
label: L10n.global().settingsMetadataTitle,
pageBuilder: () => const MetadataSettings(),
),
2023-08-14 23:21:18 +08:00
_SubPageItem(
leading: const Icon(Icons.image_outlined),
label: L10n.global().photosTabLabel,
description: L10n.global().settingsPhotosDescription,
pageBuilder: () => const PhotosSettings(),
),
2023-07-27 23:17:04 +08:00
_SubPageItem(
2023-08-14 23:21:18 +08:00
leading: const Icon(Icons.grid_view_outlined),
label: L10n.global().collectionsTooltip,
pageBuilder: () => const CollectionSettings(),
),
_SubPageItem(
leading: const Icon(Icons.view_carousel_outlined),
label: L10n.global().settingsViewerTitle,
description: L10n.global().settingsViewerDescription,
pageBuilder: () => const ViewerSettings(),
),
if (features.isSupportEnhancement)
_SubPageItem(
leading: const Icon(Icons.auto_fix_high_outlined),
label: L10n.global().settingsImageEditTitle,
description: L10n.global().settingsImageEditDescription,
pageBuilder: () => const EnhancementSettings(),
),
_SubPageItem(
leading: const Icon(Icons.emoji_symbols_outlined),
label: L10n.global().settingsMiscellaneousTitle,
pageBuilder: () => const MiscSettings(),
),
_SubPageItem(
leading: const Icon(Icons.warning_amber),
label: L10n.global().settingsExpertTitle,
pageBuilder: () => const ExpertSettings(),
),
if (_isShowDevSettings)
_SubPageItem(
leading: const Icon(Icons.code_outlined),
label: "Developer options",
pageBuilder: () => const DeveloperSettings(),
),
SettingsListCaption(
label: L10n.global().settingsAboutSectionTitle,
),
ListTile(
2023-08-14 23:21:18 +08:00
title: Text(L10n.global().settingsVersionTitle),
subtitle: const Text(k.versionStr),
onTap: () {
2023-08-14 23:21:18 +08:00
if (!_isShowDevSettings && --_devSettingsUnlockCount <= 0) {
setState(() {
_isShowDevSettings = true;
});
}
},
2023-08-14 23:21:18 +08:00
),
ListTile(
title: Text(L10n.global().settingsSourceCodeTitle),
onTap: () {
launch(_sourceRepo);
},
),
ListTile(
2023-08-14 23:21:18 +08:00
title: Text(L10n.global().settingsBugReportTitle),
onTap: () {
2023-08-14 23:21:18 +08:00
launch(_bugReportUrl);
},
),
2023-08-14 23:21:18 +08:00
SwitchListTile(
title: Text(L10n.global().settingsCaptureLogsTitle),
subtitle: Text(L10n.global().settingsCaptureLogsDescription),
value: LogCapturer().isEnable,
onChanged: (value) => _onCaptureLogChanged(context, value),
),
if (translator.isNotEmpty)
ListTile(
title: Text(L10n.global().settingsTranslatorTitle),
subtitle: Text(translator),
onTap: () {
launch(_translationUrl);
},
)
else
ListTile(
title: const Text("Improve translation"),
subtitle: const Text("Help translating to your language"),
onTap: () {
launch(_translationUrl);
},
),
],
),
2021-04-10 12:28:12 +08:00
),
2023-08-14 23:21:18 +08:00
],
),
2021-04-10 12:28:12 +08:00
);
}
2022-07-29 02:45:43 +08:00
Future<void> _onCaptureLogChanged(BuildContext context, bool value) async {
if (value) {
final result = await showDialog<bool>(
context: context,
2022-11-12 17:55:33 +08:00
builder: (context) => AlertDialog(
content: Text(L10n.global().captureLogDetails),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(true);
},
child: Text(L10n.global().enableButtonLabel),
),
],
),
);
if (result == true) {
setState(() {
LogCapturer().start();
});
}
} else {
if (LogCapturer().isEnable) {
setState(() {
LogCapturer().stop().then((result) {
_onLogSaveSuccessful(result);
});
});
}
}
}
2022-04-09 03:16:10 +08:00
Future<void> _onLogSaveSuccessful(dynamic result) async {
final nm = platform.NotificationManager();
try {
await nm.notify(LogSaveSuccessfulNotification(result));
} catch (e, stacktrace) {
_log.shout("[_onLogSaveSuccessful] Failed showing platform notification",
e, stacktrace);
}
}
var _devSettingsUnlockCount = 3;
var _isShowDevSettings = false;
static const String _sourceRepo = "https://bit.ly/3LQerBv";
static const String _bugReportUrl = "https://bit.ly/3NANrr7";
static const String _translationUrl = "https://bit.ly/3NwmdSw";
2021-09-02 16:33:35 +08:00
}
2023-07-27 23:17:04 +08:00
class _SubPageItem extends StatelessWidget {
const _SubPageItem({
this.leading,
required this.label,
this.description,
required this.pageBuilder,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: leading == null ? null : ListTileCenterLeading(child: leading!),
title: Text(label),
subtitle: description == null ? null : Text(description!),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => pageBuilder(),
),
);
},
);
}
final Widget? leading;
final String label;
final String? description;
final Widget Function() pageBuilder;
}