mirror of
https://github.com/immich-app/immich
synced 2026-08-15 13:03:57 +00:00
refactor: use currentUser for auth user table
This commit is contained in:
parent
f71b8aa2d9
commit
5f87e6a4ce
23 changed files with 83 additions and 10800 deletions
|
|
@ -1,10 +1,7 @@
|
|||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
|
||||
/// Key for each possible value in the `Store`.
|
||||
/// Defines the data type for each value
|
||||
enum StoreKey<T> {
|
||||
version<int>._(0),
|
||||
currentUser<UserDto>._(2),
|
||||
deviceId<String>._(4),
|
||||
advancedTroubleshooting<bool>._(114),
|
||||
enableHapticFeedback<bool>._(126),
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@ import 'dart:async';
|
|||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/remote_album.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
import 'package:immich_mobile/utils/debug_print.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
|
@ -17,7 +16,7 @@ final syncLinkedAlbumServiceProvider = Provider(
|
|||
ref.watch(localAlbumRepository),
|
||||
ref.watch(remoteAlbumRepository),
|
||||
ref.watch(driftAlbumApiRepositoryProvider),
|
||||
ref.watch(storeServiceProvider),
|
||||
ref.watch(authUserRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
@ -25,13 +24,13 @@ class SyncLinkedAlbumService {
|
|||
final DriftLocalAlbumRepository _localAlbumRepository;
|
||||
final DriftRemoteAlbumRepository _remoteAlbumRepository;
|
||||
final DriftAlbumApiRepository _albumApiRepository;
|
||||
final StoreService _storeService;
|
||||
final DriftAuthUserRepository _authUserRepository;
|
||||
|
||||
SyncLinkedAlbumService(
|
||||
this._localAlbumRepository,
|
||||
this._remoteAlbumRepository,
|
||||
this._albumApiRepository,
|
||||
this._storeService,
|
||||
this._authUserRepository,
|
||||
);
|
||||
|
||||
final _log = Logger("SyncLinkedAlbumService");
|
||||
|
|
@ -119,11 +118,12 @@ class SyncLinkedAlbumService {
|
|||
/// Creates a new remote album and links it to the local album
|
||||
Future<void> _createAndLinkNewRemoteAlbum(LocalAlbum localAlbum) async {
|
||||
dPrint(() => "Creating new remote album for local album: ${localAlbum.name}");
|
||||
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(
|
||||
localAlbum.name,
|
||||
_storeService.get(StoreKey.currentUser),
|
||||
assetIds: [],
|
||||
);
|
||||
final currentUser = await _authUserRepository.get();
|
||||
if (currentUser == null) {
|
||||
_log.warning("No user logged in, skipping remote album creation for local album: ${localAlbum.name}");
|
||||
return;
|
||||
}
|
||||
final newRemoteAlbum = await _albumApiRepository.createDriftAlbum(localAlbum.name, currentUser, assetIds: []);
|
||||
await _remoteAlbumRepository.create(newRemoteAlbum, []);
|
||||
return _localAlbumRepository.linkRemoteAlbum(localAlbum.id, newRemoteAlbum.id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,24 @@
|
|||
import 'dart:async';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
class UserService {
|
||||
final Logger _log = Logger("UserService");
|
||||
final UserApiRepository _userApiRepository;
|
||||
final StoreService _storeService;
|
||||
final DriftAuthUserRepository _authUserRepository;
|
||||
|
||||
UserService({required this._userApiRepository, required this._storeService});
|
||||
UserService({required this._userApiRepository, required this._authUserRepository});
|
||||
|
||||
UserDto getMyUser() {
|
||||
return _storeService.get(StoreKey.currentUser);
|
||||
}
|
||||
|
||||
UserDto? tryGetMyUser() {
|
||||
return _storeService.tryGet(StoreKey.currentUser);
|
||||
Future<UserDto?> tryGetMyUser() {
|
||||
return _authUserRepository.get();
|
||||
}
|
||||
|
||||
Stream<UserDto?> watchMyUser() {
|
||||
return _storeService.watch(StoreKey.currentUser);
|
||||
return _authUserRepository.watch();
|
||||
}
|
||||
|
||||
Future<UserDto?> refreshMyUser() async {
|
||||
|
|
@ -31,15 +26,17 @@ class UserService {
|
|||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
await _storeService.put(StoreKey.currentUser, user);
|
||||
await _authUserRepository.upsert(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
Future<String?> createProfileImage(String name, Uint8List image) async {
|
||||
try {
|
||||
final path = await _userApiRepository.createProfileImage(name: name, data: image);
|
||||
final updatedUser = getMyUser();
|
||||
await _storeService.put(StoreKey.currentUser, updatedUser);
|
||||
final updatedUser = await tryGetMyUser();
|
||||
if (updatedUser != null) {
|
||||
await _authUserRepository.upsert(updatedUser);
|
||||
}
|
||||
return path;
|
||||
} catch (e) {
|
||||
_log.warning("Failed to upload profile image", e);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/cancel.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) {
|
||||
final user = Store.tryGet(StoreKey.currentUser);
|
||||
Future<void> syncLinkedAlbumsIsolated(ProviderContainer ref) async {
|
||||
final user = await ref.read(authUserRepositoryProvider).get();
|
||||
if (user == null) {
|
||||
Logger("SyncLinkedAlbum").warning("No user logged in, skipping linked album sync");
|
||||
return Future.value();
|
||||
return;
|
||||
}
|
||||
return ref
|
||||
.read(syncLinkedAlbumServiceProvider)
|
||||
|
|
|
|||
|
|
@ -1,427 +0,0 @@
|
|||
// dart format width=80
|
||||
// ignore_for_file: type=lint
|
||||
import 'package:drift/drift.dart' as i0;
|
||||
import 'package:immich_mobile/infrastructure/entities/session.entity.drift.dart'
|
||||
as i1;
|
||||
import 'package:immich_mobile/infrastructure/entities/session.entity.dart'
|
||||
as i2;
|
||||
import 'package:drift/src/runtime/query_builder/query_builder.dart' as i3;
|
||||
|
||||
typedef $$SessionEntityTableCreateCompanionBuilder =
|
||||
i1.SessionEntityCompanion Function({
|
||||
required String key,
|
||||
i0.Value<String?> value,
|
||||
i0.Value<DateTime> updatedAt,
|
||||
});
|
||||
typedef $$SessionEntityTableUpdateCompanionBuilder =
|
||||
i1.SessionEntityCompanion Function({
|
||||
i0.Value<String> key,
|
||||
i0.Value<String?> value,
|
||||
i0.Value<DateTime> updatedAt,
|
||||
});
|
||||
|
||||
class $$SessionEntityTableFilterComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SessionEntityTable> {
|
||||
$$SessionEntityTableFilterComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnFilters<String> get key => $composableBuilder(
|
||||
column: $table.key,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<String> get value => $composableBuilder(
|
||||
column: $table.value,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
|
||||
i0.ColumnFilters<DateTime> get updatedAt => $composableBuilder(
|
||||
column: $table.updatedAt,
|
||||
builder: (column) => i0.ColumnFilters(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$SessionEntityTableOrderingComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SessionEntityTable> {
|
||||
$$SessionEntityTableOrderingComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.ColumnOrderings<String> get key => $composableBuilder(
|
||||
column: $table.key,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<String> get value => $composableBuilder(
|
||||
column: $table.value,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
|
||||
i0.ColumnOrderings<DateTime> get updatedAt => $composableBuilder(
|
||||
column: $table.updatedAt,
|
||||
builder: (column) => i0.ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$SessionEntityTableAnnotationComposer
|
||||
extends i0.Composer<i0.GeneratedDatabase, i1.$SessionEntityTable> {
|
||||
$$SessionEntityTableAnnotationComposer({
|
||||
required super.$db,
|
||||
required super.$table,
|
||||
super.joinBuilder,
|
||||
super.$addJoinBuilderToRootComposer,
|
||||
super.$removeJoinBuilderFromRootComposer,
|
||||
});
|
||||
i0.GeneratedColumn<String> get key =>
|
||||
$composableBuilder(column: $table.key, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<String> get value =>
|
||||
$composableBuilder(column: $table.value, builder: (column) => column);
|
||||
|
||||
i0.GeneratedColumn<DateTime> get updatedAt =>
|
||||
$composableBuilder(column: $table.updatedAt, builder: (column) => column);
|
||||
}
|
||||
|
||||
class $$SessionEntityTableTableManager
|
||||
extends
|
||||
i0.RootTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$SessionEntityTable,
|
||||
i1.SessionEntityData,
|
||||
i1.$$SessionEntityTableFilterComposer,
|
||||
i1.$$SessionEntityTableOrderingComposer,
|
||||
i1.$$SessionEntityTableAnnotationComposer,
|
||||
$$SessionEntityTableCreateCompanionBuilder,
|
||||
$$SessionEntityTableUpdateCompanionBuilder,
|
||||
(
|
||||
i1.SessionEntityData,
|
||||
i0.BaseReferences<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$SessionEntityTable,
|
||||
i1.SessionEntityData
|
||||
>,
|
||||
),
|
||||
i1.SessionEntityData,
|
||||
i0.PrefetchHooks Function()
|
||||
> {
|
||||
$$SessionEntityTableTableManager(
|
||||
i0.GeneratedDatabase db,
|
||||
i1.$SessionEntityTable table,
|
||||
) : super(
|
||||
i0.TableManagerState(
|
||||
db: db,
|
||||
table: table,
|
||||
createFilteringComposer: () =>
|
||||
i1.$$SessionEntityTableFilterComposer($db: db, $table: table),
|
||||
createOrderingComposer: () =>
|
||||
i1.$$SessionEntityTableOrderingComposer($db: db, $table: table),
|
||||
createComputedFieldComposer: () =>
|
||||
i1.$$SessionEntityTableAnnotationComposer($db: db, $table: table),
|
||||
updateCompanionCallback:
|
||||
({
|
||||
i0.Value<String> key = const i0.Value.absent(),
|
||||
i0.Value<String?> value = const i0.Value.absent(),
|
||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||
}) => i1.SessionEntityCompanion(
|
||||
key: key,
|
||||
value: value,
|
||||
updatedAt: updatedAt,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
required String key,
|
||||
i0.Value<String?> value = const i0.Value.absent(),
|
||||
i0.Value<DateTime> updatedAt = const i0.Value.absent(),
|
||||
}) => i1.SessionEntityCompanion.insert(
|
||||
key: key,
|
||||
value: value,
|
||||
updatedAt: updatedAt,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map((e) => (e.readTable(table), i0.BaseReferences(db, table, e)))
|
||||
.toList(),
|
||||
prefetchHooksCallback: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
typedef $$SessionEntityTableProcessedTableManager =
|
||||
i0.ProcessedTableManager<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$SessionEntityTable,
|
||||
i1.SessionEntityData,
|
||||
i1.$$SessionEntityTableFilterComposer,
|
||||
i1.$$SessionEntityTableOrderingComposer,
|
||||
i1.$$SessionEntityTableAnnotationComposer,
|
||||
$$SessionEntityTableCreateCompanionBuilder,
|
||||
$$SessionEntityTableUpdateCompanionBuilder,
|
||||
(
|
||||
i1.SessionEntityData,
|
||||
i0.BaseReferences<
|
||||
i0.GeneratedDatabase,
|
||||
i1.$SessionEntityTable,
|
||||
i1.SessionEntityData
|
||||
>,
|
||||
),
|
||||
i1.SessionEntityData,
|
||||
i0.PrefetchHooks Function()
|
||||
>;
|
||||
|
||||
class $SessionEntityTable extends i2.SessionEntity
|
||||
with i0.TableInfo<$SessionEntityTable, i1.SessionEntityData> {
|
||||
@override
|
||||
final i0.GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$SessionEntityTable(this.attachedDatabase, [this._alias]);
|
||||
static const i0.VerificationMeta _keyMeta = const i0.VerificationMeta('key');
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> key = i0.GeneratedColumn<String>(
|
||||
'key',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const i0.VerificationMeta _valueMeta = const i0.VerificationMeta(
|
||||
'value',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<String> value = i0.GeneratedColumn<String>(
|
||||
'value',
|
||||
aliasedName,
|
||||
true,
|
||||
type: i0.DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const i0.VerificationMeta _updatedAtMeta = const i0.VerificationMeta(
|
||||
'updatedAt',
|
||||
);
|
||||
@override
|
||||
late final i0.GeneratedColumn<DateTime> updatedAt =
|
||||
i0.GeneratedColumn<DateTime>(
|
||||
'updated_at',
|
||||
aliasedName,
|
||||
false,
|
||||
type: i0.DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: i3.currentDateAndTime,
|
||||
);
|
||||
@override
|
||||
List<i0.GeneratedColumn> get $columns => [key, value, updatedAt];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'session';
|
||||
@override
|
||||
i0.VerificationContext validateIntegrity(
|
||||
i0.Insertable<i1.SessionEntityData> instance, {
|
||||
bool isInserting = false,
|
||||
}) {
|
||||
final context = i0.VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('key')) {
|
||||
context.handle(
|
||||
_keyMeta,
|
||||
key.isAcceptableOrUnknown(data['key']!, _keyMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_keyMeta);
|
||||
}
|
||||
if (data.containsKey('value')) {
|
||||
context.handle(
|
||||
_valueMeta,
|
||||
value.isAcceptableOrUnknown(data['value']!, _valueMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('updated_at')) {
|
||||
context.handle(
|
||||
_updatedAtMeta,
|
||||
updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta),
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<i0.GeneratedColumn> get $primaryKey => {key};
|
||||
@override
|
||||
i1.SessionEntityData map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return i1.SessionEntityData(
|
||||
key: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}key'],
|
||||
)!,
|
||||
value: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.string,
|
||||
data['${effectivePrefix}value'],
|
||||
),
|
||||
updatedAt: attachedDatabase.typeMapping.read(
|
||||
i0.DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}updated_at'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$SessionEntityTable createAlias(String alias) {
|
||||
return $SessionEntityTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
@override
|
||||
bool get withoutRowId => true;
|
||||
@override
|
||||
bool get isStrict => true;
|
||||
}
|
||||
|
||||
class SessionEntityData extends i0.DataClass
|
||||
implements i0.Insertable<i1.SessionEntityData> {
|
||||
final String key;
|
||||
final String? value;
|
||||
final DateTime updatedAt;
|
||||
const SessionEntityData({
|
||||
required this.key,
|
||||
this.value,
|
||||
required this.updatedAt,
|
||||
});
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
map['key'] = i0.Variable<String>(key);
|
||||
if (!nullToAbsent || value != null) {
|
||||
map['value'] = i0.Variable<String>(value);
|
||||
}
|
||||
map['updated_at'] = i0.Variable<DateTime>(updatedAt);
|
||||
return map;
|
||||
}
|
||||
|
||||
factory SessionEntityData.fromJson(
|
||||
Map<String, dynamic> json, {
|
||||
i0.ValueSerializer? serializer,
|
||||
}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return SessionEntityData(
|
||||
key: serializer.fromJson<String>(json['key']),
|
||||
value: serializer.fromJson<String?>(json['value']),
|
||||
updatedAt: serializer.fromJson<DateTime>(json['updatedAt']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({i0.ValueSerializer? serializer}) {
|
||||
serializer ??= i0.driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'key': serializer.toJson<String>(key),
|
||||
'value': serializer.toJson<String?>(value),
|
||||
'updatedAt': serializer.toJson<DateTime>(updatedAt),
|
||||
};
|
||||
}
|
||||
|
||||
i1.SessionEntityData copyWith({
|
||||
String? key,
|
||||
i0.Value<String?> value = const i0.Value.absent(),
|
||||
DateTime? updatedAt,
|
||||
}) => i1.SessionEntityData(
|
||||
key: key ?? this.key,
|
||||
value: value.present ? value.value : this.value,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
SessionEntityData copyWithCompanion(i1.SessionEntityCompanion data) {
|
||||
return SessionEntityData(
|
||||
key: data.key.present ? data.key.value : this.key,
|
||||
value: data.value.present ? data.value.value : this.value,
|
||||
updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('SessionEntityData(')
|
||||
..write('key: $key, ')
|
||||
..write('value: $value, ')
|
||||
..write('updatedAt: $updatedAt')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(key, value, updatedAt);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is i1.SessionEntityData &&
|
||||
other.key == this.key &&
|
||||
other.value == this.value &&
|
||||
other.updatedAt == this.updatedAt);
|
||||
}
|
||||
|
||||
class SessionEntityCompanion extends i0.UpdateCompanion<i1.SessionEntityData> {
|
||||
final i0.Value<String> key;
|
||||
final i0.Value<String?> value;
|
||||
final i0.Value<DateTime> updatedAt;
|
||||
const SessionEntityCompanion({
|
||||
this.key = const i0.Value.absent(),
|
||||
this.value = const i0.Value.absent(),
|
||||
this.updatedAt = const i0.Value.absent(),
|
||||
});
|
||||
SessionEntityCompanion.insert({
|
||||
required String key,
|
||||
this.value = const i0.Value.absent(),
|
||||
this.updatedAt = const i0.Value.absent(),
|
||||
}) : key = i0.Value(key);
|
||||
static i0.Insertable<i1.SessionEntityData> custom({
|
||||
i0.Expression<String>? key,
|
||||
i0.Expression<String>? value,
|
||||
i0.Expression<DateTime>? updatedAt,
|
||||
}) {
|
||||
return i0.RawValuesInsertable({
|
||||
if (key != null) 'key': key,
|
||||
if (value != null) 'value': value,
|
||||
if (updatedAt != null) 'updated_at': updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
i1.SessionEntityCompanion copyWith({
|
||||
i0.Value<String>? key,
|
||||
i0.Value<String?>? value,
|
||||
i0.Value<DateTime>? updatedAt,
|
||||
}) {
|
||||
return i1.SessionEntityCompanion(
|
||||
key: key ?? this.key,
|
||||
value: value ?? this.value,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, i0.Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, i0.Expression>{};
|
||||
if (key.present) {
|
||||
map['key'] = i0.Variable<String>(key.value);
|
||||
}
|
||||
if (value.present) {
|
||||
map['value'] = i0.Variable<String>(value.value);
|
||||
}
|
||||
if (updatedAt.present) {
|
||||
map['updated_at'] = i0.Variable<DateTime>(updatedAt.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('SessionEntityCompanion(')
|
||||
..write('key: $key, ')
|
||||
..write('value: $value, ')
|
||||
..write('updatedAt: $updatedAt')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
|
||||
class DriftStoreRepository extends DriftDatabaseRepository {
|
||||
final Drift _db;
|
||||
|
|
@ -63,8 +61,6 @@ class DriftStoreRepository extends DriftDatabaseRepository {
|
|||
const (String) => entity.stringValue,
|
||||
const (bool) => entity.intValue == 1,
|
||||
const (DateTime) => entity.intValue == null ? null : DateTime.fromMillisecondsSinceEpoch(entity.intValue!),
|
||||
const (UserDto) =>
|
||||
entity.stringValue == null ? null : await DriftAuthUserRepository(_db).get(entity.stringValue!),
|
||||
_ => null,
|
||||
}
|
||||
as T?;
|
||||
|
|
@ -75,7 +71,6 @@ class DriftStoreRepository extends DriftDatabaseRepository {
|
|||
const (String) => (null, value as String),
|
||||
const (bool) => ((value as bool) ? 1 : 0, null),
|
||||
const (DateTime) => ((value as DateTime).millisecondsSinceEpoch, null),
|
||||
const (UserDto) => (null, (await DriftAuthUserRepository(_db).upsert(value as UserDto)).id),
|
||||
_ => throw UnsupportedError("Unsupported primitive type: ${key.type} for key: ${key.name}"),
|
||||
};
|
||||
return StoreEntityCompanion(id: Value(key.id), intValue: Value(intValue), stringValue: Value(strValue));
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@ class UserRepository {
|
|||
Stream<Iterable<User>> getAll() => _db.select(_db.userEntity).map(mapToUser).watch();
|
||||
}
|
||||
|
||||
// TODO(shenlong): migrate this to return AuthUser instead
|
||||
class DriftAuthUserRepository extends DriftDatabaseRepository {
|
||||
final Drift _db;
|
||||
const DriftAuthUserRepository(super.db) : _db = db;
|
||||
|
||||
Future<UserDto?> get(String id) async {
|
||||
final user = await _db.managers.authUserEntity.filter((user) => user.id.equals(id)).getSingleOrNull();
|
||||
Selectable<UserDto?> get _authUserQuery => (_db.authUserEntity.select()..limit(1)).asyncMap(_toDto);
|
||||
|
||||
if (user == null) {
|
||||
return null;
|
||||
}
|
||||
Future<UserDto?> get() => _authUserQuery.getSingleOrNull();
|
||||
|
||||
final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(id));
|
||||
Stream<UserDto?> watch() => _authUserQuery.watchSingleOrNull();
|
||||
|
||||
Future<UserDto> _toDto(AuthUserEntityData user) async {
|
||||
final query = _db.userMetadataEntity.select()..where((e) => e.userId.equals(user.id));
|
||||
final metadata = await query.map((row) => row.toDto()).get();
|
||||
|
||||
return user.toDto(metadata);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@ import 'package:easy_localization/easy_localization.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.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/platform_extensions.dart';
|
||||
import 'package:immich_mobile/extensions/theme_extensions.dart';
|
||||
|
|
@ -85,7 +83,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
|||
final backupSyncManager = ref.watch(backgroundSyncProvider);
|
||||
|
||||
Future<void> startBackup() async {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = ref.read(currentUserProvider);
|
||||
if (currentUser == null) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,16 +8,16 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||
import 'package:immich_mobile/constants/locales.dart';
|
||||
import 'package:immich_mobile/domain/models/config/app_config.dart';
|
||||
import 'package:immich_mobile/domain/models/session.model.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/generated/codegen_loader.g.dart';
|
||||
import 'package:immich_mobile/generated/translations.g.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
import 'package:immich_mobile/providers/backup/drift_backup.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/session.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/view_intent/view_intent_handler.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
|
|
@ -311,6 +311,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||
final backgroundManager = ref.read(backgroundSyncProvider);
|
||||
final backupProvider = ref.read(driftBackupProvider.notifier);
|
||||
final viewIntentHandler = ref.read(viewIntentHandlerProvider);
|
||||
final authUserRepository = ref.read(authUserRepositoryProvider);
|
||||
|
||||
unawaited(
|
||||
ref
|
||||
|
|
@ -333,9 +334,9 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||
if (syncSuccess) {
|
||||
await Future.wait([
|
||||
backgroundManager.hashAssets().then((_) {
|
||||
unawaited(_resumeBackup(backupProvider));
|
||||
unawaited(_resumeBackup(backupProvider, authUserRepository));
|
||||
}),
|
||||
_resumeBackup(backupProvider),
|
||||
_resumeBackup(backupProvider, authUserRepository),
|
||||
// TODO: Bring back when the soft freeze issue is addressed
|
||||
// backgroundManager.syncCloudIds(),
|
||||
]);
|
||||
|
|
@ -375,11 +376,11 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> _resumeBackup(DriftBackupNotifier notifier) async {
|
||||
Future<void> _resumeBackup(DriftBackupNotifier notifier, DriftAuthUserRepository authUserRepository) async {
|
||||
final isEnableBackup = SettingsRepository.instance.appConfig.backup.enabled;
|
||||
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = await authUserRepository.get();
|
||||
if (currentUser != null) {
|
||||
unawaited(notifier.startForegroundBackup(currentUser.id));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/log.service.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/extensions/platform_extensions.dart';
|
||||
import 'package:immich_mobile/providers/auth.provider.dart';
|
||||
import 'package:immich_mobile/providers/background_sync.provider.dart';
|
||||
|
|
@ -14,6 +12,7 @@ import 'package:immich_mobile/providers/infrastructure/platform.provider.dart';
|
|||
import 'package:immich_mobile/providers/infrastructure/settings.provider.dart';
|
||||
import 'package:immich_mobile/providers/permission.provider.dart';
|
||||
import 'package:immich_mobile/providers/server_info.provider.dart';
|
||||
import 'package:immich_mobile/providers/user.provider.dart';
|
||||
import 'package:immich_mobile/providers/websocket.provider.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
|
||||
|
|
@ -148,7 +147,7 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
|||
final isEnableBackup = _ref.read(appConfigProvider).backup.enabled;
|
||||
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
final currentUser = _ref.read(currentUserProvider);
|
||||
if (currentUser != null) {
|
||||
await _safeRun(
|
||||
() => _ref.read(driftBackupProvider.notifier).startForegroundBackup(currentUser.id),
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||
// Get the deviceid from the store if it exists, otherwise generate a new one
|
||||
final String deviceId = Store.tryGet(StoreKey.deviceId) ?? await FlutterUdid.consistentUdid;
|
||||
|
||||
UserDto? user = _userService.tryGetMyUser();
|
||||
UserDto? user = await _userService.tryGetMyUser();
|
||||
|
||||
try {
|
||||
final serverUser = await _userService.refreshMyUser().timeout(_timeoutDuration);
|
||||
|
|
|
|||
|
|
@ -6,17 +6,18 @@ import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
|||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/db.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/repositories/partner_api.repository.dart';
|
||||
|
||||
final userRepositoryProvider = Provider((ref) => UserRepository(ref.watch(driftProvider)));
|
||||
|
||||
final authUserRepositoryProvider = Provider((ref) => DriftAuthUserRepository(ref.watch(driftProvider)));
|
||||
|
||||
final userApiRepositoryProvider = Provider((ref) => UserApiRepository(ref.watch(apiServiceProvider).usersApi));
|
||||
|
||||
final userServiceProvider = Provider(
|
||||
(ref) => UserService(
|
||||
userApiRepository: ref.watch(userApiRepositoryProvider),
|
||||
storeService: ref.watch(storeServiceProvider),
|
||||
authUserRepository: ref.watch(authUserRepositoryProvider),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
|||
|
||||
class CurrentUserProvider extends StateNotifier<UserDto?> {
|
||||
CurrentUserProvider(this._userService) : super(null) {
|
||||
state = _userService.tryGetMyUser();
|
||||
unawaited(_userService.tryGetMyUser().then((user) => state = user ?? state));
|
||||
streamSub = _userService.watchMyUser().listen((user) => state = user ?? state);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,9 +3,7 @@ import 'dart:async';
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/models/session.model.dart';
|
||||
import 'package:immich_mobile/domain/models/settings_key.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/utils/background_sync.dart';
|
||||
import 'package:immich_mobile/entities/store.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/session.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/settings.repository.dart';
|
||||
|
|
@ -120,7 +118,6 @@ class AuthService {
|
|||
await _backgroundSyncManager.cancel();
|
||||
await Future.wait([
|
||||
_authRepository.clearLocalData(),
|
||||
Store.delete(StoreKey.currentUser),
|
||||
SessionRepository.instance.clear([SessionKey.accessToken]),
|
||||
SettingsRepository.instance.clear(const [
|
||||
.networkAutoEndpointSwitching,
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ void main() {
|
|||
expect(sut.tryGet(StoreKey.advancedTroubleshooting), _kAdvancedTroubleshooting);
|
||||
expect(sut.tryGet(StoreKey.version), _kVersion);
|
||||
// Other keys should be null
|
||||
expect(sut.tryGet(StoreKey.currentUser), isNull);
|
||||
expect(sut.tryGet(StoreKey.deviceId), isNull);
|
||||
});
|
||||
|
||||
test('Listens to stream of store updates', () async {
|
||||
|
|
@ -69,11 +69,11 @@ void main() {
|
|||
});
|
||||
|
||||
test('Throws StoreKeyNotFoundException for nonexistent keys', () {
|
||||
expect(() => sut.get(StoreKey.currentUser), throwsA(isA<StoreKeyNotFoundException>()));
|
||||
expect(() => sut.get(StoreKey.deviceId), throwsA(isA<StoreKeyNotFoundException>()));
|
||||
});
|
||||
|
||||
test('Returns the stored value for the given key or the defaultValue', () {
|
||||
expect(sut.get(StoreKey.currentUser, 5), 5);
|
||||
expect(sut.get(StoreKey.legacyBackupTriggerDelay, 5), 5);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,10 @@ import 'package:flutter_test/flutter_test.dart';
|
|||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/domain/services/sync_linked_album.service.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/store.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/user.provider.dart';
|
||||
import 'package:immich_mobile/repositories/drift_album_api_repository.dart';
|
||||
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
import '../../service.mocks.dart';
|
||||
|
||||
void main() {
|
||||
// A container with the service's deps overridden but cancellationProvider left
|
||||
|
|
@ -18,7 +17,7 @@ void main() {
|
|||
localAlbumRepository.overrideWithValue(MockLocalAlbumRepository()),
|
||||
remoteAlbumRepository.overrideWithValue(MockRemoteAlbumRepository()),
|
||||
driftAlbumApiRepositoryProvider.overrideWithValue(MockDriftAlbumApiRepository()),
|
||||
storeServiceProvider.overrideWithValue(MockStoreService()),
|
||||
authUserRepositoryProvider.overrideWithValue(MockDriftAuthUserRepository()),
|
||||
],
|
||||
);
|
||||
addTearDown(container.dispose);
|
||||
|
|
|
|||
|
|
@ -1,78 +1,62 @@
|
|||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/services/store.service.dart';
|
||||
import 'package:immich_mobile/domain/services/user.service.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/user_api.repository.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
|
||||
import '../../fixtures/user.stub.dart';
|
||||
import '../../infrastructure/repository.mock.dart';
|
||||
import '../../service.mocks.dart';
|
||||
|
||||
void main() {
|
||||
late UserService sut;
|
||||
late UserApiRepository mockUserApiRepo;
|
||||
late StoreService mockStoreService;
|
||||
late DriftAuthUserRepository mockAuthUserRepo;
|
||||
|
||||
setUp(() {
|
||||
mockUserApiRepo = MockUserApiRepository();
|
||||
mockStoreService = MockStoreService();
|
||||
sut = UserService(userApiRepository: mockUserApiRepo, storeService: mockStoreService);
|
||||
mockAuthUserRepo = MockDriftAuthUserRepository();
|
||||
sut = UserService(userApiRepository: mockUserApiRepo, authUserRepository: mockAuthUserRepo);
|
||||
|
||||
registerFallbackValue(UserStub.admin);
|
||||
when(() => mockStoreService.get(StoreKey.currentUser)).thenReturn(UserStub.admin);
|
||||
when(() => mockStoreService.tryGet(StoreKey.currentUser)).thenReturn(UserStub.admin);
|
||||
});
|
||||
|
||||
group('getMyUser', () {
|
||||
test('should return user from store', () {
|
||||
final result = sut.getMyUser();
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
test('should handle user not found scenario', () {
|
||||
when(() => mockStoreService.get(StoreKey.currentUser)).thenThrow(Exception('User not found'));
|
||||
|
||||
expect(() => sut.getMyUser(), throwsA(isA<Exception>()));
|
||||
});
|
||||
when(() => mockAuthUserRepo.get()).thenAnswer((_) async => UserStub.admin);
|
||||
when(() => mockAuthUserRepo.upsert(any())).thenAnswer((_) async => UserStub.admin);
|
||||
});
|
||||
|
||||
group('tryGetMyUser', () {
|
||||
test('should return user from store', () {
|
||||
final result = sut.tryGetMyUser();
|
||||
test('should return the current user from the auth user repository', () async {
|
||||
final result = await sut.tryGetMyUser();
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
test('should return null if user not found', () {
|
||||
when(() => mockStoreService.tryGet(StoreKey.currentUser)).thenReturn(null);
|
||||
final result = sut.tryGetMyUser();
|
||||
test('should return null if no user is logged in', () async {
|
||||
when(() => mockAuthUserRepo.get()).thenAnswer((_) async => null);
|
||||
final result = await sut.tryGetMyUser();
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('watchMyUser', () {
|
||||
test('should return user stream from store', () {
|
||||
when(() => mockStoreService.watch(StoreKey.currentUser)).thenAnswer((_) => Stream.value(UserStub.admin));
|
||||
test('should return the current user stream from the auth user repository', () {
|
||||
when(() => mockAuthUserRepo.watch()).thenAnswer((_) => Stream.value(UserStub.admin));
|
||||
final result = sut.watchMyUser();
|
||||
expect(result, emits(UserStub.admin));
|
||||
});
|
||||
|
||||
test('should return an empty stream if user not found', () {
|
||||
when(() => mockStoreService.watch(StoreKey.currentUser)).thenAnswer((_) => const Stream.empty());
|
||||
test('should return an empty stream if no user is logged in', () {
|
||||
when(() => mockAuthUserRepo.watch()).thenAnswer((_) => const Stream.empty());
|
||||
final result = sut.watchMyUser();
|
||||
expect(result, emitsInOrder([]));
|
||||
});
|
||||
});
|
||||
|
||||
group('refreshMyUser', () {
|
||||
test('should return user from api and store it', () async {
|
||||
test('should return user from api and persist it', () async {
|
||||
when(() => mockUserApiRepo.getMyUser()).thenAnswer((_) async => UserStub.admin);
|
||||
when(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin)).thenAnswer((_) async => true);
|
||||
|
||||
final result = await sut.refreshMyUser();
|
||||
verify(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin)).called(1);
|
||||
verify(() => mockAuthUserRepo.upsert(UserStub.admin)).called(1);
|
||||
expect(result, UserStub.admin);
|
||||
});
|
||||
|
||||
|
|
@ -80,7 +64,7 @@ void main() {
|
|||
when(() => mockUserApiRepo.getMyUser()).thenAnswer((_) async => null);
|
||||
|
||||
final result = await sut.refreshMyUser();
|
||||
verifyNever(() => mockStoreService.put(StoreKey.currentUser, UserStub.admin));
|
||||
verifyNever(() => mockAuthUserRepo.upsert(any()));
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
|
|
@ -88,29 +72,26 @@ void main() {
|
|||
group('createProfileImage', () {
|
||||
test('should return profile image path', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
).thenAnswer((_) async => profileImagePath);
|
||||
when(() => mockStoreService.put(StoreKey.currentUser, updatedUser)).thenAnswer((_) async => true);
|
||||
|
||||
final result = await sut.createProfileImage(profileImagePath, Uint8List(0));
|
||||
|
||||
verify(() => mockStoreService.put(StoreKey.currentUser, updatedUser)).called(1);
|
||||
verify(() => mockAuthUserRepo.upsert(UserStub.admin)).called(1);
|
||||
expect(result, profileImagePath);
|
||||
});
|
||||
|
||||
test('should return null if profile image creation fails', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
).thenThrow(Exception('Failed to create profile image'));
|
||||
|
||||
final result = await sut.createProfileImage(profileImagePath, Uint8List(0));
|
||||
verifyNever(() => mockStoreService.put(StoreKey.currentUser, updatedUser));
|
||||
verifyNever(() => mockAuthUserRepo.upsert(any()));
|
||||
expect(result, isNull);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,17 +4,13 @@ import 'package:drift/drift.dart' hide isNull;
|
|||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:immich_mobile/domain/models/store.model.dart';
|
||||
import 'package:immich_mobile/domain/models/user.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/store.entity.drift.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/store.repository.dart';
|
||||
|
||||
import '../../fixtures/user.stub.dart';
|
||||
|
||||
const _kTestAccessToken = "#TestToken";
|
||||
const _kTestVersion = 10;
|
||||
const _kTestAdvancedTroubleshooting = false;
|
||||
final _kTestUser = UserStub.admin;
|
||||
|
||||
Future<void> _populateStore(Drift db) async {
|
||||
await db.batch((batch) async {
|
||||
|
|
@ -82,14 +78,6 @@ void main() {
|
|||
advancedTroubleshooting = await sut.tryGet(StoreKey.advancedTroubleshooting);
|
||||
expect(advancedTroubleshooting, _kTestAdvancedTroubleshooting);
|
||||
});
|
||||
|
||||
test('converts user', () async {
|
||||
UserDto? user = await sut.tryGet(StoreKey.currentUser);
|
||||
expect(user, isNull);
|
||||
await sut.upsert(StoreKey.currentUser, _kTestUser);
|
||||
user = await sut.tryGet(StoreKey.currentUser);
|
||||
expect(user, _kTestUser);
|
||||
});
|
||||
});
|
||||
|
||||
group('Store Repository Deletes:', () {
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ class MockSyncMigrationRepository extends Mock implements SyncMigrationRepositor
|
|||
|
||||
class MockUserRepository extends Mock implements UserRepository {}
|
||||
|
||||
class MockDriftAuthUserRepository extends Mock implements DriftAuthUserRepository {}
|
||||
|
||||
class MockPartnerRepository extends Mock implements PartnerRepository {}
|
||||
|
||||
// API Repos
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ void main() {
|
|||
userService = MockUserService();
|
||||
|
||||
when(() => memoryService.getMemoryLane('user-1')).thenAnswer((_) async => []);
|
||||
when(() => userService.tryGetMyUser()).thenReturn(user());
|
||||
when(() => userService.tryGetMyUser()).thenAnswer((_) async => user());
|
||||
when(() => userService.watchMyUser()).thenAnswer((_) => const Stream.empty());
|
||||
});
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ void main() {
|
|||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
container.listen(driftMemoryFutureProvider, (_, __) {});
|
||||
async.flushMicrotasks();
|
||||
async.elapse(Duration.zero);
|
||||
|
||||
verify(() => memoryService.getMemoryLane('user-1')).called(1);
|
||||
|
||||
|
|
@ -67,7 +67,7 @@ void main() {
|
|||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
final subscription = container.listen(driftMemoryFutureProvider, (_, __) {});
|
||||
async.flushMicrotasks();
|
||||
async.elapse(Duration.zero);
|
||||
verify(() => memoryService.getMemoryLane('user-1')).called(1);
|
||||
|
||||
subscription.close();
|
||||
|
|
@ -79,7 +79,7 @@ void main() {
|
|||
});
|
||||
|
||||
test('does not query or arm the timer when memories are disabled', () {
|
||||
when(() => userService.tryGetMyUser()).thenReturn(user(memoryEnabled: false));
|
||||
when(() => userService.tryGetMyUser()).thenAnswer((_) async => user(memoryEnabled: false));
|
||||
|
||||
fakeAsync((async) {
|
||||
final container = makeContainer();
|
||||
|
|
|
|||
|
|
@ -144,8 +144,7 @@ class ServiceMocks {
|
|||
}
|
||||
|
||||
void _stubUserService() {
|
||||
when(user.getMyUser).thenReturn(UserFactory.createDto());
|
||||
when(user.tryGetMyUser).thenReturn(null);
|
||||
when(user.tryGetMyUser).thenAnswer((_) async => UserFactory.createDto());
|
||||
when(user.watchMyUser).thenAnswer((_) => const Stream.empty());
|
||||
when(user.refreshMyUser).thenAnswer((_) async => null);
|
||||
when(user.createProfileImage).thenAnswer((_) async => null);
|
||||
|
|
@ -301,10 +300,7 @@ extension type const PartnerServiceStub(MockPartnerService service) implements S
|
|||
}
|
||||
|
||||
extension type const UserServiceStub(MockUserService service) implements Stub<MockUserService> {
|
||||
UserDto Function() get getMyUser =>
|
||||
() => service.getMyUser();
|
||||
|
||||
UserDto? Function() get tryGetMyUser =>
|
||||
Future<UserDto?> Function() get tryGetMyUser =>
|
||||
() => service.tryGetMyUser();
|
||||
|
||||
Stream<UserDto?> Function() get watchMyUser =>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class PresentationContext {
|
|||
|
||||
List<Override> get overrides => [
|
||||
currentUserProvider.overrideWith((ref) => CurrentUserProvider(service.user.service)),
|
||||
authUserProvider.overrideWithValue(currentUser),
|
||||
assetServiceProvider.overrideWithValue(service.asset.service),
|
||||
cleanupServiceProvider.overrideWithValue(service.cleanup.service),
|
||||
remoteAlbumServiceProvider.overrideWithValue(service.album.service),
|
||||
|
|
@ -81,7 +82,7 @@ class PresentationContext {
|
|||
}
|
||||
|
||||
void setup() {
|
||||
when(service.user.tryGetMyUser).thenReturn(currentUser);
|
||||
when(service.user.tryGetMyUser).thenAnswer((_) async => currentUser);
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue