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

271 lines
9.9 KiB
Dart
Raw Normal View History

2022-07-28 18:59:26 +02:00
import 'dart:async';
2021-04-10 06:28:12 +02:00
import 'package:flutter/material.dart';
2023-06-06 15:39:58 +02:00
import 'package:flutter_bloc/flutter_bloc.dart';
2021-04-10 06:28:12 +02:00
import 'package:logging/logging.dart';
2021-07-25 07:00:38 +02:00
import 'package:nc_photos/app_localizations.dart';
2023-06-06 15:39:58 +02:00
import 'package:nc_photos/controller/pref_controller.dart';
import 'package:nc_photos/debug_util.dart';
2021-04-10 06:28:12 +02:00
import 'package:nc_photos/k.dart' as k;
2021-06-23 10:15:25 +02:00
import 'package:nc_photos/language_util.dart' as language_util;
2022-04-08 21:16:10 +02: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-08 21:16:10 +02:00
import 'package:nc_photos/platform/notification.dart';
2023-06-06 15:39:58 +02:00
import 'package:nc_photos/stream_util.dart';
2022-07-08 11:38:24 +02:00
import 'package:nc_photos/url_launcher_util.dart';
import 'package:nc_photos/widget/list_tile_center_leading.dart';
2023-08-04 21:12:29 +02:00
import 'package:nc_photos/widget/settings/collection_settings.dart';
2023-05-29 18:55:10 +02:00
import 'package:nc_photos/widget/settings/developer_settings.dart';
2023-08-14 17:07:09 +02:00
import 'package:nc_photos/widget/settings/enhancement_settings.dart';
import 'package:nc_photos/widget/settings/expert_settings.dart';
2023-06-06 15:39:58 +02:00
import 'package:nc_photos/widget/settings/language_settings.dart';
2023-07-27 17:14:50 +02:00
import 'package:nc_photos/widget/settings/metadata_settings.dart';
2023-08-09 16:45:32 +02:00
import 'package:nc_photos/widget/settings/misc_settings.dart';
2023-07-27 18:51:57 +02:00
import 'package:nc_photos/widget/settings/photos_settings.dart';
2023-06-10 12:44:02 +02:00
import 'package:nc_photos/widget/settings/settings_list_caption.dart';
import 'package:nc_photos/widget/settings/theme_settings.dart';
2023-08-04 21:11:41 +02:00
import 'package:nc_photos/widget/settings/viewer_settings.dart';
2022-12-16 16:01:04 +01:00
import 'package:np_codegen/np_codegen.dart';
2021-04-10 06:28:12 +02:00
2022-12-16 16:01:04 +01:00
part 'settings.g.dart';
2021-04-10 06:28:12 +02:00
class Settings extends StatefulWidget {
static const routeName = "/settings";
2023-08-14 17:21:18 +02:00
static Route buildRoute() => MaterialPageRoute(
builder: (_) => const Settings(),
2021-07-23 22:05:57 +02:00
);
2023-08-14 17:21:18 +02:00
const Settings({super.key});
2021-04-10 06:28:12 +02:00
@override
2023-08-14 17:21:18 +02:00
State<StatefulWidget> createState() => _SettingsState();
2021-04-10 06:28:12 +02:00
}
2022-12-16 16:01:04 +01:00
@npLog
2021-04-10 06:28:12 +02:00
class _SettingsState extends State<Settings> {
@override
2023-07-27 18:53:40 +02:00
Widget build(BuildContext context) {
final translator = L10n.global().translator;
2023-08-14 17:21:18 +02: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 15:39:58 +02:00
),
2022-08-08 08:35:37 +02:00
),
2023-07-27 17:17:04 +02:00
_SubPageItem(
2023-08-14 17:21:18 +02: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(),
),
_SubPageItem(
leading: const Icon(Icons.image_outlined),
label: L10n.global().photosTabLabel,
description: L10n.global().settingsPhotosDescription,
pageBuilder: () => const PhotosSettings(),
),
2023-07-27 17:17:04 +02:00
_SubPageItem(
2023-08-14 17:21:18 +02: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(),
),
// if (_enabledExperiments.isNotEmpty)
// _SubPageItem(
// leading: const Icon(Icons.science_outlined),
// label: L10n.global().settingsExperimentalTitle,
// description: L10n.global().settingsExperimentalDescription,
// pageBuilder: () => _ExperimentalSettings(),
// ),
_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 17:21:18 +02:00
title: Text(L10n.global().settingsVersionTitle),
subtitle: const Text(k.versionStr),
onTap: () {
2023-08-14 17:21:18 +02:00
if (!_isShowDevSettings && --_devSettingsUnlockCount <= 0) {
setState(() {
_isShowDevSettings = true;
});
}
},
2023-08-14 17:21:18 +02:00
),
ListTile(
title: Text(L10n.global().settingsSourceCodeTitle),
onTap: () {
launch(_sourceRepo);
},
),
ListTile(
2023-08-14 17:21:18 +02:00
title: Text(L10n.global().settingsBugReportTitle),
onTap: () {
2023-08-14 17:21:18 +02:00
launch(_bugReportUrl);
},
),
2023-08-14 17:21:18 +02: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 06:28:12 +02:00
),
2023-08-14 17:21:18 +02:00
],
),
2021-04-10 06:28:12 +02:00
);
}
2022-07-28 20:45:43 +02:00
Future<void> _onCaptureLogChanged(BuildContext context, bool value) async {
if (value) {
final result = await showDialog<bool>(
context: context,
2022-11-12 10:55:33 +01: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-08 21:16:10 +02: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 10:33:35 +02:00
}
2023-07-27 17:17:04 +02: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;
}
2023-05-17 19:42:08 +02:00
// final _enabledExperiments = [
// ];