nc-photos/app/lib/use_case/startup_sync.dart

122 lines
3.7 KiB
Dart

import 'dart:async';
import 'package:event_bus/event_bus.dart';
import 'package:flutter_isolate/flutter_isolate.dart';
import 'package:kiwi/kiwi.dart';
import 'package:logging/logging.dart';
import 'package:nc_photos/account.dart';
import 'package:nc_photos/app_init.dart' as app_init;
import 'package:nc_photos/di_container.dart';
import 'package:nc_photos/event/event.dart';
import 'package:nc_photos/platform/k.dart' as platform_k;
import 'package:nc_photos/use_case/sync_favorite.dart';
import 'package:nc_photos/use_case/sync_person.dart';
import 'package:nc_photos/use_case/sync_tag.dart';
import 'package:np_codegen/np_codegen.dart';
import 'package:np_common/type.dart';
part 'startup_sync.g.dart';
/// Sync various properties with server during startup
@npLog
class StartupSync {
StartupSync(this._c)
: assert(require(_c)),
assert(SyncFavorite.require(_c)),
assert(SyncTag.require(_c));
static bool require(DiContainer c) => true;
/// Sync in a background isolate
static Future<SyncResult> runInIsolate(Account account) async {
if (platform_k.isWeb) {
// not supported on web
final c = KiwiContainer().resolve<DiContainer>();
return await StartupSync(c)(account);
} else {
// we can't use regular isolate here because self-signed cert support
// requires native plugins
final resultJson =
await flutterCompute(_isolateMain, _IsolateMessage(account).toJson());
final result = SyncResult.fromJson(resultJson);
// events fired in background isolate won't be noticed by the main isolate,
// so we fire them again here
_broadcastResult(account, result);
return result;
}
}
Future<SyncResult> call(Account account) async {
_log.info("[_run] Begin sync");
final stopwatch = Stopwatch()..start();
late final int syncFavoriteCount;
try {
syncFavoriteCount = await SyncFavorite(_c)(account);
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncFavorite", e, stackTrace);
syncFavoriteCount = -1;
}
try {
await SyncTag(_c)(account);
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncTag", e, stackTrace);
}
try {
await SyncPerson(_c)(account);
} catch (e, stackTrace) {
_log.shout("[_run] Failed while SyncPerson", e, stackTrace);
}
_log.info("[_run] Elapsed time: ${stopwatch.elapsedMilliseconds}ms");
return SyncResult(syncFavoriteCount);
}
static void _broadcastResult(Account account, SyncResult result) {
final eventBus = KiwiContainer().resolve<EventBus>();
if (result.syncFavoriteCount > 0) {
eventBus.fire(FavoriteResyncedEvent(account));
}
}
final DiContainer _c;
}
class SyncResult {
const SyncResult(this.syncFavoriteCount);
factory SyncResult.fromJson(JsonObj json) => SyncResult(
json["syncFavoriteCount"],
);
JsonObj toJson() => {
"syncFavoriteCount": syncFavoriteCount,
};
final int syncFavoriteCount;
}
class _IsolateMessage {
const _IsolateMessage(this.account);
factory _IsolateMessage.fromJson(JsonObj json) => _IsolateMessage(
Account.fromJson(
json["account"].cast<String, dynamic>(),
upgraderV1: const AccountUpgraderV1(),
)!,
);
JsonObj toJson() => {
"account": account.toJson(),
};
final Account account;
}
@pragma("vm:entry-point")
Future<JsonObj> _isolateMain(JsonObj messageJson) async {
final message = _IsolateMessage.fromJson(messageJson);
await app_init.init(app_init.InitIsolateType.flutterIsolate);
final c = KiwiContainer().resolve<DiContainer>();
final result = await StartupSync(c)(message.account);
return result.toJson();
}