Allow processing exif over data network

This commit is contained in:
Ming Ming 2022-06-08 02:51:37 +08:00
parent d63bdc4393
commit a3c92baca5
8 changed files with 124 additions and 6 deletions

View file

@ -0,0 +1,3 @@
extension FutureNotNullExtension<T> on Future<T?> {
Future<T> notNull() async => (await this)!;
}

View file

@ -309,6 +309,14 @@
"@settingsExifSupportTrueSubtitle": {
"description": "Subtitle of the EXIF support setting when the value is true. The goal is to warn user about the possible side effects of enabling this setting"
},
"settingsExifWifiOnlyTitle": "Process EXIF over Wi-Fi only",
"@settingsExifWifiOnlyTitle": {
"description": "Whether to only process EXIF data when connected to a Wi-Fi network"
},
"settingsExifWifiOnlyFalseSubtitle": "Data charges may apply",
"@settingsExifWifiOnlyFalseSubtitle": {
"description": "Shown when users allow processing exif data over any network"
},
"settingsMemoriesTitle": "Memories",
"@settingsMemoriesTitle": {
"description": "Memory albums contain photos taken in a specific time range in the past"

View file

@ -1,5 +1,7 @@
{
"cs": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsMemoriesTitle",
"settingsMemoriesSubtitle",
"settingsAccountTitle",
@ -110,6 +112,8 @@
],
"de": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsMemoriesTitle",
"settingsMemoriesSubtitle",
"settingsAccountTitle",
@ -235,6 +239,8 @@
"el": [
"collectionsTooltip",
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsMemoriesTitle",
"settingsMemoriesSubtitle",
"settingsAccountTitle",
@ -413,6 +419,8 @@
],
"es": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -442,6 +450,8 @@
],
"fi": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsMiscellaneousTitle",
"settingsMiscellaneousPageTitle",
"settingsPhotosTabSortByNameTitle",
@ -454,6 +464,8 @@
"fr": [
"collectionsTooltip",
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -482,6 +494,8 @@
],
"pl": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -528,6 +542,8 @@
],
"pt": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -553,6 +569,8 @@
],
"ru": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -578,6 +596,8 @@
],
"zh": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",
@ -603,6 +623,8 @@
],
"zh_Hant": [
"settingsExifWifiOnlyTitle",
"settingsExifWifiOnlyFalseSubtitle",
"settingsPhotoEnhancementTitle",
"settingsPhotoEnhancementPageTitle",
"settingsEnhanceMaxResolutionTitle",

View file

@ -32,7 +32,8 @@ class MetadataTask {
for (final r in account.roots) {
final dir = File(path: file_util.unstripPath(account, r));
hasScanShareFolder |= file_util.isOrUnderDir(shareFolder, dir);
final op = UpdateMissingMetadata(fileRepo);
final op = UpdateMissingMetadata(
fileRepo, const _UpdateMissingMetadataConfigProvider());
await for (final _ in op(account, dir)) {
if (!Pref().isEnableExifOr()) {
_log.info("[call] EXIF disabled, task ending immaturely");
@ -42,7 +43,8 @@ class MetadataTask {
}
}
if (!hasScanShareFolder) {
final op = UpdateMissingMetadata(fileRepo);
final op = UpdateMissingMetadata(
fileRepo, const _UpdateMissingMetadataConfigProvider());
await for (final _ in op(
account,
shareFolder,
@ -117,3 +119,11 @@ class MetadataTaskManager {
static MetadataTaskManager? _inst;
}
class _UpdateMissingMetadataConfigProvider
implements UpdateMissingMetadataConfigProvider {
const _UpdateMissingMetadataConfigProvider();
@override
isWifiOnly() async => Pref().shouldProcessExifWifiOnlyOr();
}

View file

@ -208,6 +208,15 @@ class Pref {
value,
(key, value) => provider.setBool(key, value));
bool? shouldProcessExifWifiOnly() =>
provider.getBool(PrefKey.shouldProcessExifWifiOnly);
bool shouldProcessExifWifiOnlyOr([bool def = true]) =>
shouldProcessExifWifiOnly() ?? def;
Future<bool> setProcessExifWifiOnly(bool value) => _set<bool>(
PrefKey.shouldProcessExifWifiOnly,
value,
(key, value) => provider.setBool(key, value));
Future<bool> _set<T>(PrefKey key, T value,
Future<bool> Function(PrefKey key, T value) setFn) async {
if (await setFn(key, value)) {
@ -502,6 +511,7 @@ enum PrefKey {
hasShownEnhanceInfo,
firstRunTime,
isPhotosTabSortByName,
shouldProcessExifWifiOnly,
// account pref
isEnableFaceRecognitionApp,
@ -566,6 +576,8 @@ extension on PrefKey {
return "firstRunTime";
case PrefKey.isPhotosTabSortByName:
return "isPhotosTabSortByName";
case PrefKey.shouldProcessExifWifiOnly:
return "shouldProcessExifWifiOnly";
// account pref
case PrefKey.isEnableFaceRecognitionApp:

View file

@ -13,6 +13,7 @@ import 'package:nc_photos/entity/file/data_source.dart';
import 'package:nc_photos/entity/file_util.dart' as file_util;
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/event/native_event.dart';
import 'package:nc_photos/future_extension.dart';
import 'package:nc_photos/language_util.dart' as language_util;
import 'package:nc_photos/pref.dart';
import 'package:nc_photos/use_case/update_missing_metadata.dart';
@ -35,6 +36,9 @@ Future<void> startService() async {
onBackground: () => throw UnimplementedError(),
),
);
// sync settings
await ServiceConfig.setProcessExifWifiOnly(
Pref().shouldProcessExifWifiOnlyOr());
await service.start();
}
@ -54,6 +58,12 @@ void serviceMain() async {
await _Service()();
}
class ServiceConfig {
static Future<void> setProcessExifWifiOnly(bool flag) async {
await Preference.setBool(_servicePref, _servicePrefProcessWifiOnly, flag);
}
}
class _Service {
Future<void> call() async {
final service = FlutterBackgroundService();
@ -229,7 +239,8 @@ class _MetadataTask {
for (final r in account.roots) {
final dir = File(path: file_util.unstripPath(account, r));
hasScanShareFolder |= file_util.isOrUnderDir(shareFolder, dir);
final updater = UpdateMissingMetadata(fileRepo);
final updater = UpdateMissingMetadata(
fileRepo, const _UpdateMissingMetadataConfigProvider());
void onServiceStop() {
_log.info("[_updateMetadata] Stopping task: user canceled");
updater.stop();
@ -247,7 +258,8 @@ class _MetadataTask {
}
}
if (!hasScanShareFolder) {
final shareUpdater = UpdateMissingMetadata(fileRepo);
final shareUpdater = UpdateMissingMetadata(
fileRepo, const _UpdateMissingMetadataConfigProvider());
void onServiceStop() {
_log.info("[_updateMetadata] Stopping task: user canceled");
shareUpdater.stop();
@ -295,7 +307,20 @@ class _MetadataTask {
static final _log = Logger("service._MetadataTask");
}
class _UpdateMissingMetadataConfigProvider
implements UpdateMissingMetadataConfigProvider {
const _UpdateMissingMetadataConfigProvider();
@override
isWifiOnly() =>
Preference.getBool(_servicePref, _servicePrefProcessWifiOnly, true)
.notNull();
}
const _dataKeyEvent = "event";
const _eventStop = "stop";
const _servicePref = "service";
const _servicePrefProcessWifiOnly = "shouldProcessWifiOnly";
final _log = Logger("service");

View file

@ -14,8 +14,12 @@ import 'package:nc_photos/use_case/load_metadata.dart';
import 'package:nc_photos/use_case/scan_missing_metadata.dart';
import 'package:nc_photos/use_case/update_property.dart';
abstract class UpdateMissingMetadataConfigProvider {
Future<bool> isWifiOnly();
}
class UpdateMissingMetadata {
UpdateMissingMetadata(this.fileRepo);
UpdateMissingMetadata(this.fileRepo, this.configProvider);
/// Update metadata for all files that support one under a dir
///
@ -91,7 +95,8 @@ class UpdateMissingMetadata {
Future<void> _ensureWifi() async {
var count = 0;
while (!await connectivity_util.isWifi()) {
while (await configProvider.isWifiOnly() &&
!await connectivity_util.isWifi()) {
if (!_shouldRun) {
throw const InterruptedException();
}
@ -117,6 +122,7 @@ class UpdateMissingMetadata {
}
final FileRepo fileRepo;
final UpdateMissingMetadataConfigProvider configProvider;
bool _shouldRun = true;

View file

@ -15,6 +15,7 @@ import 'package:nc_photos/mobile/platform.dart'
import 'package:nc_photos/platform/k.dart' as platform_k;
import 'package:nc_photos/platform/notification.dart';
import 'package:nc_photos/pref.dart';
import 'package:nc_photos/service.dart';
import 'package:nc_photos/snack_bar_manager.dart';
import 'package:nc_photos/theme.dart';
import 'package:nc_photos/widget/fancy_option_picker.dart';
@ -63,6 +64,7 @@ class _SettingsState extends State<Settings> {
initState() {
super.initState();
_isEnableExif = Pref().isEnableExifOr();
_shouldProcessExifWifiOnly = Pref().shouldProcessExifWifiOnlyOr();
final settings = AccountPref.of(widget.account);
_isEnableMemoryAlbum = settings.isEnableMemoryAlbumOr(true);
@ -111,6 +113,15 @@ class _SettingsState extends State<Settings> {
value: _isEnableExif,
onChanged: (value) => _onExifSupportChanged(context, value),
),
if (platform_k.isMobile)
SwitchListTile(
title: Text(L10n.global().settingsExifWifiOnlyTitle),
subtitle: _shouldProcessExifWifiOnly
? null
: Text(L10n.global().settingsExifWifiOnlyFalseSubtitle),
value: _shouldProcessExifWifiOnly,
onChanged: _isEnableExif ? _onExifWifiOnlyChanged : null,
),
SwitchListTile(
title: Text(L10n.global().settingsMemoriesTitle),
subtitle: Text(L10n.global().settingsMemoriesSubtitle),
@ -322,6 +333,26 @@ class _SettingsState extends State<Settings> {
}
}
Future<void> _onExifWifiOnlyChanged(bool value) async {
_log.info("[_onExifWifiOnlyChanged] New value: $value");
final oldValue = _shouldProcessExifWifiOnly;
setState(() {
_shouldProcessExifWifiOnly = value;
});
if (!await Pref().setProcessExifWifiOnly(value)) {
_log.severe("[_onExifWifiOnlyChanged] Failed writing pref");
SnackBarManager().showSnackBar(SnackBar(
content: Text(L10n.global().writePreferenceFailureNotification),
duration: k.snackBarDurationNormal,
));
setState(() {
_shouldProcessExifWifiOnly = oldValue;
});
} else {
ServiceConfig.setProcessExifWifiOnly(value);
}
}
Future<void> _onEnableMemoryAlbumChanged(bool value) async {
_log.info("[_onEnableMemoryAlbumChanged] New value: $value");
final oldValue = _isEnableMemoryAlbum;
@ -408,6 +439,7 @@ class _SettingsState extends State<Settings> {
}
late bool _isEnableExif;
late bool _shouldProcessExifWifiOnly;
late bool _isEnableMemoryAlbum;
late final _prefUpdatedListener =