diff --git a/mobile/android/app/src/main/AndroidManifest.xml b/mobile/android/app/src/main/AndroidManifest.xml index 58d7f0655a..eb81dc267b 100644 --- a/mobile/android/app/src/main/AndroidManifest.xml +++ b/mobile/android/app/src/main/AndroidManifest.xml @@ -6,7 +6,6 @@ android:maxSdkVersion="32" /> - @@ -125,4 +124,4 @@ - + \ No newline at end of file diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt index e7f787e8d8..8520413cff 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/BackgroundServicePlugin.kt @@ -1,40 +1,25 @@ package app.alextran.immich -import android.content.ContentResolver -import android.content.ContentUris -import android.content.ContentValues import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Build -import android.os.Bundle -import android.os.Environment -import android.provider.MediaStore -import android.provider.Settings import android.util.Log import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.embedding.engine.plugins.activity.ActivityAware -import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding import io.flutter.plugin.common.BinaryMessenger import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry import java.security.MessageDigest import java.io.FileInputStream import kotlinx.coroutines.* /** - * Android plugin for Dart `BackgroundService` and file trash operations + * Android plugin for Dart `BackgroundService` + * + * Receives messages/method calls from the foreground Dart side to manage + * the background service, e.g. start (enqueue), stop (cancel) */ -class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, ActivityAware, PluginRegistry.ActivityResultListener { +class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler { private var methodChannel: MethodChannel? = null - private var fileTrashChannel: MethodChannel? = null private var context: Context? = null - private var pendingResult: Result? = null - private val PERMISSION_REQUEST_CODE = 1001 - private var activityBinding: ActivityPluginBinding? = null override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { onAttachedToEngine(binding.applicationContext, binding.binaryMessenger) @@ -44,10 +29,6 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, context = ctx methodChannel = MethodChannel(messenger, "immich/foregroundChannel") methodChannel?.setMethodCallHandler(this) - - // Add file trash channel - fileTrashChannel = MethodChannel(messenger, "file_trash") - fileTrashChannel?.setMethodCallHandler(this) } override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { @@ -57,14 +38,11 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, private fun onDetachedFromEngine() { methodChannel?.setMethodCallHandler(null) methodChannel = null - fileTrashChannel?.setMethodCallHandler(null) - fileTrashChannel = null } - override fun onMethodCall(call: MethodCall, result: Result) { + override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { val ctx = context!! when (call.method) { - // Existing BackgroundService methods "enable" -> { val args = call.arguments>()!! ctx.getSharedPreferences(BackupWorker.SHARED_PREF_NAME, Context.MODE_PRIVATE) @@ -136,180 +114,10 @@ class BackgroundServicePlugin : FlutterPlugin, MethodChannel.MethodCallHandler, } } - // File Trash methods moved from MainActivity - "moveToTrash" -> { - val fileName = call.argument("fileName") - if (fileName != null) { - if (hasManageStoragePermission()) { - val success = moveToTrash(fileName) - result.success(success) - } else { - result.error("PERMISSION_DENIED", "Storage permission required", null) - } - } else { - result.error("INVALID_NAME", "The file name is not specified.", null) - } - } - - "restoreFromTrash" -> { - val fileName = call.argument("fileName") - if (fileName != null) { - if (hasManageStoragePermission()) { - val success = untrashImage(fileName) - result.success(success) - } else { - result.error("PERMISSION_DENIED", "Storage permission required", null) - } - } else { - result.error("INVALID_NAME", "The file name is not specified.", null) - } - } - - "requestManageStoragePermission" -> { - if (!hasManageStoragePermission()) { - requestManageStoragePermission(result) - } else { - Log.e("Manage storage permission", "Permission already granted") - result.success(true) - } - } - else -> result.notImplemented() } } - - // File Trash methods moved from MainActivity - private fun hasManageStoragePermission(): Boolean { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - Environment.isExternalStorageManager() - } else { - true - } - } - - private fun requestManageStoragePermission(result: Result) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - pendingResult = result // Store the result callback - val activity = activityBinding?.activity ?: return - - val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION) - intent.data = Uri.parse("package:${activity.packageName}") - activity.startActivityForResult(intent, PERMISSION_REQUEST_CODE) - } else { - result.success(true) - } - } - - private fun moveToTrash(fileName: String): Boolean { - val contentResolver = context?.contentResolver ?: return false - val uri = getFileUri(fileName) - Log.e("FILE_URI", uri.toString()) - return uri?.let { moveToTrash(it) } ?: false - } - - private fun moveToTrash(contentUri: Uri): Boolean { - val contentResolver = context?.contentResolver ?: return false - return try { - val values = ContentValues().apply { - put(MediaStore.MediaColumns.IS_TRASHED, 1) // Move to trash - } - val updated = contentResolver.update(contentUri, values, null, null) - updated > 0 - } catch (e: Exception) { - Log.e("TrashError", "Error moving to trash", e) - false - } - } - - private fun getFileUri(fileName: String): Uri? { - val contentResolver = context?.contentResolver ?: return null - val contentUri = MediaStore.Files.getContentUri("external") - val projection = arrayOf(MediaStore.Images.Media._ID) - val selection = "${MediaStore.Images.Media.DISPLAY_NAME} = ?" - val selectionArgs = arrayOf(fileName) - var fileUri: Uri? = null - - contentResolver.query(contentUri, projection, selection, selectionArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)) - fileUri = ContentUris.withAppendedId(contentUri, id) - } - } - return fileUri - } - - private fun untrashImage(name: String): Boolean { - val contentResolver = context?.contentResolver ?: return false - val uri = getTrashedFileUri(contentResolver, name) - Log.e("FILE_URI", uri.toString()) - return uri?.let { untrashImage(it) } ?: false - } - - private fun untrashImage(contentUri: Uri): Boolean { - val contentResolver = context?.contentResolver ?: return false - return try { - val values = ContentValues().apply { - put(MediaStore.MediaColumns.IS_TRASHED, 0) // Restore file - } - val updated = contentResolver.update(contentUri, values, null, null) - updated > 0 - } catch (e: Exception) { - Log.e("TrashError", "Error restoring file", e) - false - } - } - - private fun getTrashedFileUri(contentResolver: ContentResolver, fileName: String): Uri? { - val contentUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL) - val projection = arrayOf(MediaStore.Files.FileColumns._ID) - - val queryArgs = Bundle().apply { - putString(ContentResolver.QUERY_ARG_SQL_SELECTION, "${MediaStore.Files.FileColumns.DISPLAY_NAME} = ?") - putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, arrayOf(fileName)) - putInt(MediaStore.QUERY_ARG_MATCH_TRASHED, MediaStore.MATCH_ONLY) - } - - contentResolver.query(contentUri, projection, queryArgs, null)?.use { cursor -> - if (cursor.moveToFirst()) { - val id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns._ID)) - return ContentUris.withAppendedId(contentUri, id) - } - } - return null - } - - // ActivityAware implementation - override fun onAttachedToActivity(binding: ActivityPluginBinding) { - activityBinding = binding - binding.addActivityResultListener(this) - } - - override fun onDetachedFromActivityForConfigChanges() { - activityBinding?.removeActivityResultListener(this) - activityBinding = null - } - - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { - activityBinding = binding - binding.addActivityResultListener(this) - } - - override fun onDetachedFromActivity() { - activityBinding?.removeActivityResultListener(this) - activityBinding = null - } - - // ActivityResultListener implementation - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { - if (requestCode == PERMISSION_REQUEST_CODE) { - val granted = hasManageStoragePermission() - pendingResult?.success(granted) - pendingResult = null - return true - } - return false - } } private const val TAG = "BackgroundServicePlugin" -private const val BUFFER_SIZE = 2 * 1024 * 1024 +private const val BUFFER_SIZE = 2 * 1024 * 1024; diff --git a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt index 2b6bf81148..4ffb490c77 100644 --- a/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt +++ b/mobile/android/app/src/main/kotlin/app/alextran/immich/MainActivity.kt @@ -2,12 +2,14 @@ package app.alextran.immich import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine -import androidx.annotation.NonNull +import android.os.Bundle +import android.content.Intent class MainActivity : FlutterActivity() { - override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) { + + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) flutterEngine.plugins.add(BackgroundServicePlugin()) - // No need to set up method channel here as it's now handled in the plugin } + } diff --git a/mobile/lib/domain/models/store.model.dart b/mobile/lib/domain/models/store.model.dart index 8a5a908e0d..e6d9ecaf48 100644 --- a/mobile/lib/domain/models/store.model.dart +++ b/mobile/lib/domain/models/store.model.dart @@ -65,7 +65,6 @@ enum StoreKey { // Video settings loadOriginalVideo._(136), - manageLocalMediaAndroid._(137), // Experimental stuff photoManagerCustomFilter._(1000); diff --git a/mobile/lib/interfaces/local_files_manager.interface.dart b/mobile/lib/interfaces/local_files_manager.interface.dart deleted file mode 100644 index c8b83a7c93..0000000000 --- a/mobile/lib/interfaces/local_files_manager.interface.dart +++ /dev/null @@ -1,5 +0,0 @@ -abstract interface class ILocalFilesManager { - Future moveToTrash(String fileName); - Future restoreFromTrash(String fileName); - Future requestManageStoragePermission(); -} diff --git a/mobile/lib/providers/websocket.provider.dart b/mobile/lib/providers/websocket.provider.dart index 72dbda8b6f..f92d2c8421 100644 --- a/mobile/lib/providers/websocket.provider.dart +++ b/mobile/lib/providers/websocket.provider.dart @@ -23,7 +23,6 @@ enum PendingAction { assetDelete, assetUploaded, assetHidden, - assetTrash, } class PendingChange { @@ -161,7 +160,7 @@ class WebsocketNotifier extends StateNotifier { socket.on('on_upload_success', _handleOnUploadSuccess); socket.on('on_config_update', _handleOnConfigUpdate); socket.on('on_asset_delete', _handleOnAssetDelete); - socket.on('on_asset_trash', _handleOnAssetTrash); + socket.on('on_asset_trash', _handleServerUpdates); socket.on('on_asset_restore', _handleServerUpdates); socket.on('on_asset_update', _handleServerUpdates); socket.on('on_asset_stack_update', _handleServerUpdates); @@ -208,26 +207,6 @@ class WebsocketNotifier extends StateNotifier { _debounce.run(handlePendingChanges); } - Future _handlePendingTrashes() async { - final trashChanges = state.pendingChanges - .where((c) => c.action == PendingAction.assetTrash) - .toList(); - if (trashChanges.isNotEmpty) { - List remoteIds = trashChanges - .expand((a) => (a.value as List).map((e) => e.toString())) - .toList(); - - await _ref.read(syncServiceProvider).handleRemoteAssetRemoval(remoteIds); - await _ref.read(assetProvider.notifier).getAllAsset(); - - state = state.copyWith( - pendingChanges: state.pendingChanges - .whereNot((c) => trashChanges.contains(c)) - .toList(), - ); - } - } - Future _handlePendingDeletes() async { final deleteChanges = state.pendingChanges .where((c) => c.action == PendingAction.assetDelete) @@ -288,7 +267,6 @@ class WebsocketNotifier extends StateNotifier { await _handlePendingUploaded(); await _handlePendingDeletes(); await _handlingPendingHidden(); - await _handlePendingTrashes(); } void _handleOnConfigUpdate(dynamic _) { @@ -307,10 +285,6 @@ class WebsocketNotifier extends StateNotifier { void _handleOnAssetDelete(dynamic data) => addPendingChange(PendingAction.assetDelete, data); - void _handleOnAssetTrash(dynamic data) { - addPendingChange(PendingAction.assetTrash, data); - } - void _handleOnAssetHidden(dynamic data) => addPendingChange(PendingAction.assetHidden, data); diff --git a/mobile/lib/repositories/local_files_manager.repository.dart b/mobile/lib/repositories/local_files_manager.repository.dart deleted file mode 100644 index 522d7e7a05..0000000000 --- a/mobile/lib/repositories/local_files_manager.repository.dart +++ /dev/null @@ -1,23 +0,0 @@ -import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:immich_mobile/interfaces/local_files_manager.interface.dart'; -import 'package:immich_mobile/utils/local_files_manager.dart'; - -final localFilesManagerRepositoryProvider = - Provider((ref) => LocalFilesManagerRepository()); - -class LocalFilesManagerRepository implements ILocalFilesManager { - @override - Future moveToTrash(String fileName) async { - return await LocalFilesManager.moveToTrash(fileName); - } - - @override - Future restoreFromTrash(String fileName) async { - return await LocalFilesManager.restoreFromTrash(fileName); - } - - @override - Future requestManageStoragePermission() async { - return await LocalFilesManager.requestManageStoragePermission(); - } -} diff --git a/mobile/lib/services/app_settings.service.dart b/mobile/lib/services/app_settings.service.dart index 6413b69fce..cc57b8d3a3 100644 --- a/mobile/lib/services/app_settings.service.dart +++ b/mobile/lib/services/app_settings.service.dart @@ -61,7 +61,6 @@ enum AppSettingsEnum { 0, ), advancedTroubleshooting(StoreKey.advancedTroubleshooting, null, false), - manageLocalMediaAndroid(StoreKey.manageLocalMediaAndroid, null, false), logLevel(StoreKey.logLevel, null, 5), // Level.INFO = 5 preferRemoteImage(StoreKey.preferRemoteImage, null, false), loopVideo(StoreKey.loopVideo, "loopVideo", true), diff --git a/mobile/lib/services/sync.service.dart b/mobile/lib/services/sync.service.dart index 547e49c1a0..11a9dcb56a 100644 --- a/mobile/lib/services/sync.service.dart +++ b/mobile/lib/services/sync.service.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -17,10 +16,8 @@ import 'package:immich_mobile/interfaces/album_api.interface.dart'; import 'package:immich_mobile/interfaces/album_media.interface.dart'; import 'package:immich_mobile/interfaces/asset.interface.dart'; import 'package:immich_mobile/interfaces/etag.interface.dart'; -import 'package:immich_mobile/interfaces/local_files_manager.interface.dart'; import 'package:immich_mobile/interfaces/partner.interface.dart'; import 'package:immich_mobile/interfaces/partner_api.interface.dart'; -import 'package:immich_mobile/providers/app_settings.provider.dart'; import 'package:immich_mobile/providers/infrastructure/exif.provider.dart'; import 'package:immich_mobile/providers/infrastructure/user.provider.dart'; import 'package:immich_mobile/repositories/album.repository.dart'; @@ -28,10 +25,8 @@ import 'package:immich_mobile/repositories/album_api.repository.dart'; import 'package:immich_mobile/repositories/album_media.repository.dart'; import 'package:immich_mobile/repositories/asset.repository.dart'; import 'package:immich_mobile/repositories/etag.repository.dart'; -import 'package:immich_mobile/repositories/local_files_manager.repository.dart'; import 'package:immich_mobile/repositories/partner.repository.dart'; import 'package:immich_mobile/repositories/partner_api.repository.dart'; -import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/entity.service.dart'; import 'package:immich_mobile/services/hash.service.dart'; import 'package:immich_mobile/utils/async_mutex.dart'; @@ -53,8 +48,6 @@ final syncServiceProvider = Provider( ref.watch(userRepositoryProvider), ref.watch(userServiceProvider), ref.watch(etagRepositoryProvider), - ref.watch(appSettingsServiceProvider), - ref.watch(localFilesManagerRepositoryProvider), ref.watch(partnerApiRepositoryProvider), ref.watch(userApiRepositoryProvider), ), @@ -76,8 +69,6 @@ class SyncService { final IUserApiRepository _userApiRepository; final AsyncMutex _lock = AsyncMutex(); final Logger _log = Logger('SyncService'); - final AppSettingsService _appSettingsService; - final ILocalFilesManager _localFilesManager; SyncService( this._hashService, @@ -91,8 +82,6 @@ class SyncService { this._userRepository, this._userService, this._eTagRepository, - this._appSettingsService, - this._localFilesManager, this._partnerApiRepository, this._userApiRepository, ); @@ -249,19 +238,8 @@ class SyncService { return null; } - Future _moveToTrashMatchedAssets(Iterable idsToDelete) async { - final List localAssets = await _assetRepository.getAllLocal(); - final List matchedAssets = localAssets - .where((asset) => idsToDelete.contains(asset.remoteId)) - .toList(); - - for (var asset in matchedAssets) { - _localFilesManager.moveToTrash(asset.fileName); - } - } - /// Deletes remote-only assets, updates merged assets to be local-only - Future handleRemoteAssetRemoval(List idsToDelete) async { + Future handleRemoteAssetRemoval(List idsToDelete) { return _assetRepository.transaction(() async { await _assetRepository.deleteAllByRemoteId( idsToDelete, @@ -271,12 +249,6 @@ class SyncService { idsToDelete, state: AssetState.merged, ); - if (Platform.isAndroid && - _appSettingsService.getSetting( - AppSettingsEnum.manageLocalMediaAndroid, - )) { - await _moveToTrashMatchedAssets(idsToDelete); - } if (merged.isEmpty) return; for (final Asset asset in merged) { asset.remoteId = null; @@ -818,27 +790,10 @@ class SyncService { return (existing, toUpsert); } - Future _toggleTrashStatusForAssets(List assetsList) async { - for (var asset in assetsList) { - if (asset.isTrashed) { - _localFilesManager.moveToTrash(asset.fileName); - } else { - _localFilesManager.restoreFromTrash(asset.fileName); - } - } - } - /// Inserts or updates the assets in the database with their ExifInfo (if any) Future upsertAssetsWithExif(List assets) async { if (assets.isEmpty) return; - if (Platform.isAndroid && - _appSettingsService.getSetting( - AppSettingsEnum.manageLocalMediaAndroid, - )) { - _toggleTrashStatusForAssets(assets); - } - try { await _assetRepository.transaction(() async { await _assetRepository.updateAll(assets); diff --git a/mobile/lib/utils/local_files_manager.dart b/mobile/lib/utils/local_files_manager.dart deleted file mode 100644 index da9308c3cf..0000000000 --- a/mobile/lib/utils/local_files_manager.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/services.dart'; - -class LocalFilesManager { - static const MethodChannel _channel = MethodChannel('file_trash'); - - static Future moveToTrash(String fileName) async { - try { - final bool success = - await _channel.invokeMethod('moveToTrash', {'fileName': fileName}); - return success; - } on PlatformException catch (e) { - debugPrint('Error moving to trash: ${e.message}'); - return false; - } - } - - static Future restoreFromTrash(String fileName) async { - try { - final bool success = await _channel - .invokeMethod('restoreFromTrash', {'fileName': fileName}); - return success; - } on PlatformException catch (e) { - debugPrint('Error restoring file: ${e.message}'); - return false; - } - } - - static Future requestManageStoragePermission() async { - try { - final bool success = - await _channel.invokeMethod('requestManageStoragePermission'); - return success; - } on PlatformException catch (e) { - debugPrint('Error requesting permission: ${e.message}'); - return false; - } - } -} diff --git a/mobile/lib/widgets/settings/advanced_settings.dart b/mobile/lib/widgets/settings/advanced_settings.dart index 98c8728298..a2e0e5b95c 100644 --- a/mobile/lib/widgets/settings/advanced_settings.dart +++ b/mobile/lib/widgets/settings/advanced_settings.dart @@ -1,13 +1,11 @@ import 'dart:io'; -import 'package:device_info_plus/device_info_plus.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart' hide Store; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/domain/services/log.service.dart'; import 'package:immich_mobile/providers/user.provider.dart'; -import 'package:immich_mobile/repositories/local_files_manager.repository.dart'; import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/utils/hooks/app_settings_update_hook.dart'; import 'package:immich_mobile/utils/http_ssl_cert_override.dart'; @@ -27,8 +25,6 @@ class AdvancedSettings extends HookConsumerWidget { final advancedTroubleshooting = useAppSettingsState(AppSettingsEnum.advancedTroubleshooting); - final manageLocalMediaAndroid = - useAppSettingsState(AppSettingsEnum.manageLocalMediaAndroid); final levelId = useAppSettingsState(AppSettingsEnum.logLevel); final preferRemote = useAppSettingsState(AppSettingsEnum.preferRemoteImage); final allowSelfSignedSSLCert = @@ -44,16 +40,6 @@ class AdvancedSettings extends HookConsumerWidget { LogService.I.setlogLevel(Level.LEVELS[levelId.value].toLogLevel()), ); - Future checkAndroidVersion() async { - if (Platform.isAndroid) { - DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); - AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; - int sdkVersion = androidInfo.version.sdkInt; - return sdkVersion >= 30; - } - return false; - } - final advancedSettings = [ SettingsSwitchListTile( enabled: true, @@ -61,29 +47,6 @@ class AdvancedSettings extends HookConsumerWidget { title: "advanced_settings_troubleshooting_title".tr(), subtitle: "advanced_settings_troubleshooting_subtitle".tr(), ), - FutureBuilder( - future: checkAndroidVersion(), - builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data == true) { - return SettingsSwitchListTile( - enabled: true, - valueNotifier: manageLocalMediaAndroid, - title: "advanced_settings_sync_remote_deletions_title".tr(), - subtitle: "advanced_settings_sync_remote_deletions_subtitle".tr(), - onChanged: (value) async { - if (value) { - final result = await ref - .read(localFilesManagerRepositoryProvider) - .requestManageStoragePermission(); - manageLocalMediaAndroid.value = result; - } - }, - ); - } else { - return const SizedBox.shrink(); - } - }, - ), SettingsSliderListTile( text: "advanced_settings_log_level_title".tr(args: [logLevel]), valueNotifier: levelId, diff --git a/mobile/test/modules/shared/sync_service_test.dart b/mobile/test/modules/shared/sync_service_test.dart index 2029ade018..3879e64237 100644 --- a/mobile/test/modules/shared/sync_service_test.dart +++ b/mobile/test/modules/shared/sync_service_test.dart @@ -60,9 +60,6 @@ void main() { final MockAlbumMediaRepository albumMediaRepository = MockAlbumMediaRepository(); final MockAlbumApiRepository albumApiRepository = MockAlbumApiRepository(); - final MockAppSettingService appSettingService = MockAppSettingService(); - final MockLocalFilesManagerRepository localFilesManagerRepository = - MockLocalFilesManagerRepository(); final MockPartnerApiRepository partnerApiRepository = MockPartnerApiRepository(); final MockUserApiRepository userApiRepository = MockUserApiRepository(); @@ -109,8 +106,6 @@ void main() { userRepository, userService, eTagRepository, - appSettingService, - localFilesManagerRepository, partnerApiRepository, userApiRepository, ); diff --git a/mobile/test/repository.mocks.dart b/mobile/test/repository.mocks.dart index d2f0da4231..1c698297dc 100644 --- a/mobile/test/repository.mocks.dart +++ b/mobile/test/repository.mocks.dart @@ -10,7 +10,6 @@ import 'package:immich_mobile/interfaces/auth_api.interface.dart'; import 'package:immich_mobile/interfaces/backup_album.interface.dart'; import 'package:immich_mobile/interfaces/etag.interface.dart'; import 'package:immich_mobile/interfaces/file_media.interface.dart'; -import 'package:immich_mobile/interfaces/local_files_manager.interface.dart'; import 'package:immich_mobile/interfaces/partner.interface.dart'; import 'package:immich_mobile/interfaces/partner_api.interface.dart'; import 'package:mocktail/mocktail.dart'; @@ -42,9 +41,6 @@ class MockAuthApiRepository extends Mock implements IAuthApiRepository {} class MockAuthRepository extends Mock implements IAuthRepository {} -class MockPartnerRepository extends Mock implements IPartnerRepository {} - class MockPartnerApiRepository extends Mock implements IPartnerApiRepository {} -class MockLocalFilesManagerRepository extends Mock - implements ILocalFilesManager {} +class MockPartnerRepository extends Mock implements IPartnerRepository {} diff --git a/mobile/test/service.mocks.dart b/mobile/test/service.mocks.dart index 87a8c01cf0..d31a7e5d50 100644 --- a/mobile/test/service.mocks.dart +++ b/mobile/test/service.mocks.dart @@ -1,6 +1,5 @@ import 'package:immich_mobile/services/album.service.dart'; import 'package:immich_mobile/services/api.service.dart'; -import 'package:immich_mobile/services/app_settings.service.dart'; import 'package:immich_mobile/services/background.service.dart'; import 'package:immich_mobile/services/backup.service.dart'; import 'package:immich_mobile/services/entity.service.dart'; @@ -26,6 +25,4 @@ class MockNetworkService extends Mock implements NetworkService {} class MockSearchApi extends Mock implements SearchApi {} -class MockAppSettingService extends Mock implements AppSettingsService {} - class MockBackgroundService extends Mock implements BackgroundService {}