Compare commits

...

1 Commits

Author SHA1 Message Date
Santo Shakil 215559d86a fix(mobile): show the real date for android local photos with no exif
photos with no exif date showed their copy-to-phone date in the "on this device" albums instead of the real date. fall back to the earlier of date_modified/date_added (matches the server + ios), plus a migration to fix the rows already saved wrong.
2026-06-18 20:48:24 +06:00
2 changed files with 28 additions and 3 deletions
@@ -174,9 +174,10 @@ open class NativeSyncApiImplBase(context: Context) : ImmichPlugin(), ActivityAwa
MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO -> 2L
else -> 0L
}
// Date taken is milliseconds since epoch, Date added is seconds since epoch
// Date taken is in ms; date added/modified in seconds. No-EXIF (date taken <= 0)
// falls back to the earliest of modified/added to match the server + iOS.
val createdAt = (c.getLong(dateTakenColumn).takeIf { it > 0 }?.div(1000))
?: c.getLong(dateAddedColumn)
?: minOf(c.getLong(dateModifiedColumn), c.getLong(dateAddedColumn))
// Date modified is seconds since epoch
val modifiedAt = c.getLong(dateModifiedColumn)
val width = c.getInt(widthColumn).toLong()
+25 -1
View File
@@ -12,13 +12,14 @@ import 'package:immich_mobile/domain/models/settings_key.dart';
import 'package:immich_mobile/domain/models/store.model.dart';
import 'package:immich_mobile/domain/models/timeline.model.dart';
import 'package:immich_mobile/entities/store.entity.dart';
import 'package:immich_mobile/extensions/platform_extensions.dart';
import 'package:immich_mobile/infrastructure/entities/settings.entity.drift.dart';
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
import 'package:immich_mobile/infrastructure/repositories/network.repository.dart';
import 'package:immich_mobile/models/auth/auxilary_endpoint.model.dart';
import 'package:immich_mobile/providers/album/album_sort_by_options.provider.dart';
const int targetVersion = 26;
const int targetVersion = 27;
Future<void> migrateDatabaseIfNeeded(Drift drift) async {
final int version = Store.get(StoreKey.version, targetVersion);
@@ -31,10 +32,33 @@ Future<void> migrateDatabaseIfNeeded(Drift drift) async {
await _migrateTo26(drift);
}
if (version < 27) {
if (!await _migrateTo27(drift)) {
return;
}
}
await Store.put(StoreKey.version, targetVersion);
return;
}
Future<bool> _migrateTo27(Drift drift) async {
// Android-only: no-EXIF photos got a wrong createdAt (DATE_ADDED copy-time instead
// of the real DATE_MODIFIED). Those rows can't self-heal -- the local sync only
// updates an asset when its updatedAt (DATE_MODIFIED) changes, which it never does
// here. A createdAt later than updatedAt is the copy-time signature, so clamp it
// back to updatedAt (the real date, == the new minOf(DATE_MODIFIED, DATE_ADDED)).
if (!CurrentPlatform.isAndroid) {
return true;
}
try {
await drift.customStatement('UPDATE local_asset_entity SET created_at = updated_at WHERE created_at > updated_at');
return true;
} catch (_) {
return false;
}
}
Future<void> _migrateTo25() async {
final accessToken = Store.tryGet(StoreKey.accessToken);
if (accessToken == null || accessToken.isEmpty) {