mirror of
https://github.com/immich-app/immich.git
synced 2026-07-23 05:44:48 +03:00
Compare commits
1 Commits
fix/auto-h
...
fix/24545-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bba46d5c62 |
@@ -198,19 +198,22 @@ class FlutterError (
|
||||
/** Generated class from Pigeon that represents data sent in messages. */
|
||||
data class BackgroundWorkerSettings (
|
||||
val requiresCharging: Boolean,
|
||||
val requiresUnmetered: Boolean,
|
||||
val minimumDelaySeconds: Long
|
||||
)
|
||||
{
|
||||
companion object {
|
||||
fun fromList(pigeonVar_list: List<Any?>): BackgroundWorkerSettings {
|
||||
val requiresCharging = pigeonVar_list[0] as Boolean
|
||||
val minimumDelaySeconds = pigeonVar_list[1] as Long
|
||||
return BackgroundWorkerSettings(requiresCharging, minimumDelaySeconds)
|
||||
val requiresUnmetered = pigeonVar_list[1] as Boolean
|
||||
val minimumDelaySeconds = pigeonVar_list[2] as Long
|
||||
return BackgroundWorkerSettings(requiresCharging, requiresUnmetered, minimumDelaySeconds)
|
||||
}
|
||||
}
|
||||
fun toList(): List<Any?> {
|
||||
return listOf(
|
||||
requiresCharging,
|
||||
requiresUnmetered,
|
||||
minimumDelaySeconds,
|
||||
)
|
||||
}
|
||||
@@ -222,12 +225,13 @@ data class BackgroundWorkerSettings (
|
||||
return true
|
||||
}
|
||||
val other = other as BackgroundWorkerSettings
|
||||
return BackgroundWorkerPigeonUtils.deepEquals(this.requiresCharging, other.requiresCharging) && BackgroundWorkerPigeonUtils.deepEquals(this.minimumDelaySeconds, other.minimumDelaySeconds)
|
||||
return BackgroundWorkerPigeonUtils.deepEquals(this.requiresCharging, other.requiresCharging) && BackgroundWorkerPigeonUtils.deepEquals(this.requiresUnmetered, other.requiresUnmetered) && BackgroundWorkerPigeonUtils.deepEquals(this.minimumDelaySeconds, other.minimumDelaySeconds)
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = javaClass.hashCode()
|
||||
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.requiresCharging)
|
||||
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.requiresUnmetered)
|
||||
result = 31 * result + BackgroundWorkerPigeonUtils.deepHash(this.minimumDelaySeconds)
|
||||
return result
|
||||
}
|
||||
@@ -256,7 +260,7 @@ private open class BackgroundWorkerPigeonCodec : StandardMessageCodec() {
|
||||
|
||||
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
|
||||
interface BackgroundWorkerFgHostApi {
|
||||
fun enable()
|
||||
fun enable(settings: BackgroundWorkerSettings)
|
||||
fun saveNotificationMessage(title: String, body: String)
|
||||
fun configure(settings: BackgroundWorkerSettings)
|
||||
fun disable()
|
||||
@@ -273,9 +277,11 @@ interface BackgroundWorkerFgHostApi {
|
||||
run {
|
||||
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable$separatedMessageChannelSuffix", codec)
|
||||
if (api != null) {
|
||||
channel.setMessageHandler { _, reply ->
|
||||
channel.setMessageHandler { message, reply ->
|
||||
val args = message as List<Any?>
|
||||
val settingsArg = args[0] as BackgroundWorkerSettings
|
||||
val wrapped: List<Any?> = try {
|
||||
api.enable()
|
||||
api.enable(settingsArg)
|
||||
listOf(null)
|
||||
} catch (exception: Throwable) {
|
||||
BackgroundWorkerPigeonUtils.wrapError(exception)
|
||||
|
||||
@@ -7,9 +7,15 @@ import androidx.work.BackoffPolicy
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import androidx.work.ExistingWorkPolicy
|
||||
import androidx.work.NetworkType
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.PeriodicWorkRequestBuilder
|
||||
import androidx.work.WorkInfo
|
||||
import androidx.work.WorkManager
|
||||
import com.google.common.util.concurrent.FutureCallback
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.MoreExecutors
|
||||
import io.flutter.embedding.engine.FlutterEngineCache
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -18,9 +24,8 @@ private const val TAG = "BackgroundWorkerApiImpl"
|
||||
class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
||||
private val ctx: Context = context.applicationContext
|
||||
|
||||
override fun enable() {
|
||||
enqueueMediaObserver(ctx)
|
||||
enqueuePeriodicWorker(ctx)
|
||||
override fun enable(settings: BackgroundWorkerSettings) {
|
||||
applySettings(settings)
|
||||
}
|
||||
|
||||
override fun saveNotificationMessage(title: String, body: String) {
|
||||
@@ -28,9 +33,14 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
||||
}
|
||||
|
||||
override fun configure(settings: BackgroundWorkerSettings) {
|
||||
applySettings(settings)
|
||||
}
|
||||
|
||||
private fun applySettings(settings: BackgroundWorkerSettings) {
|
||||
BackgroundWorkerPreferences(ctx).updateSettings(settings)
|
||||
enqueueMediaObserver(ctx)
|
||||
enqueuePeriodicWorker(ctx)
|
||||
refreshQueuedBackgroundWorker(ctx)
|
||||
}
|
||||
|
||||
override fun disable() {
|
||||
@@ -95,17 +105,42 @@ class BackgroundWorkerApiImpl(context: Context) : BackgroundWorkerFgHostApi {
|
||||
}
|
||||
|
||||
fun enqueueBackgroundWorker(ctx: Context) {
|
||||
val constraints = Constraints.Builder().setRequiresBatteryNotLow(true).build()
|
||||
val work = OneTimeWorkRequestBuilder<BackgroundWorker>()
|
||||
.setConstraints(constraints)
|
||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||
.build()
|
||||
val work = backgroundWorkerRequestBuilder(ctx).build()
|
||||
WorkManager.getInstance(ctx)
|
||||
.enqueueUniqueWork(BACKGROUND_WORKER_NAME, ExistingWorkPolicy.KEEP, work)
|
||||
|
||||
Log.i(TAG, "Enqueued background worker with name: $BACKGROUND_WORKER_NAME")
|
||||
}
|
||||
|
||||
private fun backgroundWorkerRequestBuilder(ctx: Context): OneTimeWorkRequest.Builder {
|
||||
val settings = BackgroundWorkerPreferences(ctx).getSettings()
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(if (settings.requiresUnmetered) NetworkType.UNMETERED else NetworkType.CONNECTED)
|
||||
.setRequiresBatteryNotLow(true)
|
||||
.build()
|
||||
return OneTimeWorkRequestBuilder<BackgroundWorker>()
|
||||
.setConstraints(constraints)
|
||||
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
|
||||
}
|
||||
|
||||
private fun refreshQueuedBackgroundWorker(ctx: Context) {
|
||||
val workManager = WorkManager.getInstance(ctx)
|
||||
Futures.addCallback(
|
||||
workManager.getWorkInfosForUniqueWork(BACKGROUND_WORKER_NAME),
|
||||
object : FutureCallback<List<WorkInfo>> {
|
||||
override fun onSuccess(infos: List<WorkInfo>?) {
|
||||
val info = infos?.firstOrNull { it.state == WorkInfo.State.ENQUEUED } ?: return
|
||||
workManager.updateWork(backgroundWorkerRequestBuilder(ctx).setId(info.id).build())
|
||||
}
|
||||
|
||||
override fun onFailure(t: Throwable) {
|
||||
Log.w(TAG, "Failed to update background worker", t)
|
||||
}
|
||||
},
|
||||
MoreExecutors.directExecutor(),
|
||||
)
|
||||
}
|
||||
|
||||
fun isBackgroundWorkerRunning(): Boolean {
|
||||
// Easier to check if the engine is cached as we always cache the engine when starting the worker
|
||||
// and remove it when the worker is finished
|
||||
|
||||
@@ -9,12 +9,14 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
|
||||
const val SHARED_PREF_NAME = "Immich::BackgroundWorker"
|
||||
private const val SHARED_PREF_MIN_DELAY_KEY = "BackgroundWorker::minDelaySeconds"
|
||||
private const val SHARED_PREF_REQUIRE_CHARGING_KEY = "BackgroundWorker::requireCharging"
|
||||
private const val SHARED_PREF_REQUIRE_UNMETERED_KEY = "BackgroundWorker::requireUnmetered"
|
||||
private const val SHARED_PREF_LOCK_KEY = "BackgroundWorker::isLocked"
|
||||
private const val SHARED_PREF_NOTIF_TITLE_KEY = "BackgroundWorker::notificationTitle"
|
||||
private const val SHARED_PREF_NOTIF_MSG_KEY = "BackgroundWorker::notificationMessage"
|
||||
|
||||
private const val DEFAULT_MIN_DELAY_SECONDS = 30L
|
||||
private const val DEFAULT_REQUIRE_CHARGING = false
|
||||
private const val DEFAULT_REQUIRE_UNMETERED = true
|
||||
private const val DEFAULT_NOTIF_TITLE = "Uploading media"
|
||||
private const val DEFAULT_NOTIF_MSG = "Checking for new assets…"
|
||||
}
|
||||
@@ -27,6 +29,7 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
|
||||
sp.edit {
|
||||
putLong(SHARED_PREF_MIN_DELAY_KEY, settings.minimumDelaySeconds)
|
||||
putBoolean(SHARED_PREF_REQUIRE_CHARGING_KEY, settings.requiresCharging)
|
||||
putBoolean(SHARED_PREF_REQUIRE_UNMETERED_KEY, settings.requiresUnmetered)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +42,10 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
|
||||
SHARED_PREF_REQUIRE_CHARGING_KEY,
|
||||
DEFAULT_REQUIRE_CHARGING
|
||||
),
|
||||
requiresUnmetered = sp.getBoolean(
|
||||
SHARED_PREF_REQUIRE_UNMETERED_KEY,
|
||||
DEFAULT_REQUIRE_UNMETERED
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -66,4 +73,3 @@ class BackgroundWorkerPreferences(private val ctx: Context) {
|
||||
return sp.getBoolean(SHARED_PREF_LOCK_KEY, true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,22 +163,26 @@ func deepHashBackgroundWorker(value: Any?, hasher: inout Hasher) {
|
||||
/// Generated class from Pigeon that represents data sent in messages.
|
||||
struct BackgroundWorkerSettings: Hashable {
|
||||
var requiresCharging: Bool
|
||||
var requiresUnmetered: Bool
|
||||
var minimumDelaySeconds: Int64
|
||||
|
||||
|
||||
// swift-format-ignore: AlwaysUseLowerCamelCase
|
||||
static func fromList(_ pigeonVar_list: [Any?]) -> BackgroundWorkerSettings? {
|
||||
let requiresCharging = pigeonVar_list[0] as! Bool
|
||||
let minimumDelaySeconds = pigeonVar_list[1] as! Int64
|
||||
let requiresUnmetered = pigeonVar_list[1] as! Bool
|
||||
let minimumDelaySeconds = pigeonVar_list[2] as! Int64
|
||||
|
||||
return BackgroundWorkerSettings(
|
||||
requiresCharging: requiresCharging,
|
||||
requiresUnmetered: requiresUnmetered,
|
||||
minimumDelaySeconds: minimumDelaySeconds
|
||||
)
|
||||
}
|
||||
func toList() -> [Any?] {
|
||||
return [
|
||||
requiresCharging,
|
||||
requiresUnmetered,
|
||||
minimumDelaySeconds,
|
||||
]
|
||||
}
|
||||
@@ -186,12 +190,13 @@ struct BackgroundWorkerSettings: Hashable {
|
||||
if Swift.type(of: lhs) != Swift.type(of: rhs) {
|
||||
return false
|
||||
}
|
||||
return deepEqualsBackgroundWorker(lhs.requiresCharging, rhs.requiresCharging) && deepEqualsBackgroundWorker(lhs.minimumDelaySeconds, rhs.minimumDelaySeconds)
|
||||
return deepEqualsBackgroundWorker(lhs.requiresCharging, rhs.requiresCharging) && deepEqualsBackgroundWorker(lhs.requiresUnmetered, rhs.requiresUnmetered) && deepEqualsBackgroundWorker(lhs.minimumDelaySeconds, rhs.minimumDelaySeconds)
|
||||
}
|
||||
|
||||
func hash(into hasher: inout Hasher) {
|
||||
hasher.combine("BackgroundWorkerSettings")
|
||||
deepHashBackgroundWorker(value: requiresCharging, hasher: &hasher)
|
||||
deepHashBackgroundWorker(value: requiresUnmetered, hasher: &hasher)
|
||||
deepHashBackgroundWorker(value: minimumDelaySeconds, hasher: &hasher)
|
||||
}
|
||||
}
|
||||
@@ -234,7 +239,7 @@ class BackgroundWorkerPigeonCodec: FlutterStandardMessageCodec, @unchecked Senda
|
||||
|
||||
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
|
||||
protocol BackgroundWorkerFgHostApi {
|
||||
func enable() throws
|
||||
func enable(settings: BackgroundWorkerSettings) throws
|
||||
func saveNotificationMessage(title: String, body: String) throws
|
||||
func configure(settings: BackgroundWorkerSettings) throws
|
||||
func disable() throws
|
||||
@@ -248,9 +253,11 @@ class BackgroundWorkerFgHostApiSetup {
|
||||
let channelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
|
||||
let enableChannel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable\(channelSuffix)", binaryMessenger: binaryMessenger, codec: codec)
|
||||
if let api = api {
|
||||
enableChannel.setMessageHandler { _, reply in
|
||||
enableChannel.setMessageHandler { message, reply in
|
||||
let args = message as! [Any?]
|
||||
let settingsArg = args[0] as! BackgroundWorkerSettings
|
||||
do {
|
||||
try api.enable()
|
||||
try api.enable(settings: settingsArg)
|
||||
reply(wrapResult(nil))
|
||||
} catch {
|
||||
reply(wrapError(error))
|
||||
|
||||
@@ -2,7 +2,7 @@ import BackgroundTasks
|
||||
|
||||
class BackgroundWorkerApiImpl: BackgroundWorkerFgHostApi {
|
||||
|
||||
func enable() throws {
|
||||
func enable(settings: BackgroundWorkerSettings) throws {
|
||||
BackgroundWorkerApiImpl.scheduleRefreshWorker()
|
||||
BackgroundWorkerApiImpl.scheduleProcessingWorker()
|
||||
print("BackgroundWorkerApiImpl:enable Background worker scheduled")
|
||||
|
||||
@@ -33,22 +33,25 @@ class BackgroundWorkerFgService {
|
||||
const BackgroundWorkerFgService(this._foregroundHostApi);
|
||||
|
||||
// TODO: Move this call to native side once old timeline is removed
|
||||
Future<void> enable() => _foregroundHostApi.enable();
|
||||
Future<void> enable() => _foregroundHostApi.enable(_currentSettings());
|
||||
|
||||
Future<void> saveNotificationMessage(String title, String body) =>
|
||||
_foregroundHostApi.saveNotificationMessage(title, body);
|
||||
|
||||
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) {
|
||||
final backup = SettingsRepository.instance.appConfig.backup;
|
||||
return _foregroundHostApi.configure(
|
||||
BackgroundWorkerSettings(
|
||||
minimumDelaySeconds: minimumDelaySeconds ?? backup.triggerDelay,
|
||||
requiresCharging: requireCharging ?? backup.requireCharging,
|
||||
),
|
||||
);
|
||||
}
|
||||
Future<void> configure({int? minimumDelaySeconds, bool? requireCharging}) => _foregroundHostApi.configure(
|
||||
_currentSettings(minimumDelaySeconds: minimumDelaySeconds, requireCharging: requireCharging),
|
||||
);
|
||||
|
||||
Future<void> disable() => _foregroundHostApi.disable();
|
||||
|
||||
BackgroundWorkerSettings _currentSettings({int? minimumDelaySeconds, bool? requireCharging}) {
|
||||
final backup = SettingsRepository.instance.appConfig.backup;
|
||||
return BackgroundWorkerSettings(
|
||||
minimumDelaySeconds: minimumDelaySeconds ?? backup.triggerDelay,
|
||||
requiresCharging: requireCharging ?? backup.requireCharging,
|
||||
requiresUnmetered: !(backup.useCellularForPhotos || backup.useCellularForVideos),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
|
||||
21
mobile/lib/platform/background_worker_api.g.dart
generated
21
mobile/lib/platform/background_worker_api.g.dart
generated
@@ -97,14 +97,20 @@ int _deepHash(Object? value) {
|
||||
}
|
||||
|
||||
class BackgroundWorkerSettings {
|
||||
BackgroundWorkerSettings({required this.requiresCharging, required this.minimumDelaySeconds});
|
||||
BackgroundWorkerSettings({
|
||||
required this.requiresCharging,
|
||||
required this.requiresUnmetered,
|
||||
required this.minimumDelaySeconds,
|
||||
});
|
||||
|
||||
bool requiresCharging;
|
||||
|
||||
bool requiresUnmetered;
|
||||
|
||||
int minimumDelaySeconds;
|
||||
|
||||
List<Object?> _toList() {
|
||||
return <Object?>[requiresCharging, minimumDelaySeconds];
|
||||
return <Object?>[requiresCharging, requiresUnmetered, minimumDelaySeconds];
|
||||
}
|
||||
|
||||
Object encode() {
|
||||
@@ -113,7 +119,11 @@ class BackgroundWorkerSettings {
|
||||
|
||||
static BackgroundWorkerSettings decode(Object result) {
|
||||
result as List<Object?>;
|
||||
return BackgroundWorkerSettings(requiresCharging: result[0]! as bool, minimumDelaySeconds: result[1]! as int);
|
||||
return BackgroundWorkerSettings(
|
||||
requiresCharging: result[0]! as bool,
|
||||
requiresUnmetered: result[1]! as bool,
|
||||
minimumDelaySeconds: result[2]! as int,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -126,6 +136,7 @@ class BackgroundWorkerSettings {
|
||||
return true;
|
||||
}
|
||||
return _deepEquals(requiresCharging, other.requiresCharging) &&
|
||||
_deepEquals(requiresUnmetered, other.requiresUnmetered) &&
|
||||
_deepEquals(minimumDelaySeconds, other.minimumDelaySeconds);
|
||||
}
|
||||
|
||||
@@ -173,7 +184,7 @@ class BackgroundWorkerFgHostApi {
|
||||
|
||||
final String pigeonVar_messageChannelSuffix;
|
||||
|
||||
Future<void> enable() async {
|
||||
Future<void> enable(BackgroundWorkerSettings settings) async {
|
||||
final pigeonVar_channelName =
|
||||
'dev.flutter.pigeon.immich_mobile.BackgroundWorkerFgHostApi.enable$pigeonVar_messageChannelSuffix';
|
||||
final pigeonVar_channel = BasicMessageChannel<Object?>(
|
||||
@@ -181,7 +192,7 @@ class BackgroundWorkerFgHostApi {
|
||||
pigeonChannelCodec,
|
||||
binaryMessenger: pigeonVar_binaryMessenger,
|
||||
);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
|
||||
final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(<Object?>[settings]);
|
||||
final pigeonVar_replyList = await pigeonVar_sendFuture as List<Object?>?;
|
||||
|
||||
_extractReplyValueOrThrow(pigeonVar_replyList, pigeonVar_channelName, isNullValid: true);
|
||||
|
||||
@@ -192,30 +192,34 @@ class _BackupSwitchTile extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _UseCellularForVideosButton extends StatelessWidget {
|
||||
class _UseCellularForVideosButton extends ConsumerWidget {
|
||||
const _UseCellularForVideosButton();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fgService = ref.read(backgroundWorkerFgServiceProvider);
|
||||
return _BackupSwitchTile(
|
||||
metadataKey: SettingsKey.backupUseCellularForVideos,
|
||||
selector: (c) => c.backup.useCellularForVideos,
|
||||
titleKey: "videos",
|
||||
subtitleKey: "network_requirement_videos_upload",
|
||||
onChanged: (_) => fgService.configure(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _UseCellularForPhotosButton extends StatelessWidget {
|
||||
class _UseCellularForPhotosButton extends ConsumerWidget {
|
||||
const _UseCellularForPhotosButton();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final fgService = ref.read(backgroundWorkerFgServiceProvider);
|
||||
return _BackupSwitchTile(
|
||||
metadataKey: SettingsKey.backupUseCellularForPhotos,
|
||||
selector: (c) => c.backup.useCellularForPhotos,
|
||||
titleKey: "photos",
|
||||
subtitleKey: "network_requirement_photos_upload",
|
||||
onChanged: (_) => fgService.configure(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,19 @@ import 'package:pigeon/pigeon.dart';
|
||||
)
|
||||
class BackgroundWorkerSettings {
|
||||
final bool requiresCharging;
|
||||
final bool requiresUnmetered;
|
||||
final int minimumDelaySeconds;
|
||||
|
||||
const BackgroundWorkerSettings({required this.requiresCharging, required this.minimumDelaySeconds});
|
||||
const BackgroundWorkerSettings({
|
||||
required this.requiresCharging,
|
||||
required this.requiresUnmetered,
|
||||
required this.minimumDelaySeconds,
|
||||
});
|
||||
}
|
||||
|
||||
@HostApi()
|
||||
abstract class BackgroundWorkerFgHostApi {
|
||||
void enable();
|
||||
void enable(BackgroundWorkerSettings settings);
|
||||
|
||||
void saveNotificationMessage(String title, String body);
|
||||
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/services/background_worker.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/platform/background_worker_api.g.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../repository_context.dart';
|
||||
|
||||
class _MockBackgroundWorkerFgHostApi extends Mock implements BackgroundWorkerFgHostApi {}
|
||||
|
||||
void main() {
|
||||
late MediumRepositoryContext ctx;
|
||||
late _MockBackgroundWorkerFgHostApi hostApi;
|
||||
late BackgroundWorkerFgService sut;
|
||||
|
||||
setUpAll(() async {
|
||||
ctx = MediumRepositoryContext();
|
||||
await SettingsRepository.ensureInitialized(ctx.db);
|
||||
registerFallbackValue(
|
||||
BackgroundWorkerSettings(requiresCharging: false, requiresUnmetered: true, minimumDelaySeconds: 30),
|
||||
);
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await ctx.dispose();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
hostApi = _MockBackgroundWorkerFgHostApi();
|
||||
when(() => hostApi.enable(any())).thenAnswer((_) async {});
|
||||
when(() => hostApi.configure(any())).thenAnswer((_) async {});
|
||||
sut = BackgroundWorkerFgService(hostApi);
|
||||
});
|
||||
|
||||
group('BackgroundWorkerFgService network constraint', () {
|
||||
Future<bool> configuredRequiresUnmetered({required bool photos, required bool videos}) async {
|
||||
await SettingsRepository.instance.write(.backupUseCellularForPhotos, photos);
|
||||
await SettingsRepository.instance.write(.backupUseCellularForVideos, videos);
|
||||
await sut.configure();
|
||||
final settings = verify(() => hostApi.configure(captureAny())).captured.single as BackgroundWorkerSettings;
|
||||
return settings.requiresUnmetered;
|
||||
}
|
||||
|
||||
test('requires unmetered by default', () async {
|
||||
expect(await configuredRequiresUnmetered(photos: false, videos: false), isTrue);
|
||||
});
|
||||
|
||||
test('does not require unmetered when photos may use cellular', () async {
|
||||
expect(await configuredRequiresUnmetered(photos: true, videos: false), isFalse);
|
||||
});
|
||||
|
||||
test('does not require unmetered when videos may use cellular', () async {
|
||||
expect(await configuredRequiresUnmetered(photos: false, videos: true), isFalse);
|
||||
});
|
||||
|
||||
test('does not require unmetered when both photos and videos may use cellular', () async {
|
||||
expect(await configuredRequiresUnmetered(photos: true, videos: true), isFalse);
|
||||
});
|
||||
|
||||
test('enable carries the same constraint at startup', () async {
|
||||
await SettingsRepository.instance.write(.backupUseCellularForPhotos, true);
|
||||
await SettingsRepository.instance.write(.backupUseCellularForVideos, true);
|
||||
await sut.enable();
|
||||
final settings = verify(() => hostApi.enable(captureAny())).captured.single as BackgroundWorkerSettings;
|
||||
expect(settings.requiresUnmetered, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user