mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
feat: network requirement option for upload (#20302)
* wifi toggle * feat: network requirement option for upload * chore: put back holding queue previous config numbers * options * backup option page * pr feedback
This commit is contained in:
parent
47a025f39f
commit
10e9c278ee
@ -580,8 +580,10 @@
|
|||||||
"backup_manual_in_progress": "Upload already in progress. Try after sometime",
|
"backup_manual_in_progress": "Upload already in progress. Try after sometime",
|
||||||
"backup_manual_success": "Success",
|
"backup_manual_success": "Success",
|
||||||
"backup_manual_title": "Upload status",
|
"backup_manual_title": "Upload status",
|
||||||
|
"backup_options": "Backup Options",
|
||||||
"backup_options_page_title": "Backup options",
|
"backup_options_page_title": "Backup options",
|
||||||
"backup_setting_subtitle": "Manage background and foreground upload settings",
|
"backup_setting_subtitle": "Manage background and foreground upload settings",
|
||||||
|
"backup_settings_subtitle": "Manage upload settings",
|
||||||
"backward": "Backward",
|
"backward": "Backward",
|
||||||
"beta_sync": "Beta Sync Status",
|
"beta_sync": "Beta Sync Status",
|
||||||
"beta_sync_subtitle": "Manage the new sync system",
|
"beta_sync_subtitle": "Manage the new sync system",
|
||||||
@ -1312,6 +1314,9 @@
|
|||||||
"my_albums": "My albums",
|
"my_albums": "My albums",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"name_or_nickname": "Name or nickname",
|
"name_or_nickname": "Name or nickname",
|
||||||
|
"network_requirement_photos_upload": "Use cellular data to backup photos",
|
||||||
|
"network_requirement_videos_upload": "Use cellular data to backup videos",
|
||||||
|
"network_requirements_updated": "Network requirements changed, resetting backup queue",
|
||||||
"networking_settings": "Networking",
|
"networking_settings": "Networking",
|
||||||
"networking_subtitle": "Manage the server endpoint settings",
|
"networking_subtitle": "Manage the server endpoint settings",
|
||||||
"never": "Never",
|
"never": "Never",
|
||||||
|
@ -71,7 +71,9 @@ enum StoreKey<T> {
|
|||||||
photoManagerCustomFilter<bool>._(1000),
|
photoManagerCustomFilter<bool>._(1000),
|
||||||
betaPromptShown<bool>._(1001),
|
betaPromptShown<bool>._(1001),
|
||||||
betaTimeline<bool>._(1002),
|
betaTimeline<bool>._(1002),
|
||||||
enableBackup<bool>._(1003);
|
enableBackup<bool>._(1003),
|
||||||
|
useWifiForUploadVideos<bool>._(1004),
|
||||||
|
useWifiForUploadPhotos<bool>._(1005);
|
||||||
|
|
||||||
const StoreKey._(this.id);
|
const StoreKey._(this.id);
|
||||||
final int id;
|
final int id;
|
||||||
|
@ -91,10 +91,9 @@ Future<void> initApp() async {
|
|||||||
initializeTimeZones();
|
initializeTimeZones();
|
||||||
|
|
||||||
// Initialize the file downloader
|
// Initialize the file downloader
|
||||||
|
|
||||||
await FileDownloader().configure(
|
await FileDownloader().configure(
|
||||||
// maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3
|
// maxConcurrent: 6, maxConcurrentByHost(server):6, maxConcurrentByGroup: 3
|
||||||
globalConfig: (Config.holdingQueue, (1000, 1000, 1000)),
|
globalConfig: (Config.holdingQueue, (6, 6, 3)),
|
||||||
);
|
);
|
||||||
|
|
||||||
await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false);
|
await FileDownloader().trackTasksInGroup(kDownloadGroupLivePhoto, markDownloadedComplete: false);
|
||||||
|
@ -65,6 +65,15 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||||||
splashRadius: 24,
|
splashRadius: 24,
|
||||||
icon: const Icon(Icons.arrow_back_ios_rounded),
|
icon: const Icon(Icons.arrow_back_ios_rounded),
|
||||||
),
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
context.pushRoute(const DriftBackupOptionsRoute());
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.settings_outlined),
|
||||||
|
tooltip: "backup_options".t(context: context),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
68
mobile/lib/pages/backup/drift_backup_options.page.dart
Normal file
68
mobile/lib/pages/backup/drift_backup_options.page.dart
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
|
import 'package:immich_mobile/providers/user.provider.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
|
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class DriftBackupOptionsPage extends ConsumerWidget {
|
||||||
|
const DriftBackupOptionsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
bool hasPopped = false;
|
||||||
|
final previousWifiReqForVideos = Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false;
|
||||||
|
final previousWifiReqForPhotos = Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false;
|
||||||
|
return PopScope(
|
||||||
|
onPopInvokedWithResult: (didPop, result) async {
|
||||||
|
// There is an issue with Flutter where the pop event
|
||||||
|
// can be triggered multiple times, so we guard it with _hasPopped
|
||||||
|
|
||||||
|
final currentWifiReqForVideos = Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false;
|
||||||
|
final currentWifiReqForPhotos = Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false;
|
||||||
|
|
||||||
|
if (currentWifiReqForVideos == previousWifiReqForVideos &&
|
||||||
|
currentWifiReqForPhotos == previousWifiReqForPhotos) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didPop && !hasPopped) {
|
||||||
|
hasPopped = true;
|
||||||
|
|
||||||
|
final currentUser = ref.read(currentUserProvider);
|
||||||
|
if (currentUser == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await ref.read(driftBackupProvider.notifier).getBackupStatus(currentUser.id);
|
||||||
|
final isBackupEnabled = ref.read(appSettingsServiceProvider).getSetting(AppSettingsEnum.enableBackup);
|
||||||
|
if (!isBackupEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text("network_requirements_updated".t(context: context)),
|
||||||
|
duration: const Duration(seconds: 4),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
final backupNotifier = ref.read(driftBackupProvider.notifier);
|
||||||
|
backupNotifier.cancel().then((_) {
|
||||||
|
backupNotifier.startBackup(currentUser.id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(title: Text("backup_options".t(context: context))),
|
||||||
|
body: const DriftBackupSettings(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
import 'package:flutter_hooks/flutter_hooks.dart' hide Store;
|
||||||
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
import 'package:immich_mobile/entities/store.entity.dart';
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
import 'package:immich_mobile/routing/router.dart';
|
import 'package:immich_mobile/routing/router.dart';
|
||||||
@ -9,6 +10,7 @@ import 'package:immich_mobile/widgets/settings/advanced_settings.dart';
|
|||||||
import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_settings.dart';
|
import 'package:immich_mobile/widgets/settings/asset_list_settings/asset_list_settings.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart';
|
import 'package:immich_mobile/widgets/settings/asset_viewer_settings/asset_viewer_settings.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/backup_settings/backup_settings.dart';
|
import 'package:immich_mobile/widgets/settings/backup_settings/backup_settings.dart';
|
||||||
|
import 'package:immich_mobile/widgets/settings/backup_settings/drift_backup_settings.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/beta_sync_settings/beta_sync_settings.dart';
|
import 'package:immich_mobile/widgets/settings/beta_sync_settings/beta_sync_settings.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/beta_timeline_list_tile.dart';
|
import 'package:immich_mobile/widgets/settings/beta_timeline_list_tile.dart';
|
||||||
import 'package:immich_mobile/widgets/settings/language_settings.dart';
|
import 'package:immich_mobile/widgets/settings/language_settings.dart';
|
||||||
@ -21,7 +23,7 @@ enum SettingSection {
|
|||||||
beta('beta_sync', Icons.sync_outlined, "beta_sync_subtitle"),
|
beta('beta_sync', Icons.sync_outlined, "beta_sync_subtitle"),
|
||||||
advanced('advanced', Icons.build_outlined, "advanced_settings_tile_subtitle"),
|
advanced('advanced', Icons.build_outlined, "advanced_settings_tile_subtitle"),
|
||||||
assetViewer('asset_viewer_settings_title', Icons.image_outlined, "asset_viewer_settings_subtitle"),
|
assetViewer('asset_viewer_settings_title', Icons.image_outlined, "asset_viewer_settings_subtitle"),
|
||||||
backup('backup', Icons.cloud_upload_outlined, "backup_setting_subtitle"),
|
backup('backup', Icons.cloud_upload_outlined, "backup_settings_subtitle"),
|
||||||
languages('language', Icons.language, "setting_languages_subtitle"),
|
languages('language', Icons.language, "setting_languages_subtitle"),
|
||||||
networking('networking_settings', Icons.wifi, "networking_subtitle"),
|
networking('networking_settings', Icons.wifi, "networking_subtitle"),
|
||||||
notifications('notifications', Icons.notifications_none_rounded, "setting_notifications_subtitle"),
|
notifications('notifications', Icons.notifications_none_rounded, "setting_notifications_subtitle"),
|
||||||
@ -36,7 +38,8 @@ enum SettingSection {
|
|||||||
SettingSection.beta => const _BetaLandscapeToggle(),
|
SettingSection.beta => const _BetaLandscapeToggle(),
|
||||||
SettingSection.advanced => const AdvancedSettings(),
|
SettingSection.advanced => const AdvancedSettings(),
|
||||||
SettingSection.assetViewer => const AssetViewerSettings(),
|
SettingSection.assetViewer => const AssetViewerSettings(),
|
||||||
SettingSection.backup => const BackupSettings(),
|
SettingSection.backup =>
|
||||||
|
Store.tryGet(StoreKey.betaTimeline) ?? false ? const DriftBackupSettings() : const BackupSettings(),
|
||||||
SettingSection.languages => const LanguageSettings(),
|
SettingSection.languages => const LanguageSettings(),
|
||||||
SettingSection.networking => const NetworkingSettings(),
|
SettingSection.networking => const NetworkingSettings(),
|
||||||
SettingSection.notifications => const NotificationSetting(),
|
SettingSection.notifications => const NotificationSetting(),
|
||||||
|
@ -187,12 +187,12 @@ class DriftBackupState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final driftBackupProvider = StateNotifierProvider<ExpBackupNotifier, DriftBackupState>((ref) {
|
final driftBackupProvider = StateNotifierProvider<DriftBackupNotifier, DriftBackupState>((ref) {
|
||||||
return ExpBackupNotifier(ref.watch(uploadServiceProvider));
|
return DriftBackupNotifier(ref.watch(uploadServiceProvider));
|
||||||
});
|
});
|
||||||
|
|
||||||
class ExpBackupNotifier extends StateNotifier<DriftBackupState> {
|
class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||||
ExpBackupNotifier(this._uploadService)
|
DriftBackupNotifier(this._uploadService)
|
||||||
: super(
|
: super(
|
||||||
const DriftBackupState(
|
const DriftBackupState(
|
||||||
totalCount: 0,
|
totalCount: 0,
|
||||||
|
@ -28,6 +28,7 @@ import 'package:immich_mobile/pages/backup/drift_backup.page.dart';
|
|||||||
import 'package:immich_mobile/pages/backup/backup_album_selection.page.dart';
|
import 'package:immich_mobile/pages/backup/backup_album_selection.page.dart';
|
||||||
import 'package:immich_mobile/pages/backup/backup_controller.page.dart';
|
import 'package:immich_mobile/pages/backup/backup_controller.page.dart';
|
||||||
import 'package:immich_mobile/pages/backup/backup_options.page.dart';
|
import 'package:immich_mobile/pages/backup/backup_options.page.dart';
|
||||||
|
import 'package:immich_mobile/pages/backup/drift_backup_options.page.dart';
|
||||||
import 'package:immich_mobile/pages/backup/drift_upload_detail.page.dart';
|
import 'package:immich_mobile/pages/backup/drift_upload_detail.page.dart';
|
||||||
import 'package:immich_mobile/pages/backup/failed_backup_status.page.dart';
|
import 'package:immich_mobile/pages/backup/failed_backup_status.page.dart';
|
||||||
import 'package:immich_mobile/pages/common/activities.page.dart';
|
import 'package:immich_mobile/pages/common/activities.page.dart';
|
||||||
@ -322,13 +323,12 @@ class AppRouter extends RootStackRouter {
|
|||||||
AutoRoute(page: DriftPlaceDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftPlaceDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: DriftUserSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftUserSelectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: ChangeExperienceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: ChangeExperienceRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
|
|
||||||
AutoRoute(page: DriftPartnerRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftPartnerRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: DriftUploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftUploadDetailRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: BetaSyncSettingsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: BetaSyncSettingsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
|
|
||||||
AutoRoute(page: DriftPeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
AutoRoute(page: DriftPeopleCollectionRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
AutoRoute(page: DriftPersonRoute.page, guards: [_authGuard]),
|
AutoRoute(page: DriftPersonRoute.page, guards: [_authGuard]),
|
||||||
|
AutoRoute(page: DriftBackupOptionsRoute.page, guards: [_authGuard, _duplicateGuard]),
|
||||||
// required to handle all deeplinks in deep_link.service.dart
|
// required to handle all deeplinks in deep_link.service.dart
|
||||||
// auto_route_library#1722
|
// auto_route_library#1722
|
||||||
RedirectRoute(path: '*', redirectTo: '/'),
|
RedirectRoute(path: '*', redirectTo: '/'),
|
||||||
|
@ -764,6 +764,22 @@ class DriftBackupAlbumSelectionRoute extends PageRouteInfo<void> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// generated route for
|
||||||
|
/// [DriftBackupOptionsPage]
|
||||||
|
class DriftBackupOptionsRoute extends PageRouteInfo<void> {
|
||||||
|
const DriftBackupOptionsRoute({List<PageRouteInfo>? children})
|
||||||
|
: super(DriftBackupOptionsRoute.name, initialChildren: children);
|
||||||
|
|
||||||
|
static const String name = 'DriftBackupOptionsRoute';
|
||||||
|
|
||||||
|
static PageInfo page = PageInfo(
|
||||||
|
name,
|
||||||
|
builder: (data) {
|
||||||
|
return const DriftBackupOptionsPage();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// generated route for
|
/// generated route for
|
||||||
/// [DriftBackupPage]
|
/// [DriftBackupPage]
|
||||||
class DriftBackupRoute extends PageRouteInfo<void> {
|
class DriftBackupRoute extends PageRouteInfo<void> {
|
||||||
|
@ -47,7 +47,9 @@ enum AppSettingsEnum<T> {
|
|||||||
autoEndpointSwitching<bool>(StoreKey.autoEndpointSwitching, null, false),
|
autoEndpointSwitching<bool>(StoreKey.autoEndpointSwitching, null, false),
|
||||||
photoManagerCustomFilter<bool>(StoreKey.photoManagerCustomFilter, null, true),
|
photoManagerCustomFilter<bool>(StoreKey.photoManagerCustomFilter, null, true),
|
||||||
betaTimeline<bool>(StoreKey.betaTimeline, null, false),
|
betaTimeline<bool>(StoreKey.betaTimeline, null, false),
|
||||||
enableBackup<bool>(StoreKey.enableBackup, null, false);
|
enableBackup<bool>(StoreKey.enableBackup, null, false),
|
||||||
|
useCellularForUploadVideos<bool>(StoreKey.useWifiForUploadVideos, null, false),
|
||||||
|
useCellularForUploadPhotos<bool>(StoreKey.useWifiForUploadPhotos, null, false);
|
||||||
|
|
||||||
const AppSettingsEnum(this.storeKey, this.hiveKey, this.defaultValue);
|
const AppSettingsEnum(this.storeKey, this.hiveKey, this.defaultValue);
|
||||||
|
|
||||||
|
@ -12,11 +12,13 @@ import 'package:immich_mobile/entities/store.entity.dart';
|
|||||||
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/backup.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/local_asset.repository.dart';
|
||||||
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
import 'package:immich_mobile/infrastructure/repositories/storage.repository.dart';
|
||||||
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/asset.provider.dart';
|
||||||
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
import 'package:immich_mobile/providers/infrastructure/storage.provider.dart';
|
||||||
import 'package:immich_mobile/repositories/upload.repository.dart';
|
import 'package:immich_mobile/repositories/upload.repository.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
final uploadServiceProvider = Provider((ref) {
|
final uploadServiceProvider = Provider((ref) {
|
||||||
@ -25,6 +27,7 @@ final uploadServiceProvider = Provider((ref) {
|
|||||||
ref.watch(backupRepositoryProvider),
|
ref.watch(backupRepositoryProvider),
|
||||||
ref.watch(storageRepositoryProvider),
|
ref.watch(storageRepositoryProvider),
|
||||||
ref.watch(localAssetRepository),
|
ref.watch(localAssetRepository),
|
||||||
|
ref.watch(appSettingsServiceProvider),
|
||||||
);
|
);
|
||||||
|
|
||||||
ref.onDispose(service.dispose);
|
ref.onDispose(service.dispose);
|
||||||
@ -32,7 +35,13 @@ final uploadServiceProvider = Provider((ref) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
class UploadService {
|
class UploadService {
|
||||||
UploadService(this._uploadRepository, this._backupRepository, this._storageRepository, this._localAssetRepository) {
|
UploadService(
|
||||||
|
this._uploadRepository,
|
||||||
|
this._backupRepository,
|
||||||
|
this._storageRepository,
|
||||||
|
this._localAssetRepository,
|
||||||
|
this._appSettingsService,
|
||||||
|
) {
|
||||||
_uploadRepository.onUploadStatus = _onUploadCallback;
|
_uploadRepository.onUploadStatus = _onUploadCallback;
|
||||||
_uploadRepository.onTaskProgress = _onTaskProgressCallback;
|
_uploadRepository.onTaskProgress = _onTaskProgressCallback;
|
||||||
}
|
}
|
||||||
@ -41,6 +50,7 @@ class UploadService {
|
|||||||
final DriftBackupRepository _backupRepository;
|
final DriftBackupRepository _backupRepository;
|
||||||
final StorageRepository _storageRepository;
|
final StorageRepository _storageRepository;
|
||||||
final DriftLocalAssetRepository _localAssetRepository;
|
final DriftLocalAssetRepository _localAssetRepository;
|
||||||
|
final AppSettingsService _appSettingsService;
|
||||||
|
|
||||||
final StreamController<TaskStatusUpdate> _taskStatusController = StreamController<TaskStatusUpdate>.broadcast();
|
final StreamController<TaskStatusUpdate> _taskStatusController = StreamController<TaskStatusUpdate>.broadcast();
|
||||||
final StreamController<TaskProgressUpdate> _taskProgressController = StreamController<TaskProgressUpdate>.broadcast();
|
final StreamController<TaskProgressUpdate> _taskProgressController = StreamController<TaskProgressUpdate>.broadcast();
|
||||||
@ -240,6 +250,14 @@ class UploadService {
|
|||||||
livePhotoVideoId: '',
|
livePhotoVideoId: '',
|
||||||
).toJson();
|
).toJson();
|
||||||
|
|
||||||
|
bool requiresWiFi = true;
|
||||||
|
|
||||||
|
if (asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadVideos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
|
} else if (!asset.isVideo && _appSettingsService.getSetting(AppSettingsEnum.useCellularForUploadPhotos)) {
|
||||||
|
requiresWiFi = false;
|
||||||
|
}
|
||||||
|
|
||||||
return buildUploadTask(
|
return buildUploadTask(
|
||||||
file,
|
file,
|
||||||
originalFileName: originalFileName,
|
originalFileName: originalFileName,
|
||||||
@ -248,6 +266,7 @@ class UploadService {
|
|||||||
group: group,
|
group: group,
|
||||||
priority: priority,
|
priority: priority,
|
||||||
isFavorite: asset.isFavorite,
|
isFavorite: asset.isFavorite,
|
||||||
|
requiresWiFi: requiresWiFi,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,12 +303,12 @@ class UploadService {
|
|||||||
String? metadata,
|
String? metadata,
|
||||||
int? priority,
|
int? priority,
|
||||||
bool? isFavorite,
|
bool? isFavorite,
|
||||||
|
bool requiresWiFi = true,
|
||||||
}) async {
|
}) async {
|
||||||
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
final serverEndpoint = Store.get(StoreKey.serverEndpoint);
|
||||||
final url = Uri.parse('$serverEndpoint/assets').toString();
|
final url = Uri.parse('$serverEndpoint/assets').toString();
|
||||||
final headers = ApiService.getRequestHeaders();
|
final headers = ApiService.getRequestHeaders();
|
||||||
final deviceId = Store.get(StoreKey.deviceId);
|
final deviceId = Store.get(StoreKey.deviceId);
|
||||||
|
|
||||||
final (baseDirectory, directory, filename) = await Task.split(filePath: file.path);
|
final (baseDirectory, directory, filename) = await Task.split(filePath: file.path);
|
||||||
final stats = await file.stat();
|
final stats = await file.stat();
|
||||||
final fileCreatedAt = stats.changed;
|
final fileCreatedAt = stats.changed;
|
||||||
@ -318,6 +337,7 @@ class UploadService {
|
|||||||
fileField: 'assetData',
|
fileField: 'assetData',
|
||||||
metaData: metadata ?? '',
|
metaData: metadata ?? '',
|
||||||
group: group,
|
group: group,
|
||||||
|
requiresWiFi: requiresWiFi,
|
||||||
priority: priority ?? 5,
|
priority: priority ?? 5,
|
||||||
updates: Updates.statusAndProgress,
|
updates: Updates.statusAndProgress,
|
||||||
retries: 3,
|
retries: 3,
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||||
|
import 'package:immich_mobile/entities/store.entity.dart';
|
||||||
|
import 'package:immich_mobile/extensions/build_context_extensions.dart';
|
||||||
|
import 'package:immich_mobile/extensions/translate_extensions.dart';
|
||||||
|
import 'package:immich_mobile/providers/app_settings.provider.dart';
|
||||||
|
import 'package:immich_mobile/services/app_settings.service.dart';
|
||||||
|
import 'package:immich_mobile/widgets/settings/settings_sub_page_scaffold.dart';
|
||||||
|
|
||||||
|
class DriftBackupSettings extends StatelessWidget {
|
||||||
|
const DriftBackupSettings({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const SettingsSubPageScaffold(settings: [_UseWifiForUploadVideosButton(), _UseWifiForUploadPhotosButton()]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UseWifiForUploadVideosButton extends ConsumerWidget {
|
||||||
|
const _UseWifiForUploadVideosButton();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final valueStream = Store.watch(StoreKey.useWifiForUploadVideos);
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"videos".t(context: context),
|
||||||
|
style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor),
|
||||||
|
),
|
||||||
|
subtitle: Text("network_requirement_videos_upload".t(context: context), style: context.textTheme.labelLarge),
|
||||||
|
trailing: StreamBuilder(
|
||||||
|
stream: valueStream,
|
||||||
|
initialData: Store.tryGet(StoreKey.useWifiForUploadVideos) ?? false,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final value = snapshot.data ?? false;
|
||||||
|
return Switch(
|
||||||
|
value: value,
|
||||||
|
onChanged: (bool newValue) async {
|
||||||
|
await ref
|
||||||
|
.read(appSettingsServiceProvider)
|
||||||
|
.setSetting(AppSettingsEnum.useCellularForUploadVideos, newValue);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UseWifiForUploadPhotosButton extends ConsumerWidget {
|
||||||
|
const _UseWifiForUploadPhotosButton();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final valueStream = Store.watch(StoreKey.useWifiForUploadPhotos);
|
||||||
|
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"photos".t(context: context),
|
||||||
|
style: context.textTheme.titleMedium?.copyWith(color: context.primaryColor),
|
||||||
|
),
|
||||||
|
subtitle: Text("network_requirement_photos_upload".t(context: context), style: context.textTheme.labelLarge),
|
||||||
|
trailing: StreamBuilder(
|
||||||
|
stream: valueStream,
|
||||||
|
initialData: Store.tryGet(StoreKey.useWifiForUploadPhotos) ?? false,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
final value = snapshot.data ?? false;
|
||||||
|
return Switch(
|
||||||
|
value: value,
|
||||||
|
onChanged: (bool newValue) async {
|
||||||
|
await ref
|
||||||
|
.read(appSettingsServiceProvider)
|
||||||
|
.setSetting(AppSettingsEnum.useCellularForUploadPhotos, newValue);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user