mirror of
https://github.com/immich-app/immich.git
synced 2026-01-29 00:04:52 -08:00
Compare commits
2 Commits
fix/flippe
...
fix-migrat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99a8740f1b | ||
|
|
a781c78caf |
@@ -98,7 +98,12 @@ class AssetService {
|
||||
height = fetched?.height?.toDouble();
|
||||
}
|
||||
|
||||
return (width: width, height: height, isFlipped: false);
|
||||
// Check exif for orientation to determine if dimensions should be flipped
|
||||
// This is important for videos where raw file dimensions may not match display dimensions
|
||||
final exif = await _remoteAssetRepository.getExif(asset.id);
|
||||
final isFlipped = exif?.isFlipped ?? false;
|
||||
|
||||
return (width: width, height: height, isFlipped: isFlipped);
|
||||
}
|
||||
|
||||
Future<List<(String, String)>> getPlaces(String userId) {
|
||||
|
||||
@@ -36,9 +36,6 @@ class SyncApiRepository {
|
||||
headers.addAll(headerParams);
|
||||
|
||||
final shouldReset = Store.get(StoreKey.shouldResetSync, false);
|
||||
if (shouldReset) {
|
||||
_logger.info("Resetting sync state by client");
|
||||
}
|
||||
final request = http.Request('POST', Uri.parse(endpoint));
|
||||
request.headers.addAll(headers);
|
||||
request.body = jsonEncode(
|
||||
|
||||
@@ -268,7 +268,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||
batch.update(
|
||||
_db.remoteAssetEntity,
|
||||
RemoteAssetEntityCompanion(width: Value(width), height: Value(height)),
|
||||
where: (row) => row.id.equals(exif.assetId) & row.isEdited.equals(false),
|
||||
where: (row) => row.id.equals(exif.assetId) & row.width.isNull() & row.height.isNull(),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ import 'package:isar/isar.dart';
|
||||
// ignore: import_rule_photo_manager
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
|
||||
const int targetVersion = 21;
|
||||
const int targetVersion = 20;
|
||||
|
||||
Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
|
||||
final hasVersion = Store.tryGet(StoreKey.version) != null;
|
||||
@@ -88,10 +88,7 @@ Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
|
||||
|
||||
if (version < 20 && Store.isBetaTimelineEnabled) {
|
||||
await _syncLocalAlbumIsIosSharedAlbum(drift);
|
||||
}
|
||||
|
||||
if (version < 21) {
|
||||
await Store.put(StoreKey.shouldResetSync, true);
|
||||
await _backfillAssetExifWidthHeight(drift);
|
||||
}
|
||||
|
||||
if (targetVersion >= 12) {
|
||||
@@ -285,6 +282,26 @@ Future<void> _syncLocalAlbumIsIosSharedAlbum(Drift db) async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _backfillAssetExifWidthHeight(Drift db) async {
|
||||
try {
|
||||
// Only backfill images (type = 1), not videos
|
||||
// Videos have different dimension handling based on orientation/exif
|
||||
await db.customStatement('''
|
||||
UPDATE remote_exif_entity AS remote_exif
|
||||
SET width = asset.width,
|
||||
height = asset.height
|
||||
FROM remote_asset_entity AS asset
|
||||
WHERE remote_exif.asset_id = asset.id
|
||||
AND asset.type = 1
|
||||
AND (remote_exif.width IS NULL OR remote_exif.width = 0 OR remote_exif.height IS NULL OR remote_exif.height = 0);
|
||||
''');
|
||||
|
||||
dPrint(() => "[MIGRATION] Successfully backfilled asset exif width and height");
|
||||
} catch (error) {
|
||||
dPrint(() => "[MIGRATION] Error while backfilling asset exif width and height: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> migrateDeviceAssetToSqlite(Isar db, Drift drift) async {
|
||||
try {
|
||||
final isarDeviceAssets = await db.deviceAssetEntitys.where().findAll();
|
||||
|
||||
@@ -24,7 +24,6 @@ SyncAssetV1 _createAsset({
|
||||
String ownerId = 'user-1',
|
||||
int? width,
|
||||
int? height,
|
||||
bool isEdited = false,
|
||||
}) {
|
||||
return SyncAssetV1(
|
||||
id: id,
|
||||
@@ -45,7 +44,7 @@ SyncAssetV1 _createAsset({
|
||||
livePhotoVideoId: null,
|
||||
stackId: null,
|
||||
thumbhash: null,
|
||||
isEdited: isEdited,
|
||||
isEdited: false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -155,7 +154,7 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test('does not update dimensions if asset is edited', () async {
|
||||
test('does not update dimensions if asset already has width and height', () async {
|
||||
const assetId = 'asset-with-dimensions';
|
||||
const existingWidth = 1920;
|
||||
const existingHeight = 1080;
|
||||
@@ -170,7 +169,6 @@ void main() {
|
||||
fileName: 'with_dimensions.jpg',
|
||||
width: existingWidth,
|
||||
height: existingHeight,
|
||||
isEdited: true,
|
||||
);
|
||||
await sut.updateAssetsV1([asset]);
|
||||
|
||||
|
||||
@@ -118,7 +118,13 @@ abstract final class TestUtils {
|
||||
return result;
|
||||
}
|
||||
|
||||
static domain.RemoteAsset createRemoteAsset({required String id, int? width, int? height, String? ownerId}) {
|
||||
static domain.RemoteAsset createRemoteAsset({
|
||||
required String id,
|
||||
int? width,
|
||||
int? height,
|
||||
String? ownerId,
|
||||
String? localId,
|
||||
}) {
|
||||
return domain.RemoteAsset(
|
||||
id: id,
|
||||
checksum: 'checksum1',
|
||||
@@ -132,6 +138,7 @@ abstract final class TestUtils {
|
||||
width: width,
|
||||
height: height,
|
||||
isEdited: false,
|
||||
localId: localId,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await sql`UPDATE "session" SET "isPendingSyncReset" = false`.execute(db);
|
||||
await sql`TRUNCATE TABLE "session_sync_checkpoint"`.execute(db);
|
||||
}
|
||||
|
||||
export async function down(): Promise<void> {}
|
||||
Reference in New Issue
Block a user