Compare commits

..

2 Commits

Author SHA1 Message Date
Alex
99a8740f1b only migrate for images 2026-01-27 22:37:12 -06:00
Alex
a781c78caf fix: width and height migration issue 2026-01-27 21:48:19 -06:00
7 changed files with 39 additions and 23 deletions

View File

@@ -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) {

View File

@@ -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(

View File

@@ -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(),
);
}
});

View File

@@ -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();

View File

@@ -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]);

View File

@@ -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,
);
}

View File

@@ -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> {}