fix: sync is_favorite from native (#20412)

* feat: sync is_favorite from native

* handle favorite during upload

* Update mobile/ios/Runner/Sync/MessagesImpl.swift

Co-authored-by: Alex <alex.tran1502@gmail.com>

---------

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
shenlong 2025-07-30 08:27:04 +05:30 committed by GitHub
parent 07ed060c32
commit 268b411a6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 30 additions and 8 deletions

View File

@ -88,7 +88,8 @@ data class PlatformAsset (
val width: Long? = null, val width: Long? = null,
val height: Long? = null, val height: Long? = null,
val durationInSeconds: Long, val durationInSeconds: Long,
val orientation: Long val orientation: Long,
val isFavorite: Boolean
) )
{ {
companion object { companion object {
@ -102,7 +103,8 @@ data class PlatformAsset (
val height = pigeonVar_list[6] as Long? val height = pigeonVar_list[6] as Long?
val durationInSeconds = pigeonVar_list[7] as Long val durationInSeconds = pigeonVar_list[7] as Long
val orientation = pigeonVar_list[8] as Long val orientation = pigeonVar_list[8] as Long
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation) val isFavorite = pigeonVar_list[9] as Boolean
return PlatformAsset(id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite)
} }
} }
fun toList(): List<Any?> { fun toList(): List<Any?> {
@ -116,6 +118,7 @@ data class PlatformAsset (
height, height,
durationInSeconds, durationInSeconds,
orientation, orientation,
isFavorite,
) )
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@ -42,6 +42,7 @@ open class NativeSyncApiImplBase(context: Context) {
MediaStore.MediaColumns.HEIGHT, MediaStore.MediaColumns.HEIGHT,
MediaStore.MediaColumns.DURATION, MediaStore.MediaColumns.DURATION,
MediaStore.MediaColumns.ORIENTATION, MediaStore.MediaColumns.ORIENTATION,
MediaStore.MediaColumns.IS_FAVORITE,
) )
const val HASH_BUFFER_SIZE = 2 * 1024 * 1024 const val HASH_BUFFER_SIZE = 2 * 1024 * 1024
@ -77,6 +78,7 @@ open class NativeSyncApiImplBase(context: Context) {
val durationColumn = c.getColumnIndexOrThrow(MediaStore.MediaColumns.DURATION) val durationColumn = c.getColumnIndexOrThrow(MediaStore.MediaColumns.DURATION)
val orientationColumn = val orientationColumn =
c.getColumnIndexOrThrow(MediaStore.MediaColumns.ORIENTATION) c.getColumnIndexOrThrow(MediaStore.MediaColumns.ORIENTATION)
val favoriteColumn = c.getColumnIndexOrThrow(MediaStore.MediaColumns.IS_FAVORITE)
while (c.moveToNext()) { while (c.moveToNext()) {
val id = c.getLong(idColumn).toString() val id = c.getLong(idColumn).toString()
@ -105,6 +107,7 @@ open class NativeSyncApiImplBase(context: Context) {
else c.getLong(durationColumn) / 1000 else c.getLong(durationColumn) / 1000
val bucketId = c.getString(bucketIdColumn) val bucketId = c.getString(bucketIdColumn)
val orientation = c.getInt(orientationColumn) val orientation = c.getInt(orientationColumn)
val isFavorite = c.getInt(favoriteColumn) != 0;
val asset = PlatformAsset( val asset = PlatformAsset(
id, id,
@ -116,6 +119,7 @@ open class NativeSyncApiImplBase(context: Context) {
height, height,
duration, duration,
orientation.toLong(), orientation.toLong(),
isFavorite,
) )
yield(AssetResult.ValidAsset(asset, bucketId)) yield(AssetResult.ValidAsset(asset, bucketId))
} }

View File

@ -139,6 +139,7 @@ struct PlatformAsset: Hashable {
var height: Int64? = nil var height: Int64? = nil
var durationInSeconds: Int64 var durationInSeconds: Int64
var orientation: Int64 var orientation: Int64
var isFavorite: Bool
// swift-format-ignore: AlwaysUseLowerCamelCase // swift-format-ignore: AlwaysUseLowerCamelCase
@ -152,6 +153,7 @@ struct PlatformAsset: Hashable {
let height: Int64? = nilOrValue(pigeonVar_list[6]) let height: Int64? = nilOrValue(pigeonVar_list[6])
let durationInSeconds = pigeonVar_list[7] as! Int64 let durationInSeconds = pigeonVar_list[7] as! Int64
let orientation = pigeonVar_list[8] as! Int64 let orientation = pigeonVar_list[8] as! Int64
let isFavorite = pigeonVar_list[9] as! Bool
return PlatformAsset( return PlatformAsset(
id: id, id: id,
@ -162,7 +164,8 @@ struct PlatformAsset: Hashable {
width: width, width: width,
height: height, height: height,
durationInSeconds: durationInSeconds, durationInSeconds: durationInSeconds,
orientation: orientation orientation: orientation,
isFavorite: isFavorite
) )
} }
func toList() -> [Any?] { func toList() -> [Any?] {
@ -176,6 +179,7 @@ struct PlatformAsset: Hashable {
height, height,
durationInSeconds, durationInSeconds,
orientation, orientation,
isFavorite,
] ]
} }
static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool { static func == (lhs: PlatformAsset, rhs: PlatformAsset) -> Bool {

View File

@ -28,7 +28,8 @@ extension PHAsset {
width: Int64(pixelWidth), width: Int64(pixelWidth),
height: Int64(pixelHeight), height: Int64(pixelHeight),
durationInSeconds: Int64(duration), durationInSeconds: Int64(duration),
orientation: 0 orientation: 0,
isFavorite: isFavorite
) )
} }
} }

View File

@ -312,6 +312,7 @@ extension on Iterable<PlatformAsset> {
height: e.height, height: e.height,
durationInSeconds: e.durationInSeconds, durationInSeconds: e.durationInSeconds,
orientation: e.orientation, orientation: e.orientation,
isFavorite: e.isFavorite,
), ),
).toList(); ).toList();
} }

View File

@ -236,6 +236,7 @@ class DriftLocalAlbumRepository extends DriftDatabaseRepository {
id: asset.id, id: asset.id,
orientation: Value(asset.orientation), orientation: Value(asset.orientation),
checksum: const Value(null), checksum: const Value(null),
isFavorite: Value(asset.isFavorite),
); );
batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>( batch.insert<$LocalAssetEntityTable, LocalAssetEntityData>(
_db.localAssetEntity, _db.localAssetEntity,

View File

@ -40,6 +40,7 @@ class PlatformAsset {
this.height, this.height,
required this.durationInSeconds, required this.durationInSeconds,
required this.orientation, required this.orientation,
required this.isFavorite,
}); });
String id; String id;
@ -60,8 +61,10 @@ class PlatformAsset {
int orientation; int orientation;
bool isFavorite;
List<Object?> _toList() { List<Object?> _toList() {
return <Object?>[id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation]; return <Object?>[id, name, type, createdAt, updatedAt, width, height, durationInSeconds, orientation, isFavorite];
} }
Object encode() { Object encode() {
@ -80,6 +83,7 @@ class PlatformAsset {
height: result[6] as int?, height: result[6] as int?,
durationInSeconds: result[7]! as int, durationInSeconds: result[7]! as int,
orientation: result[8]! as int, orientation: result[8]! as int,
isFavorite: result[9]! as bool,
); );
} }

View File

@ -247,6 +247,7 @@ class UploadService {
metadata: metadata, metadata: metadata,
group: group, group: group,
priority: priority, priority: priority,
isFavorite: asset.isFavorite,
); );
} }
@ -270,6 +271,7 @@ class UploadService {
fields: fields, fields: fields,
group: kBackupLivePhotoGroup, group: kBackupLivePhotoGroup,
priority: 0, // Highest priority to get upload immediately priority: 0, // Highest priority to get upload immediately
isFavorite: asset.isFavorite,
); );
} }
@ -281,6 +283,7 @@ class UploadService {
String? deviceAssetId, String? deviceAssetId,
String? metadata, String? metadata,
int? priority, int? priority,
bool? isFavorite,
}) async { }) async {
final serverEndpoint = Store.get(StoreKey.serverEndpoint); final serverEndpoint = Store.get(StoreKey.serverEndpoint);
final url = Uri.parse('$serverEndpoint/assets').toString(); final url = Uri.parse('$serverEndpoint/assets').toString();
@ -297,7 +300,7 @@ class UploadService {
'deviceId': deviceId, 'deviceId': deviceId,
'fileCreatedAt': fileCreatedAt.toUtc().toIso8601String(), 'fileCreatedAt': fileCreatedAt.toUtc().toIso8601String(),
'fileModifiedAt': fileModifiedAt.toUtc().toIso8601String(), 'fileModifiedAt': fileModifiedAt.toUtc().toIso8601String(),
'isFavorite': 'false', 'isFavorite': isFavorite?.toString() ?? 'false',
'duration': '0', 'duration': '0',
if (fields != null) ...fields, if (fields != null) ...fields,
}; };

View File

@ -5,8 +5,7 @@ import 'package:pigeon/pigeon.dart';
dartOut: 'lib/platform/native_sync_api.g.dart', dartOut: 'lib/platform/native_sync_api.g.dart',
swiftOut: 'ios/Runner/Sync/Messages.g.swift', swiftOut: 'ios/Runner/Sync/Messages.g.swift',
swiftOptions: SwiftOptions(), swiftOptions: SwiftOptions(),
kotlinOut: kotlinOut: 'android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt',
'android/app/src/main/kotlin/app/alextran/immich/sync/Messages.g.kt',
kotlinOptions: KotlinOptions(package: 'app.alextran.immich.sync'), kotlinOptions: KotlinOptions(package: 'app.alextran.immich.sync'),
dartOptions: DartOptions(), dartOptions: DartOptions(),
dartPackageName: 'immich_mobile', dartPackageName: 'immich_mobile',
@ -24,6 +23,7 @@ class PlatformAsset {
final int? height; final int? height;
final int durationInSeconds; final int durationInSeconds;
final int orientation; final int orientation;
final bool isFavorite;
const PlatformAsset({ const PlatformAsset({
required this.id, required this.id,
@ -35,6 +35,7 @@ class PlatformAsset {
this.height, this.height,
this.durationInSeconds = 0, this.durationInSeconds = 0,
this.orientation = 0, this.orientation = 0,
this.isFavorite = false,
}); });
} }