mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-02-02 06:46:22 +01:00
Allow processing exif over data network
This commit is contained in:
parent
d63bdc4393
commit
a3c92baca5
8 changed files with 124 additions and 6 deletions
3
app/lib/future_extension.dart
Normal file
3
app/lib/future_extension.dart
Normal file
|
@ -0,0 +1,3 @@
|
|||
extension FutureNotNullExtension<T> on Future<T?> {
|
||||
Future<T> notNull() async => (await this)!;
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 =
|
||||
|
|
Loading…
Reference in a new issue