mirror of
https://github.com/zebrajr/immich.git
synced 2025-12-06 00:20:20 +01:00
fix: user profile images not working in beta timeline (#20203)
* fix user icons in album view * revert updateUsersV1 change * fix: UserDto merge issues * fix: update user entity * revert what I thought were merge issues turns out drift cant figure out when it needs to gen a file... * fix removed line * handle defaults for older servers * feat: checkpoint migrations * fix: use parenthesis instead of brackets * Update 1753800911775-ProfileImageCheckpointRemoval.ts * fix: sync stream updateUsersV1
This commit is contained in:
parent
da5deffd03
commit
097e132fba
BIN
mobile/drift_schemas/main/drift_schema_v5.json
generated
Normal file
BIN
mobile/drift_schemas/main/drift_schema_v5.json
generated
Normal file
Binary file not shown.
|
|
@ -11,7 +11,6 @@ class UserDto {
|
|||
final bool isAdmin;
|
||||
final DateTime updatedAt;
|
||||
|
||||
final String? profileImagePath;
|
||||
final AvatarColor avatarColor;
|
||||
|
||||
final bool memoryEnabled;
|
||||
|
|
@ -25,18 +24,22 @@ class UserDto {
|
|||
|
||||
bool get hasQuota => quotaSizeInBytes > 0;
|
||||
|
||||
final bool hasProfileImage;
|
||||
final DateTime profileChangedAt;
|
||||
|
||||
const UserDto({
|
||||
required this.id,
|
||||
required this.email,
|
||||
required this.name,
|
||||
required this.isAdmin,
|
||||
required this.updatedAt,
|
||||
this.profileImagePath,
|
||||
required this.profileChangedAt,
|
||||
this.avatarColor = AvatarColor.primary,
|
||||
this.memoryEnabled = true,
|
||||
this.inTimeline = false,
|
||||
this.isPartnerSharedBy = false,
|
||||
this.isPartnerSharedWith = false,
|
||||
this.hasProfileImage = false,
|
||||
this.quotaUsageInBytes = 0,
|
||||
this.quotaSizeInBytes = 0,
|
||||
});
|
||||
|
|
@ -49,14 +52,13 @@ email: $email,
|
|||
name: $name,
|
||||
isAdmin: $isAdmin,
|
||||
updatedAt: $updatedAt,
|
||||
profileImagePath: ${profileImagePath ?? '<NA>'},
|
||||
avatarColor: $avatarColor,
|
||||
memoryEnabled: $memoryEnabled,
|
||||
inTimeline: $inTimeline,
|
||||
isPartnerSharedBy: $isPartnerSharedBy,
|
||||
isPartnerSharedWith: $isPartnerSharedWith,
|
||||
quotaUsageInBytes: $quotaUsageInBytes,
|
||||
quotaSizeInBytes: $quotaSizeInBytes,
|
||||
hasProfileImage: $hasProfileImage
|
||||
profileChangedAt: $profileChangedAt
|
||||
}''';
|
||||
}
|
||||
|
||||
|
|
@ -66,28 +68,26 @@ quotaSizeInBytes: $quotaSizeInBytes,
|
|||
String? name,
|
||||
bool? isAdmin,
|
||||
DateTime? updatedAt,
|
||||
String? profileImagePath,
|
||||
AvatarColor? avatarColor,
|
||||
bool? memoryEnabled,
|
||||
bool? inTimeline,
|
||||
bool? isPartnerSharedBy,
|
||||
bool? isPartnerSharedWith,
|
||||
int? quotaUsageInBytes,
|
||||
int? quotaSizeInBytes,
|
||||
bool? hasProfileImage,
|
||||
DateTime? profileChangedAt,
|
||||
}) => UserDto(
|
||||
id: id ?? this.id,
|
||||
email: email ?? this.email,
|
||||
name: name ?? this.name,
|
||||
isAdmin: isAdmin ?? this.isAdmin,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
profileImagePath: profileImagePath ?? this.profileImagePath,
|
||||
avatarColor: avatarColor ?? this.avatarColor,
|
||||
memoryEnabled: memoryEnabled ?? this.memoryEnabled,
|
||||
inTimeline: inTimeline ?? this.inTimeline,
|
||||
isPartnerSharedBy: isPartnerSharedBy ?? this.isPartnerSharedBy,
|
||||
isPartnerSharedWith: isPartnerSharedWith ?? this.isPartnerSharedWith,
|
||||
quotaUsageInBytes: quotaUsageInBytes ?? this.quotaUsageInBytes,
|
||||
quotaSizeInBytes: quotaSizeInBytes ?? this.quotaSizeInBytes,
|
||||
hasProfileImage: hasProfileImage ?? this.hasProfileImage,
|
||||
profileChangedAt: profileChangedAt ?? this.profileChangedAt,
|
||||
);
|
||||
|
||||
@override
|
||||
|
|
@ -101,12 +101,11 @@ quotaSizeInBytes: $quotaSizeInBytes,
|
|||
other.name == name &&
|
||||
other.isPartnerSharedBy == isPartnerSharedBy &&
|
||||
other.isPartnerSharedWith == isPartnerSharedWith &&
|
||||
other.profileImagePath == profileImagePath &&
|
||||
other.isAdmin == isAdmin &&
|
||||
other.memoryEnabled == memoryEnabled &&
|
||||
other.inTimeline == inTimeline &&
|
||||
other.quotaUsageInBytes == quotaUsageInBytes &&
|
||||
other.quotaSizeInBytes == quotaSizeInBytes;
|
||||
other.hasProfileImage == hasProfileImage &&
|
||||
other.profileChangedAt.isAtSameMomentAs(profileChangedAt);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -116,14 +115,13 @@ quotaSizeInBytes: $quotaSizeInBytes,
|
|||
email.hashCode ^
|
||||
updatedAt.hashCode ^
|
||||
isAdmin.hashCode ^
|
||||
profileImagePath.hashCode ^
|
||||
avatarColor.hashCode ^
|
||||
memoryEnabled.hashCode ^
|
||||
inTimeline.hashCode ^
|
||||
isPartnerSharedBy.hashCode ^
|
||||
isPartnerSharedWith.hashCode ^
|
||||
quotaUsageInBytes.hashCode ^
|
||||
quotaSizeInBytes.hashCode;
|
||||
hasProfileImage.hashCode ^
|
||||
profileChangedAt.hashCode;
|
||||
}
|
||||
|
||||
class PartnerUserDto {
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class UserService {
|
|||
Future<String?> createProfileImage(String name, Uint8List image) async {
|
||||
try {
|
||||
final path = await _userApiRepository.createProfileImage(name: name, data: image);
|
||||
final updatedUser = getMyUser().copyWith(profileImagePath: path);
|
||||
final updatedUser = getMyUser();
|
||||
await _storeService.put(StoreKey.currentUser, updatedUser);
|
||||
await _isarUserRepository.update(updatedUser);
|
||||
return path;
|
||||
|
|
|
|||
|
|
@ -50,12 +50,10 @@ class User {
|
|||
isAdmin: dto.isAdmin,
|
||||
isPartnerSharedBy: dto.isPartnerSharedBy,
|
||||
isPartnerSharedWith: dto.isPartnerSharedWith,
|
||||
profileImagePath: dto.profileImagePath ?? "",
|
||||
profileImagePath: dto.hasProfileImage ? "HAS_PROFILE_IMAGE" : "",
|
||||
avatarColor: dto.avatarColor,
|
||||
memoryEnabled: dto.memoryEnabled,
|
||||
inTimeline: dto.inTimeline,
|
||||
quotaUsageInBytes: dto.quotaUsageInBytes,
|
||||
quotaSizeInBytes: dto.quotaSizeInBytes,
|
||||
);
|
||||
|
||||
UserDto toDto() => UserDto(
|
||||
|
|
@ -64,12 +62,13 @@ class User {
|
|||
name: name,
|
||||
isAdmin: isAdmin,
|
||||
updatedAt: updatedAt,
|
||||
profileImagePath: profileImagePath.isEmpty ? null : profileImagePath,
|
||||
avatarColor: avatarColor,
|
||||
memoryEnabled: memoryEnabled,
|
||||
inTimeline: inTimeline,
|
||||
isPartnerSharedBy: isPartnerSharedBy,
|
||||
isPartnerSharedWith: isPartnerSharedWith,
|
||||
hasProfileImage: profileImagePath.isNotEmpty,
|
||||
profileChangedAt: updatedAt,
|
||||
quotaUsageInBytes: quotaUsageInBytes,
|
||||
quotaSizeInBytes: quotaSizeInBytes,
|
||||
);
|
||||
|
|
@ -82,11 +81,11 @@ class UserEntity extends Table with DriftDefaultsMixin {
|
|||
TextColumn get name => text()();
|
||||
BoolColumn get isAdmin => boolean().withDefault(const Constant(false))();
|
||||
TextColumn get email => text()();
|
||||
TextColumn get profileImagePath => text().nullable()();
|
||||
|
||||
BoolColumn get hasProfileImage => boolean().withDefault(const Constant(false))();
|
||||
DateTimeColumn get profileChangedAt => dateTime().withDefault(currentDateAndTime)();
|
||||
|
||||
DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)();
|
||||
// Quota
|
||||
IntColumn get quotaSizeInBytes => integer().nullable()();
|
||||
IntColumn get quotaUsageInBytes => integer().withDefault(const Constant(0))();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -66,7 +66,7 @@ class Drift extends $Drift implements IDatabaseRepository {
|
|||
: super(executor ?? driftDatabase(name: 'immich', native: const DriftNativeOptions(shareAcrossIsolates: true)));
|
||||
|
||||
@override
|
||||
int get schemaVersion => 4;
|
||||
int get schemaVersion => 5;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
|
|
@ -94,6 +94,15 @@ class Drift extends $Drift implements IDatabaseRepository {
|
|||
// asset_face_entity is added
|
||||
await m.create(v4.assetFaceEntity);
|
||||
},
|
||||
from4To5: (m, v5) async {
|
||||
await m.alterTable(
|
||||
TableMigration(
|
||||
v5.userEntity,
|
||||
newColumns: [v5.userEntity.hasProfileImage, v5.userEntity.profileChangedAt],
|
||||
columnTransformer: {v5.userEntity.profileChangedAt: currentDateAndTime},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -173,15 +173,14 @@ class DriftRemoteAlbumRepository extends DriftDatabaseRepository {
|
|||
id: user.id,
|
||||
email: user.email,
|
||||
name: user.name,
|
||||
profileImagePath: user.profileImagePath?.isEmpty == true ? null : user.profileImagePath,
|
||||
isAdmin: user.isAdmin,
|
||||
updatedAt: user.updatedAt,
|
||||
quotaSizeInBytes: user.quotaSizeInBytes ?? 0,
|
||||
quotaUsageInBytes: user.quotaUsageInBytes,
|
||||
memoryEnabled: true,
|
||||
inTimeline: false,
|
||||
isPartnerSharedBy: false,
|
||||
isPartnerSharedWith: false,
|
||||
profileChangedAt: user.profileChangedAt,
|
||||
hasProfileImage: user.hasProfileImage,
|
||||
),
|
||||
)
|
||||
.get();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,12 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
|||
try {
|
||||
await _db.batch((batch) {
|
||||
for (final user in data) {
|
||||
final companion = UserEntityCompanion(name: Value(user.name), email: Value(user.email));
|
||||
final companion = UserEntityCompanion(
|
||||
name: Value(user.name),
|
||||
email: Value(user.email),
|
||||
hasProfileImage: Value(user.hasProfileImage),
|
||||
profileChangedAt: Value(user.profileChangedAt),
|
||||
);
|
||||
|
||||
batch.insert(_db.userEntity, companion.copyWith(id: Value(user.id)), onConflict: DoUpdate((_) => companion));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ abstract final class UserConverter {
|
|||
name: dto.name,
|
||||
isAdmin: false,
|
||||
updatedAt: DateTime.now(),
|
||||
profileImagePath: dto.profileImagePath,
|
||||
hasProfileImage: dto.profileImagePath.isNotEmpty,
|
||||
profileChangedAt: dto.profileChangedAt,
|
||||
avatarColor: dto.avatarColor.toAvatarColor(),
|
||||
);
|
||||
|
||||
|
|
@ -21,14 +22,13 @@ abstract final class UserConverter {
|
|||
name: adminDto.name,
|
||||
isAdmin: adminDto.isAdmin,
|
||||
updatedAt: adminDto.updatedAt,
|
||||
profileImagePath: adminDto.profileImagePath,
|
||||
avatarColor: adminDto.avatarColor.toAvatarColor(),
|
||||
memoryEnabled: preferenceDto?.memories.enabled ?? true,
|
||||
inTimeline: false,
|
||||
isPartnerSharedBy: false,
|
||||
isPartnerSharedWith: false,
|
||||
quotaUsageInBytes: adminDto.quotaUsageInBytes ?? 0,
|
||||
quotaSizeInBytes: adminDto.quotaSizeInBytes ?? 0,
|
||||
profileChangedAt: adminDto.profileChangedAt,
|
||||
hasProfileImage: adminDto.profileImagePath.isNotEmpty,
|
||||
);
|
||||
|
||||
static UserDto fromPartnerDto(PartnerResponseDto dto) => UserDto(
|
||||
|
|
@ -37,14 +37,13 @@ abstract final class UserConverter {
|
|||
name: dto.name,
|
||||
isAdmin: false,
|
||||
updatedAt: DateTime.now(),
|
||||
profileImagePath: dto.profileImagePath,
|
||||
avatarColor: dto.avatarColor.toAvatarColor(),
|
||||
memoryEnabled: false,
|
||||
inTimeline: dto.inTimeline ?? false,
|
||||
isPartnerSharedBy: false,
|
||||
isPartnerSharedWith: false,
|
||||
quotaUsageInBytes: 0,
|
||||
quotaSizeInBytes: 0,
|
||||
profileChangedAt: dto.profileChangedAt,
|
||||
hasProfileImage: dto.profileImagePath.isNotEmpty,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,15 +27,14 @@ final driftUsersProvider = FutureProvider.autoDispose<List<UserDto>>((ref) async
|
|||
name: entity.name,
|
||||
email: entity.email,
|
||||
isAdmin: entity.isAdmin,
|
||||
profileImagePath: entity.profileImagePath,
|
||||
updatedAt: entity.updatedAt,
|
||||
quotaSizeInBytes: entity.quotaSizeInBytes ?? 0,
|
||||
quotaUsageInBytes: entity.quotaUsageInBytes,
|
||||
isPartnerSharedBy: false,
|
||||
isPartnerSharedWith: false,
|
||||
avatarColor: AvatarColor.primary,
|
||||
memoryEnabled: true,
|
||||
inTimeline: true,
|
||||
profileChangedAt: entity.profileChangedAt,
|
||||
hasProfileImage: entity.hasProfileImage,
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
|
|
|||
|
|
@ -167,7 +167,6 @@ class AuthNotifier extends StateNotifier<AuthState> {
|
|||
isAuthenticated: true,
|
||||
name: user.name,
|
||||
isAdmin: user.isAdmin,
|
||||
profileImagePath: user.profileImagePath,
|
||||
);
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ dynamic upgradeDto(dynamic value, String targetType) {
|
|||
addDefault(value, 'isOnboarded', false);
|
||||
}
|
||||
break;
|
||||
case 'SyncUserV1':
|
||||
if (value is Map) {
|
||||
addDefault(value, 'profileChangedAt', DateTime.now().toIso8601String());
|
||||
addDefault(value, 'hasProfileImage', false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class UserCircleAvatar extends ConsumerWidget {
|
|||
),
|
||||
child: Text(user.name[0].toUpperCase()),
|
||||
);
|
||||
|
||||
return Tooltip(
|
||||
message: user.name,
|
||||
child: Container(
|
||||
|
|
@ -42,13 +43,12 @@ class UserCircleAvatar extends ConsumerWidget {
|
|||
child: CircleAvatar(
|
||||
backgroundColor: userAvatarColor,
|
||||
radius: radius,
|
||||
child: user.profileImagePath == null
|
||||
? textIcon
|
||||
: ClipRRect(
|
||||
child: user.hasProfileImage
|
||||
? ClipRRect(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(50)),
|
||||
child: CachedNetworkImage(
|
||||
fit: BoxFit.cover,
|
||||
cacheKey: user.profileImagePath,
|
||||
cacheKey: user.profileChangedAt.toIso8601String(),
|
||||
width: size,
|
||||
height: size,
|
||||
placeholder: (_, __) => Image.memory(kTransparentImage),
|
||||
|
|
@ -57,7 +57,8 @@ class UserCircleAvatar extends ConsumerWidget {
|
|||
fadeInDuration: const Duration(milliseconds: 300),
|
||||
errorWidget: (context, error, stackTrace) => textIcon,
|
||||
),
|
||||
),
|
||||
)
|
||||
: textIcon,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
BIN
mobile/openapi/lib/model/sync_user_v1.dart
generated
BIN
mobile/openapi/lib/model/sync_user_v1.dart
generated
Binary file not shown.
|
|
@ -98,7 +98,7 @@ void main() {
|
|||
group('createProfileImage', () {
|
||||
test('should return profile image path', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin.copyWith(profileImagePath: profileImagePath);
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
|
|
@ -115,7 +115,7 @@ void main() {
|
|||
|
||||
test('should return null if profile image creation fails', () async {
|
||||
const profileImagePath = 'profile.jpg';
|
||||
final updatedUser = UserStub.admin.copyWith(profileImagePath: profileImagePath);
|
||||
final updatedUser = UserStub.admin;
|
||||
|
||||
when(
|
||||
() => mockUserApiRepo.createProfileImage(name: profileImagePath, data: Uint8List(0)),
|
||||
|
|
|
|||
BIN
mobile/test/drift/main/generated/schema.dart
generated
BIN
mobile/test/drift/main/generated/schema.dart
generated
Binary file not shown.
BIN
mobile/test/drift/main/generated/schema_v5.dart
generated
Normal file
BIN
mobile/test/drift/main/generated/schema_v5.dart
generated
Normal file
Binary file not shown.
20
mobile/test/fixtures/sync_stream.stub.dart
vendored
20
mobile/test/fixtures/sync_stream.stub.dart
vendored
|
|
@ -4,12 +4,28 @@ import 'package:openapi/api.dart';
|
|||
abstract final class SyncStreamStub {
|
||||
static final userV1Admin = SyncEvent(
|
||||
type: SyncEntityType.userV1,
|
||||
data: SyncUserV1(deletedAt: DateTime(2020), email: "admin@admin", id: "1", name: "Admin", avatarColor: null),
|
||||
data: SyncUserV1(
|
||||
deletedAt: DateTime(2020),
|
||||
email: "admin@admin",
|
||||
id: "1",
|
||||
name: "Admin",
|
||||
avatarColor: null,
|
||||
hasProfileImage: false,
|
||||
profileChangedAt: DateTime(2025),
|
||||
),
|
||||
ack: "1",
|
||||
);
|
||||
static final userV1User = SyncEvent(
|
||||
type: SyncEntityType.userV1,
|
||||
data: SyncUserV1(deletedAt: DateTime(2021), email: "user@user", id: "5", name: "User", avatarColor: null),
|
||||
data: SyncUserV1(
|
||||
deletedAt: DateTime(2021),
|
||||
email: "user@user",
|
||||
id: "5",
|
||||
name: "User",
|
||||
avatarColor: null,
|
||||
hasProfileImage: false,
|
||||
profileChangedAt: DateTime(2025),
|
||||
),
|
||||
ack: "5",
|
||||
);
|
||||
static final userDeleteV1 = SyncEvent(
|
||||
|
|
|
|||
6
mobile/test/fixtures/user.stub.dart
vendored
6
mobile/test/fixtures/user.stub.dart
vendored
|
|
@ -10,7 +10,7 @@ abstract final class UserStub {
|
|||
name: "admin",
|
||||
isAdmin: true,
|
||||
updatedAt: DateTime(2021),
|
||||
profileImagePath: null,
|
||||
profileChangedAt: DateTime(2021),
|
||||
avatarColor: AvatarColor.green,
|
||||
);
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ abstract final class UserStub {
|
|||
name: "user1",
|
||||
isAdmin: false,
|
||||
updatedAt: DateTime(2022),
|
||||
profileImagePath: null,
|
||||
profileChangedAt: DateTime(2022),
|
||||
avatarColor: AvatarColor.red,
|
||||
);
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ abstract final class UserStub {
|
|||
name: "user2",
|
||||
isAdmin: false,
|
||||
updatedAt: DateTime(2023),
|
||||
profileImagePath: null,
|
||||
profileChangedAt: DateTime(2023),
|
||||
avatarColor: AvatarColor.primary,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,14 @@ void main() {
|
|||
final MockPartnerRepository partnerRepository = MockPartnerRepository();
|
||||
final MockUserService userService = MockUserService();
|
||||
|
||||
final owner = UserDto(id: "1", updatedAt: DateTime.now(), email: "a@b.c", name: "first last", isAdmin: false);
|
||||
final owner = UserDto(
|
||||
id: "1",
|
||||
updatedAt: DateTime.now(),
|
||||
email: "a@b.c",
|
||||
name: "first last",
|
||||
isAdmin: false,
|
||||
profileChangedAt: DateTime(2021),
|
||||
);
|
||||
late SyncService s;
|
||||
setUpAll(() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
|
|
|
|||
|
|
@ -15124,19 +15124,28 @@
|
|||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"hasProfileImage": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"profileChangedAt": {
|
||||
"format": "date-time",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"avatarColor",
|
||||
"deletedAt",
|
||||
"email",
|
||||
"hasProfileImage",
|
||||
"id",
|
||||
"name"
|
||||
"name",
|
||||
"profileChangedAt"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -357,7 +357,7 @@ export const columns = {
|
|||
],
|
||||
syncAlbumUser: ['album_user.albumsId as albumId', 'album_user.usersId as userId', 'album_user.role'],
|
||||
syncStack: ['stack.id', 'stack.createdAt', 'stack.updatedAt', 'stack.primaryAssetId', 'stack.ownerId'],
|
||||
syncUser: ['id', 'name', 'email', 'avatarColor', 'deletedAt', 'updateId'],
|
||||
syncUser: ['id', 'name', 'email', 'avatarColor', 'deletedAt', 'updateId', 'profileImagePath', 'profileChangedAt'],
|
||||
stack: ['stack.id', 'stack.primaryAssetId', 'ownerId'],
|
||||
syncAssetExif: [
|
||||
'asset_exif.assetId',
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ export class SyncUserV1 {
|
|||
@ValidateEnum({ enum: UserAvatarColor, name: 'UserAvatarColor', nullable: true })
|
||||
avatarColor!: UserAvatarColor | null;
|
||||
deletedAt!: Date | null;
|
||||
hasProfileImage!: boolean;
|
||||
profileChangedAt!: Date;
|
||||
}
|
||||
|
||||
@ExtraModel()
|
||||
|
|
@ -74,8 +76,6 @@ export class SyncAuthUserV1 extends SyncUserV1 {
|
|||
quotaSizeInBytes!: number | null;
|
||||
@ApiProperty({ type: 'integer' })
|
||||
quotaUsageInBytes!: number;
|
||||
hasProfileImage!: boolean;
|
||||
profileChangedAt!: Date;
|
||||
}
|
||||
|
||||
@ExtraModel()
|
||||
|
|
|
|||
|
|
@ -452,14 +452,14 @@ select
|
|||
"avatarColor",
|
||||
"deletedAt",
|
||||
"updateId",
|
||||
"profileImagePath",
|
||||
"profileChangedAt",
|
||||
"isAdmin",
|
||||
"pinCode",
|
||||
"oauthId",
|
||||
"storageLabel",
|
||||
"quotaSizeInBytes",
|
||||
"quotaUsageInBytes",
|
||||
"profileImagePath",
|
||||
"profileChangedAt"
|
||||
"quotaUsageInBytes"
|
||||
from
|
||||
"user"
|
||||
where
|
||||
|
|
@ -896,7 +896,9 @@ select
|
|||
"email",
|
||||
"avatarColor",
|
||||
"deletedAt",
|
||||
"updateId"
|
||||
"updateId",
|
||||
"profileImagePath",
|
||||
"profileChangedAt"
|
||||
from
|
||||
"user"
|
||||
where
|
||||
|
|
|
|||
|
|
@ -375,16 +375,7 @@ class AuthUserSync extends BaseSync {
|
|||
return this.db
|
||||
.selectFrom('user')
|
||||
.select(columns.syncUser)
|
||||
.select([
|
||||
'isAdmin',
|
||||
'pinCode',
|
||||
'oauthId',
|
||||
'storageLabel',
|
||||
'quotaSizeInBytes',
|
||||
'quotaUsageInBytes',
|
||||
'profileImagePath',
|
||||
'profileChangedAt',
|
||||
])
|
||||
.select(['isAdmin', 'pinCode', 'oauthId', 'storageLabel', 'quotaSizeInBytes', 'quotaUsageInBytes'])
|
||||
.$call(this.upsertTableFilters(ack))
|
||||
.stream();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await sql`DELETE FROM session_sync_checkpoint
|
||||
WHERE type IN (
|
||||
'UserV1',
|
||||
'AssetV1',
|
||||
'PartnerAssetV1',
|
||||
'PartnerAssetBackfillV1',
|
||||
'AlbumAssetV1',
|
||||
'AlbumAssetBackfillV1'
|
||||
)`.execute(db);
|
||||
}
|
||||
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await sql`DELETE FROM session_sync_checkpoint
|
||||
WHERE type IN (
|
||||
'UserV1',
|
||||
'AssetV1',
|
||||
'PartnerAssetV1',
|
||||
'PartnerAssetBackfillV1',
|
||||
'AlbumAssetV1',
|
||||
'AlbumAssetBackfillV1'
|
||||
)`.execute(db);
|
||||
}
|
||||
|
|
@ -188,8 +188,8 @@ export class SyncService extends BaseService {
|
|||
|
||||
const upsertType = SyncEntityType.UserV1;
|
||||
const upserts = this.syncRepository.user.getUpserts(checkpointMap[upsertType]);
|
||||
for await (const { updateId, ...data } of upserts) {
|
||||
send(response, { type: upsertType, ids: [updateId], data });
|
||||
for await (const { updateId, profileImagePath, ...data } of upserts) {
|
||||
send(response, { type: upsertType, ids: [updateId], data: { ...data, hasProfileImage: !!profileImagePath } });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,11 @@ describe(SyncEntityType.UserV1, () => {
|
|||
data: {
|
||||
deletedAt: user.deletedAt,
|
||||
email: user.email,
|
||||
hasProfileImage: user.profileImagePath !== '',
|
||||
id: user.id,
|
||||
name: user.name,
|
||||
avatarColor: user.avatarColor,
|
||||
profileChangedAt: user.profileChangedAt.toISOString(),
|
||||
},
|
||||
type: 'UserV1',
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user