mirror of
https://github.com/immich-app/immich.git
synced 2024-12-24 10:37:28 +02:00
235 lines
8.4 KiB
Dart
235 lines
8.4 KiB
Dart
|
import 'dart:io';
|
||
|
|
||
|
import 'package:easy_localization/easy_localization.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||
|
import 'package:immich_mobile/modules/backup/providers/backup.provider.dart';
|
||
|
import 'package:immich_mobile/modules/backup/providers/ios_background_settings.provider.dart';
|
||
|
import 'package:immich_mobile/modules/backup/ui/ios_debug_info_tile.dart';
|
||
|
import 'package:immich_mobile/modules/settings/ui/settings_button_list_tile.dart';
|
||
|
import 'package:immich_mobile/modules/settings/ui/settings_slider_list_tile.dart';
|
||
|
import 'package:immich_mobile/modules/settings/ui/settings_switch_list_tile.dart';
|
||
|
import 'package:permission_handler/permission_handler.dart';
|
||
|
import 'package:url_launcher/url_launcher.dart';
|
||
|
|
||
|
class BackgroundBackupSettings extends ConsumerWidget {
|
||
|
const BackgroundBackupSettings({super.key});
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||
|
final isBackgroundEnabled =
|
||
|
ref.watch(backupProvider.select((s) => s.backgroundBackup));
|
||
|
final iosSettings = ref.watch(iOSBackgroundSettingsProvider);
|
||
|
|
||
|
void showErrorToUser(String msg) {
|
||
|
final snackBar = SnackBar(
|
||
|
content: Text(
|
||
|
msg.tr(),
|
||
|
style: context.textTheme.bodyLarge?.copyWith(
|
||
|
color: context.primaryColor,
|
||
|
),
|
||
|
),
|
||
|
backgroundColor: Colors.red,
|
||
|
);
|
||
|
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||
|
}
|
||
|
|
||
|
void showBatteryOptimizationInfoToUser() {
|
||
|
showDialog<void>(
|
||
|
context: context,
|
||
|
barrierDismissible: false,
|
||
|
builder: (BuildContext ctx) {
|
||
|
return AlertDialog(
|
||
|
title: const Text(
|
||
|
'backup_controller_page_background_battery_info_title',
|
||
|
).tr(),
|
||
|
content: SingleChildScrollView(
|
||
|
child: const Text(
|
||
|
'backup_controller_page_background_battery_info_message',
|
||
|
).tr(),
|
||
|
),
|
||
|
actions: [
|
||
|
ElevatedButton(
|
||
|
onPressed: () => launchUrl(
|
||
|
Uri.parse('https://dontkillmyapp.com'),
|
||
|
mode: LaunchMode.externalApplication,
|
||
|
),
|
||
|
child: const Text(
|
||
|
"backup_controller_page_background_battery_info_link",
|
||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||
|
).tr(),
|
||
|
),
|
||
|
ElevatedButton(
|
||
|
child: const Text(
|
||
|
'backup_controller_page_background_battery_info_ok',
|
||
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||
|
).tr(),
|
||
|
onPressed: () => ctx.pop(),
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
},
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (!isBackgroundEnabled) {
|
||
|
return SettingsButtonListTile(
|
||
|
icon: Icons.cloud_sync_outlined,
|
||
|
title: 'backup_controller_page_background_is_off'.tr(),
|
||
|
subtileText: 'backup_controller_page_background_description'.tr(),
|
||
|
buttonText: 'backup_controller_page_background_turn_on'.tr(),
|
||
|
onButtonTap: () =>
|
||
|
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||
|
enabled: true,
|
||
|
onError: showErrorToUser,
|
||
|
onBatteryInfo: showBatteryOptimizationInfoToUser,
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return Column(
|
||
|
children: [
|
||
|
if (!Platform.isIOS || iosSettings?.appRefreshEnabled == true)
|
||
|
_BackgroundSettingsEnabled(
|
||
|
onError: showErrorToUser,
|
||
|
onBatteryInfo: showBatteryOptimizationInfoToUser,
|
||
|
),
|
||
|
if (Platform.isIOS && iosSettings?.appRefreshEnabled != true)
|
||
|
_IOSBackgroundRefreshDisabled(),
|
||
|
if (Platform.isIOS && iosSettings != null)
|
||
|
IosDebugInfoTile(settings: iosSettings),
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class _IOSBackgroundRefreshDisabled extends StatelessWidget {
|
||
|
@override
|
||
|
Widget build(BuildContext context) {
|
||
|
return SettingsButtonListTile(
|
||
|
icon: Icons.task_outlined,
|
||
|
title:
|
||
|
'backup_controller_page_background_app_refresh_disabled_title'.tr(),
|
||
|
subtileText:
|
||
|
'backup_controller_page_background_app_refresh_disabled_content'.tr(),
|
||
|
buttonText:
|
||
|
'backup_controller_page_background_app_refresh_enable_button_text'
|
||
|
.tr(),
|
||
|
onButtonTap: () => openAppSettings(),
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class _BackgroundSettingsEnabled extends HookConsumerWidget {
|
||
|
final void Function(String msg) onError;
|
||
|
final void Function() onBatteryInfo;
|
||
|
|
||
|
const _BackgroundSettingsEnabled({
|
||
|
required this.onError,
|
||
|
required this.onBatteryInfo,
|
||
|
});
|
||
|
|
||
|
@override
|
||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||
|
final isWifiRequired =
|
||
|
ref.watch(backupProvider.select((s) => s.backupRequireWifi));
|
||
|
final isWifiRequiredNotifier = useValueNotifier(isWifiRequired);
|
||
|
useValueChanged(
|
||
|
isWifiRequired,
|
||
|
(_, __) => WidgetsBinding.instance.addPostFrameCallback(
|
||
|
(_) => isWifiRequiredNotifier.value = isWifiRequired,
|
||
|
),
|
||
|
);
|
||
|
|
||
|
final isChargingRequired =
|
||
|
ref.watch(backupProvider.select((s) => s.backupRequireCharging));
|
||
|
final isChargingRequiredNotifier = useValueNotifier(isChargingRequired);
|
||
|
useValueChanged(
|
||
|
isChargingRequired,
|
||
|
(_, __) => WidgetsBinding.instance.addPostFrameCallback(
|
||
|
(_) => isChargingRequiredNotifier.value = isChargingRequired,
|
||
|
),
|
||
|
);
|
||
|
|
||
|
int backupDelayToSliderValue(int ms) => switch (ms) {
|
||
|
5000 => 0,
|
||
|
30000 => 1,
|
||
|
120000 => 2,
|
||
|
_ => 3,
|
||
|
};
|
||
|
|
||
|
int backupDelayToMilliseconds(int v) =>
|
||
|
switch (v) { 0 => 5000, 1 => 30000, 2 => 120000, _ => 600000 };
|
||
|
|
||
|
String formatBackupDelaySliderValue(int v) => switch (v) {
|
||
|
0 => 'setting_notifications_notify_seconds'.tr(args: const ['5']),
|
||
|
1 => 'setting_notifications_notify_seconds'.tr(args: const ['30']),
|
||
|
2 => 'setting_notifications_notify_minutes'.tr(args: const ['2']),
|
||
|
_ => 'setting_notifications_notify_minutes'.tr(args: const ['10']),
|
||
|
};
|
||
|
|
||
|
final backupTriggerDelay =
|
||
|
ref.watch(backupProvider.select((s) => s.backupTriggerDelay));
|
||
|
final triggerDelay = useState(backupDelayToSliderValue(backupTriggerDelay));
|
||
|
useValueChanged(
|
||
|
triggerDelay.value,
|
||
|
(_, __) => ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||
|
triggerDelay: backupDelayToMilliseconds(triggerDelay.value),
|
||
|
onError: onError,
|
||
|
onBatteryInfo: onBatteryInfo,
|
||
|
),
|
||
|
);
|
||
|
|
||
|
return SettingsButtonListTile(
|
||
|
icon: Icons.cloud_sync_rounded,
|
||
|
iconColor: context.primaryColor,
|
||
|
title: 'backup_controller_page_background_is_on'.tr(),
|
||
|
buttonText: 'backup_controller_page_background_turn_off'.tr(),
|
||
|
onButtonTap: () =>
|
||
|
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||
|
enabled: false,
|
||
|
onError: onError,
|
||
|
onBatteryInfo: onBatteryInfo,
|
||
|
),
|
||
|
subtitle: Column(
|
||
|
children: [
|
||
|
SettingsSwitchListTile(
|
||
|
valueNotifier: isWifiRequiredNotifier,
|
||
|
title: 'backup_controller_page_background_wifi'.tr(),
|
||
|
icon: Icons.wifi,
|
||
|
onChanged: (enabled) =>
|
||
|
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||
|
requireWifi: enabled,
|
||
|
onError: onError,
|
||
|
onBatteryInfo: onBatteryInfo,
|
||
|
),
|
||
|
),
|
||
|
SettingsSwitchListTile(
|
||
|
valueNotifier: isChargingRequiredNotifier,
|
||
|
title: 'backup_controller_page_background_charging'.tr(),
|
||
|
icon: Icons.charging_station,
|
||
|
onChanged: (enabled) =>
|
||
|
ref.read(backupProvider.notifier).configureBackgroundBackup(
|
||
|
requireCharging: enabled,
|
||
|
onError: onError,
|
||
|
onBatteryInfo: onBatteryInfo,
|
||
|
),
|
||
|
),
|
||
|
if (Platform.isAndroid)
|
||
|
SettingsSliderListTile(
|
||
|
valueNotifier: triggerDelay,
|
||
|
text: 'backup_controller_page_background_delay'.tr(
|
||
|
args: [formatBackupDelaySliderValue(triggerDelay.value)],
|
||
|
),
|
||
|
maxValue: 3.0,
|
||
|
noDivisons: 3,
|
||
|
label: formatBackupDelaySliderValue(triggerDelay.value),
|
||
|
),
|
||
|
],
|
||
|
),
|
||
|
);
|
||
|
}
|
||
|
}
|