add full sync
This commit is contained in:
@@ -1,19 +1,15 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/models/asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/asset.model.dart';
|
||||
|
||||
class Asset extends Table {
|
||||
const Asset();
|
||||
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
|
||||
TextColumn get name => text()();
|
||||
TextColumn get checksum => text().unique()();
|
||||
IntColumn get height => integer()();
|
||||
IntColumn get width => integer()();
|
||||
IntColumn get height => integer().nullable()();
|
||||
IntColumn get width => integer().nullable()();
|
||||
IntColumn get type => intEnum<AssetType>()();
|
||||
DateTimeColumn get createdTime => dateTime()();
|
||||
DateTimeColumn get modifiedTime =>
|
||||
dateTime().withDefault(currentDateAndTime)();
|
||||
IntColumn get duration => integer().withDefault(const Constant(0))();
|
||||
BoolColumn get isLivePhoto => boolean().withDefault(const Constant(false))();
|
||||
}
|
||||
|
||||
@@ -4,5 +4,8 @@ import 'package:immich_mobile/domain/entities/asset.entity.dart';
|
||||
class LocalAsset extends Asset {
|
||||
const LocalAsset();
|
||||
|
||||
TextColumn get localId => text().unique()();
|
||||
TextColumn get localId => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {localId};
|
||||
}
|
||||
|
||||
@@ -4,5 +4,9 @@ import 'package:immich_mobile/domain/entities/asset.entity.dart';
|
||||
class RemoteAsset extends Asset {
|
||||
const RemoteAsset();
|
||||
|
||||
TextColumn get remoteId => text().unique()();
|
||||
TextColumn get remoteId => text()();
|
||||
TextColumn get livePhotoVideoId => text().nullable()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {remoteId};
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
abstract class IDatabaseRepository<T> {
|
||||
/// Current version of the DB to aid with migration
|
||||
int get schemaVersion;
|
||||
|
||||
/// Initializes the DB and returns the corresponding object
|
||||
T init();
|
||||
|
||||
/// Check and migrate the DB to the latest schema
|
||||
void migrateDB();
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import 'package:immich_mobile/domain/models/log.model.dart';
|
||||
|
||||
abstract class ILogRepository {
|
||||
/// Fetches all logs
|
||||
FutureOr<List<LogMessage>> fetchLogs();
|
||||
FutureOr<List<LogMessage>> fetchAll();
|
||||
|
||||
/// Inserts a new log into the DB
|
||||
FutureOr<bool> add(LogMessage log);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import 'package:immich_mobile/domain/models/asset/remote_asset.model.dart';
|
||||
|
||||
abstract class IRemoteAssetRepository {
|
||||
/// Batch insert asset
|
||||
Future<bool> addAll(Iterable<RemoteAsset> assets);
|
||||
}
|
||||
@@ -4,8 +4,8 @@ import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
|
||||
abstract class IUserRepository {
|
||||
/// Fetches user
|
||||
FutureOr<User?> getUser(String userId);
|
||||
FutureOr<User?> fetch(String userId);
|
||||
|
||||
/// Insert user
|
||||
FutureOr<bool> insertUser(User user);
|
||||
FutureOr<bool> add(User user);
|
||||
}
|
||||
|
||||
+10
-24
@@ -7,32 +7,27 @@ enum AssetType {
|
||||
}
|
||||
|
||||
class Asset {
|
||||
final int id;
|
||||
final String name;
|
||||
final String checksum;
|
||||
final int height;
|
||||
final int width;
|
||||
final int? height;
|
||||
final int? width;
|
||||
final AssetType type;
|
||||
final DateTime createdTime;
|
||||
final DateTime modifiedTime;
|
||||
final int duration;
|
||||
final bool isLivePhoto;
|
||||
|
||||
const Asset({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.checksum,
|
||||
required this.height,
|
||||
required this.width,
|
||||
this.height,
|
||||
this.width,
|
||||
required this.type,
|
||||
required this.createdTime,
|
||||
required this.modifiedTime,
|
||||
required this.duration,
|
||||
required this.isLivePhoto,
|
||||
});
|
||||
|
||||
Asset copyWith({
|
||||
int? id,
|
||||
String? name,
|
||||
String? checksum,
|
||||
int? height,
|
||||
@@ -41,10 +36,8 @@ class Asset {
|
||||
DateTime? createdTime,
|
||||
DateTime? modifiedTime,
|
||||
int? duration,
|
||||
bool? isLivePhoto,
|
||||
}) {
|
||||
return Asset(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
checksum: checksum ?? this.checksum,
|
||||
height: height ?? this.height,
|
||||
@@ -53,52 +46,45 @@ class Asset {
|
||||
createdTime: createdTime ?? this.createdTime,
|
||||
modifiedTime: modifiedTime ?? this.modifiedTime,
|
||||
duration: duration ?? this.duration,
|
||||
isLivePhoto: isLivePhoto ?? this.isLivePhoto,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => """
|
||||
{
|
||||
"id": $id,
|
||||
"name": "$name",
|
||||
"checksum": "$checksum",
|
||||
"height": $height,
|
||||
"width": $width,
|
||||
"height": ${height ?? "-"},
|
||||
"width": ${width ?? "-"},
|
||||
"type": "$type",
|
||||
"createdTime": "$createdTime",
|
||||
"modifiedTime": "$modifiedTime",
|
||||
"duration": "$duration",
|
||||
"isLivePhoto": "$isLivePhoto",
|
||||
}""";
|
||||
|
||||
@override
|
||||
bool operator ==(covariant Asset other) {
|
||||
if (identical(this, other)) return true;
|
||||
|
||||
return other.id == id &&
|
||||
other.name == name &&
|
||||
return other.name == name &&
|
||||
other.checksum == checksum &&
|
||||
other.height == height &&
|
||||
other.width == width &&
|
||||
other.type == type &&
|
||||
other.createdTime == createdTime &&
|
||||
other.modifiedTime == modifiedTime &&
|
||||
other.duration == duration &&
|
||||
other.isLivePhoto == isLivePhoto;
|
||||
other.duration == duration;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return id.hashCode ^
|
||||
name.hashCode ^
|
||||
return name.hashCode ^
|
||||
checksum.hashCode ^
|
||||
height.hashCode ^
|
||||
width.hashCode ^
|
||||
type.hashCode ^
|
||||
createdTime.hashCode ^
|
||||
modifiedTime.hashCode ^
|
||||
duration.hashCode ^
|
||||
isLivePhoto.hashCode;
|
||||
duration.hashCode;
|
||||
}
|
||||
}
|
||||
+3
-11
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/domain/models/asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/asset.model.dart';
|
||||
|
||||
@immutable
|
||||
class LocalAsset extends Asset {
|
||||
@@ -7,7 +7,6 @@ class LocalAsset extends Asset {
|
||||
|
||||
const LocalAsset({
|
||||
required this.localId,
|
||||
required super.id,
|
||||
required super.name,
|
||||
required super.checksum,
|
||||
required super.height,
|
||||
@@ -16,23 +15,20 @@ class LocalAsset extends Asset {
|
||||
required super.createdTime,
|
||||
required super.modifiedTime,
|
||||
required super.duration,
|
||||
required super.isLivePhoto,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() => """
|
||||
{
|
||||
"id": $id,
|
||||
"localId": "$localId",
|
||||
"name": "$name",
|
||||
"checksum": "$checksum",
|
||||
"height": $height,
|
||||
"width": $width,
|
||||
"height": ${height ?? "-"},
|
||||
"width": ${width ?? "-"},
|
||||
"type": "$type",
|
||||
"createdTime": "$createdTime",
|
||||
"modifiedTime": "$modifiedTime",
|
||||
"duration": "$duration",
|
||||
"isLivePhoto": "$isLivePhoto",
|
||||
}""";
|
||||
|
||||
@override
|
||||
@@ -47,7 +43,6 @@ class LocalAsset extends Asset {
|
||||
|
||||
@override
|
||||
LocalAsset copyWith({
|
||||
int? id,
|
||||
String? localId,
|
||||
String? name,
|
||||
String? checksum,
|
||||
@@ -57,10 +52,8 @@ class LocalAsset extends Asset {
|
||||
DateTime? createdTime,
|
||||
DateTime? modifiedTime,
|
||||
int? duration,
|
||||
bool? isLivePhoto,
|
||||
}) {
|
||||
return LocalAsset(
|
||||
id: id ?? this.id,
|
||||
localId: localId ?? this.localId,
|
||||
name: name ?? this.name,
|
||||
checksum: checksum ?? this.checksum,
|
||||
@@ -70,7 +63,6 @@ class LocalAsset extends Asset {
|
||||
createdTime: createdTime ?? this.createdTime,
|
||||
modifiedTime: modifiedTime ?? this.modifiedTime,
|
||||
duration: duration ?? this.duration,
|
||||
isLivePhoto: isLivePhoto ?? this.isLivePhoto,
|
||||
);
|
||||
}
|
||||
}
|
||||
+30
-11
@@ -1,13 +1,15 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/domain/models/asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/asset.model.dart';
|
||||
import 'package:immich_mobile/utils/extensions/string.extension.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
@immutable
|
||||
class RemoteAsset extends Asset {
|
||||
final String remoteId;
|
||||
final String? livePhotoVideoId;
|
||||
|
||||
const RemoteAsset({
|
||||
required this.remoteId,
|
||||
required super.id,
|
||||
required super.name,
|
||||
required super.checksum,
|
||||
required super.height,
|
||||
@@ -16,23 +18,22 @@ class RemoteAsset extends Asset {
|
||||
required super.createdTime,
|
||||
required super.modifiedTime,
|
||||
required super.duration,
|
||||
required super.isLivePhoto,
|
||||
this.livePhotoVideoId,
|
||||
});
|
||||
|
||||
@override
|
||||
String toString() => """
|
||||
{
|
||||
"id": $id,
|
||||
"remoteId": "$remoteId",
|
||||
"name": "$name",
|
||||
"checksum": "$checksum",
|
||||
"height": $height,
|
||||
"width": $width,
|
||||
"height": ${height ?? "-"},
|
||||
"width": ${width ?? "-"},
|
||||
"type": "$type",
|
||||
"createdTime": "$createdTime",
|
||||
"modifiedTime": "$modifiedTime",
|
||||
"duration": "$duration",
|
||||
"isLivePhoto": "$isLivePhoto",
|
||||
"livePhotoVideoId": "${livePhotoVideoId ?? "-"}",
|
||||
}""";
|
||||
|
||||
@override
|
||||
@@ -47,7 +48,6 @@ class RemoteAsset extends Asset {
|
||||
|
||||
@override
|
||||
RemoteAsset copyWith({
|
||||
int? id,
|
||||
String? remoteId,
|
||||
String? name,
|
||||
String? checksum,
|
||||
@@ -57,10 +57,9 @@ class RemoteAsset extends Asset {
|
||||
DateTime? createdTime,
|
||||
DateTime? modifiedTime,
|
||||
int? duration,
|
||||
bool? isLivePhoto,
|
||||
String? livePhotoVideoId,
|
||||
}) {
|
||||
return RemoteAsset(
|
||||
id: id ?? this.id,
|
||||
remoteId: remoteId ?? this.remoteId,
|
||||
name: name ?? this.name,
|
||||
checksum: checksum ?? this.checksum,
|
||||
@@ -70,7 +69,27 @@ class RemoteAsset extends Asset {
|
||||
createdTime: createdTime ?? this.createdTime,
|
||||
modifiedTime: modifiedTime ?? this.modifiedTime,
|
||||
duration: duration ?? this.duration,
|
||||
isLivePhoto: isLivePhoto ?? this.isLivePhoto,
|
||||
livePhotoVideoId: livePhotoVideoId ?? this.livePhotoVideoId,
|
||||
);
|
||||
}
|
||||
|
||||
factory RemoteAsset.fromDto(AssetResponseDto dto) => RemoteAsset(
|
||||
remoteId: dto.id,
|
||||
createdTime: dto.fileCreatedAt,
|
||||
duration: dto.duration.tryParseInt() ?? 0,
|
||||
height: dto.exifInfo?.exifImageHeight?.toInt(),
|
||||
width: dto.exifInfo?.exifImageWidth?.toInt(),
|
||||
checksum: dto.checksum,
|
||||
name: dto.originalFileName,
|
||||
livePhotoVideoId: dto.livePhotoVideoId,
|
||||
modifiedTime: dto.fileModifiedAt,
|
||||
type: _toAssetType(dto.type),
|
||||
);
|
||||
}
|
||||
|
||||
AssetType _toAssetType(AssetTypeEnum type) => switch (type) {
|
||||
AssetTypeEnum.AUDIO => AssetType.audio,
|
||||
AssetTypeEnum.IMAGE => AssetType.image,
|
||||
AssetTypeEnum.VIDEO => AssetType.video,
|
||||
_ => AssetType.other,
|
||||
};
|
||||
@@ -1,9 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:drift_dev/api/migrations.dart';
|
||||
import 'package:drift_flutter/drift_flutter.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:immich_mobile/domain/entities/album.entity.dart';
|
||||
import 'package:immich_mobile/domain/entities/local_asset.entity.dart';
|
||||
@@ -11,54 +9,17 @@ import 'package:immich_mobile/domain/entities/log.entity.dart';
|
||||
import 'package:immich_mobile/domain/entities/remote_asset.entity.dart';
|
||||
import 'package:immich_mobile/domain/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/domain/entities/user.entity.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/database.interface.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sqlite3/sqlite3.dart';
|
||||
import 'package:sqlite3_flutter_libs/sqlite3_flutter_libs.dart';
|
||||
|
||||
import 'database.repository.drift.dart';
|
||||
|
||||
@DriftDatabase(tables: [Logs, Store, LocalAlbum, LocalAsset, User, RemoteAsset])
|
||||
class DriftDatabaseRepository extends $DriftDatabaseRepository
|
||||
implements IDatabaseRepository<GeneratedDatabase> {
|
||||
DriftDatabaseRepository() : super(_openConnection());
|
||||
|
||||
static LazyDatabase _openConnection() {
|
||||
return LazyDatabase(() async {
|
||||
final dbFolder = await getApplicationDocumentsDirectory();
|
||||
final file = File(p.join(dbFolder.path, 'db.sqlite'));
|
||||
|
||||
// Work around limitations on old Android versions
|
||||
// https://github.com/simolus3/sqlite3.dart/tree/main/sqlite3_flutter_libs#problems-on-android-6
|
||||
if (Platform.isAndroid) {
|
||||
await applyWorkaroundToOpenSqlite3OnOldAndroidVersions();
|
||||
}
|
||||
|
||||
// Make sqlite3 pick a more suitable location for temporary files - the
|
||||
// one from the system may be inaccessible due to sandboxing.
|
||||
// https://github.com/simolus3/moor/issues/876#issuecomment-710013503
|
||||
final cachebase = (await getTemporaryDirectory()).path;
|
||||
// We can't access /tmp on Android, which sqlite3 would try by default.
|
||||
// Explicitly tell it about the correct temporary directory.
|
||||
sqlite3.tempDirectory = cachebase;
|
||||
|
||||
return NativeDatabase.createInBackground(file);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
GeneratedDatabase init() => this;
|
||||
class DriftDatabaseRepository extends $DriftDatabaseRepository {
|
||||
DriftDatabaseRepository([QueryExecutor? executor])
|
||||
: super(executor ?? driftDatabase(name: 'db'));
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
||||
@override
|
||||
// ignore: no-empty-block
|
||||
void migrateDB() {
|
||||
// Migrations are handled automatically using the migrator field
|
||||
}
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
onCreate: (m) => m.createAll(),
|
||||
|
||||
@@ -13,8 +13,8 @@ class LogDriftRepository implements ILogRepository {
|
||||
const LogDriftRepository(this.db);
|
||||
|
||||
@override
|
||||
Future<List<LogMessage>> fetchLogs() async {
|
||||
return await db.managers.logs.map((l) => l.toModel()).get();
|
||||
Future<List<LogMessage>> fetchAll() async {
|
||||
return await db.managers.logs.map(_toModel).get();
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -82,15 +82,13 @@ class LogDriftRepository implements ILogRepository {
|
||||
}
|
||||
}
|
||||
|
||||
extension _LogToLogMessage on Log {
|
||||
LogMessage toModel() {
|
||||
return LogMessage(
|
||||
content: content,
|
||||
createdAt: createdAt,
|
||||
level: level,
|
||||
error: error,
|
||||
logger: logger,
|
||||
stack: stack,
|
||||
);
|
||||
}
|
||||
LogMessage _toModel(Log log) {
|
||||
return LogMessage(
|
||||
content: log.content,
|
||||
createdAt: log.createdAt,
|
||||
level: log.level,
|
||||
error: log.error,
|
||||
logger: log.logger,
|
||||
stack: log.stack,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/entities/remote_asset.entity.drift.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/remote_asset.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/remote_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/repositories/database.repository.dart';
|
||||
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
|
||||
|
||||
class RemoteAssetDriftRepository
|
||||
with LogContext
|
||||
implements IRemoteAssetRepository {
|
||||
final DriftDatabaseRepository _db;
|
||||
|
||||
const RemoteAssetDriftRepository(this._db);
|
||||
|
||||
@override
|
||||
Future<bool> addAll(Iterable<RemoteAsset> assets) async {
|
||||
try {
|
||||
await _db.batch((batch) => batch.insertAllOnConflictUpdate(
|
||||
_db.remoteAsset,
|
||||
assets.map(_toEntity),
|
||||
));
|
||||
|
||||
return true;
|
||||
} catch (e, s) {
|
||||
log.severe("Cannot insert remote assets into table", e, s);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoteAssetCompanion _toEntity(RemoteAsset asset) {
|
||||
return RemoteAssetCompanion.insert(
|
||||
name: asset.name,
|
||||
checksum: asset.checksum,
|
||||
height: Value(asset.height),
|
||||
width: Value(asset.width),
|
||||
type: asset.type,
|
||||
createdTime: asset.createdTime,
|
||||
remoteId: asset.remoteId,
|
||||
duration: Value(asset.duration),
|
||||
modifiedTime: Value(asset.modifiedTime),
|
||||
livePhotoVideoId: Value(asset.livePhotoVideoId),
|
||||
);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class StoreDriftRepository with LogContext implements IStoreRepository {
|
||||
@override
|
||||
FutureOr<void> clearStore() async {
|
||||
await db.managers.store.delete();
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
FutureOr<T?> _getValueFromStoreData<T, U>(
|
||||
|
||||
@@ -13,15 +13,15 @@ class UserDriftRepository with LogContext implements IUserRepository {
|
||||
const UserDriftRepository(this.db);
|
||||
|
||||
@override
|
||||
FutureOr<User?> getUser(String userId) async {
|
||||
FutureOr<User?> fetch(String userId) async {
|
||||
return await db.managers.user
|
||||
.filter((f) => f.id.equals(userId))
|
||||
.map((u) => u.toModel())
|
||||
.map(_toModel)
|
||||
.getSingleOrNull();
|
||||
}
|
||||
|
||||
@override
|
||||
FutureOr<bool> insertUser(User user) async {
|
||||
FutureOr<bool> add(User user) async {
|
||||
try {
|
||||
await db.into(db.user).insertOnConflictUpdate(
|
||||
UserCompanion.insert(
|
||||
@@ -46,20 +46,18 @@ class UserDriftRepository with LogContext implements IUserRepository {
|
||||
}
|
||||
}
|
||||
|
||||
extension _UserDataToUser on UserData {
|
||||
User toModel() {
|
||||
return User(
|
||||
id: id,
|
||||
email: email,
|
||||
avatarColor: avatarColor,
|
||||
inTimeline: inTimeline,
|
||||
isAdmin: isAdmin,
|
||||
memoryEnabled: memoryEnabled,
|
||||
name: name,
|
||||
profileImagePath: profileImagePath,
|
||||
quotaSizeInBytes: quotaSizeInBytes,
|
||||
quotaUsageInBytes: quotaUsageInBytes,
|
||||
updatedAt: updatedAt,
|
||||
);
|
||||
}
|
||||
User _toModel(UserData user) {
|
||||
return User(
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
avatarColor: user.avatarColor,
|
||||
inTimeline: user.inTimeline,
|
||||
isAdmin: user.isAdmin,
|
||||
memoryEnabled: user.memoryEnabled,
|
||||
name: user.name,
|
||||
profileImagePath: user.profileImagePath,
|
||||
quotaSizeInBytes: user.quotaSizeInBytes,
|
||||
quotaUsageInBytes: user.quotaUsageInBytes,
|
||||
updatedAt: user.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import 'package:immich_mobile/domain/models/server-info/server_config.model.dart';
|
||||
import 'package:immich_mobile/domain/models/server-info/server_features.model.dart';
|
||||
import 'package:immich_mobile/utils/immich_api_client.dart';
|
||||
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class ServerInfoService with LogContext {
|
||||
final ImmichApiClient _api;
|
||||
final ServerApi _serverInfo;
|
||||
|
||||
ServerApi get _serverInfo => _api.getServerApi();
|
||||
|
||||
ServerInfoService(this._api);
|
||||
const ServerInfoService(this._serverInfo);
|
||||
|
||||
Future<ServerFeatures?> getServerFeatures() async {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import 'package:drift/isolate.dart';
|
||||
import 'package:immich_mobile/domain/interfaces/remote_asset.interface.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/remote_asset.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/domain/repositories/database.repository.dart';
|
||||
import 'package:immich_mobile/service_locator.dart';
|
||||
import 'package:immich_mobile/utils/constants/globals.dart';
|
||||
import 'package:immich_mobile/utils/immich_api_client.dart';
|
||||
import 'package:immich_mobile/utils/log_manager.dart';
|
||||
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class SyncService with LogContext {
|
||||
final ImmichApiClient _appClient;
|
||||
final DriftDatabaseRepository _db;
|
||||
|
||||
SyncService(this._appClient, this._db);
|
||||
|
||||
Future<bool> doFullSyncForUserDrift(
|
||||
User user, {
|
||||
DateTime? updatedUtil,
|
||||
int? limit,
|
||||
}) async {
|
||||
final clientData = _appClient.clientData;
|
||||
try {
|
||||
await _db.computeWithDatabase(
|
||||
connect: (connection) => DriftDatabaseRepository(connection),
|
||||
computation: (database) async {
|
||||
ServiceLocator.configureServicesForIsolate(database: database);
|
||||
LogManager.I.init();
|
||||
final logger = Logger("SyncService <Isolate>");
|
||||
final syncClient =
|
||||
ImmichApiClient.clientData(clientData).getSyncApi();
|
||||
|
||||
final chunkSize = limit ?? kFullSyncChunkSize;
|
||||
final updatedTill = updatedUtil ?? DateTime.now().toUtc();
|
||||
updatedUtil ??= DateTime.now().toUtc();
|
||||
String? lastAssetId;
|
||||
|
||||
while (true) {
|
||||
logger.info(
|
||||
"Requesting more chunks from lastId - ${lastAssetId ?? "<initial_fetch>"}",
|
||||
);
|
||||
|
||||
final assets = await syncClient.getFullSyncForUser(AssetFullSyncDto(
|
||||
limit: chunkSize,
|
||||
updatedUntil: updatedTill,
|
||||
lastId: lastAssetId,
|
||||
userId: user.id,
|
||||
));
|
||||
if (assets == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
await di<IRemoteAssetRepository>()
|
||||
.addAll(assets.map(RemoteAsset.fromDto));
|
||||
|
||||
lastAssetId = assets.lastOrNull?.id;
|
||||
if (assets.length != chunkSize) break;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
);
|
||||
} catch (e, s) {
|
||||
log.severe("Error performing full sync for user - ${user.name}", e, s);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/utils/immich_api_client.dart';
|
||||
import 'package:immich_mobile/utils/mixins/log_context.mixin.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class UserService with LogContext {
|
||||
final ImmichApiClient _api;
|
||||
final UsersApi _userApi;
|
||||
|
||||
UsersApi get _userApi => _api.getUsersApi();
|
||||
|
||||
UserService(this._api);
|
||||
const UserService(this._userApi);
|
||||
|
||||
Future<User?> getMyUser() async {
|
||||
try {
|
||||
@@ -21,7 +18,7 @@ class UserService with LogContext {
|
||||
final preferencesDto = await _userApi.getMyPreferences();
|
||||
return User.fromAdminDto(userDto, preferencesDto);
|
||||
} catch (e, s) {
|
||||
log.severe("Error while fetching server features", e, s);
|
||||
log.severe("Error while fetching my user", e, s);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class StoreUserConverter extends IStoreConverter<User, String> {
|
||||
|
||||
@override
|
||||
Future<User?> fromPrimitive(String value) async {
|
||||
return await di<IUserRepository>().getUser(value);
|
||||
return await di<IUserRepository>().fetch(value);
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Reference in New Issue
Block a user