mirror of
https://github.com/immich-app/immich.git
synced 2025-12-17 09:13:17 +03:00
more fixes
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/extensions/num_extensions.dart';
|
||||
|
||||
part 'local_asset.model.dart';
|
||||
part 'remote_asset.model.dart';
|
||||
|
||||
@@ -42,8 +42,13 @@ class LocalAsset extends BaseAsset {
|
||||
@override
|
||||
String get heroTag => '${id}_${remoteId ?? checksum}';
|
||||
|
||||
String get eTag =>
|
||||
"${createdAt.millisecondsSinceEpoch ~/ 1000}$kUploadETagDelimiter${(adjustmentTime?.millisecondsSinceEpoch ?? 0) ~/ 1000}$kUploadETagDelimiter${latitude ?? 0}$kUploadETagDelimiter${longitude ?? 0}";
|
||||
String get eTag {
|
||||
final createdAt = this.createdAt.millisecondsSinceEpoch ~/ 1000;
|
||||
final adjustmentTime = this.adjustmentTime?.millisecondsSinceEpoch ?? 0;
|
||||
final latitude = this.latitude?.truncateTo(2).toStringAsFixed(2) ?? "0.00";
|
||||
final longitude = this.longitude?.truncateTo(2).toStringAsFixed(2) ?? "0.00";
|
||||
return "$createdAt$kUploadETagDelimiter$adjustmentTime$kUploadETagDelimiter$latitude$kUploadETagDelimiter$longitude";
|
||||
}
|
||||
|
||||
bool get hasCoordinates => latitude != null && longitude != null && latitude != 0 && longitude != 0;
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/asset_metadata.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/db.repository.dart';
|
||||
import 'package:immich_mobile/infrastructure/repositories/local_album.repository.dart';
|
||||
import 'package:immich_mobile/platform/native_sync_api.g.dart';
|
||||
@@ -33,12 +34,12 @@ Future<void> syncCloudIds(ProviderContainer ref) async {
|
||||
for (final mapping in mappingsToUpdate) {
|
||||
final mobileMeta = AssetMetadataUpsertItemDto(
|
||||
key: AssetMetadataKey.mobileApp,
|
||||
value: RemoteAssetMobileAppMetadata(cloudId: mapping.cloudId, eTag: mapping.eTag),
|
||||
value: RemoteAssetMobileAppMetadata(cloudId: mapping.localAsset.cloudId, eTag: mapping.localAsset.eTag),
|
||||
);
|
||||
try {
|
||||
await assetApi.updateAssetMetadata(mapping.assetId, AssetMetadataUpsertDto(items: [mobileMeta]));
|
||||
await assetApi.updateAssetMetadata(mapping.remoteAssetId, AssetMetadataUpsertDto(items: [mobileMeta]));
|
||||
} catch (error, stack) {
|
||||
Logger('migrateCloudIds').warning('Failed to update metadata for asset ${mapping.assetId}', error, stack);
|
||||
Logger('migrateCloudIds').warning('Failed to update metadata for asset ${mapping.remoteAssetId}', error, stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,47 +53,30 @@ Future<void> _populateCloudIds(Drift drift) async {
|
||||
await DriftLocalAlbumRepository(drift).updateCloudMapping(cloudMapping);
|
||||
}
|
||||
|
||||
typedef _CloudIdMapping = ({String assetId, String cloudId, String eTag});
|
||||
typedef _CloudIdMapping = ({String remoteAssetId, LocalAsset localAsset});
|
||||
|
||||
Future<List<_CloudIdMapping>> _fetchCloudIdMappings(Drift drift, String userId) async {
|
||||
final query =
|
||||
drift.remoteAssetEntity.selectOnly().join([
|
||||
drift.remoteAssetEntity.select().join([
|
||||
leftOuterJoin(
|
||||
drift.localAssetEntity,
|
||||
drift.localAssetEntity.checksum.equalsExp(drift.remoteAssetEntity.checksum),
|
||||
useColumns: false,
|
||||
),
|
||||
leftOuterJoin(
|
||||
drift.remoteAssetCloudIdEntity,
|
||||
drift.localAssetEntity.iCloudId.equalsExp(drift.remoteAssetCloudIdEntity.cloudId),
|
||||
useColumns: false,
|
||||
),
|
||||
])
|
||||
..addColumns([
|
||||
drift.remoteAssetEntity.id,
|
||||
drift.localAssetEntity.iCloudId,
|
||||
drift.localAssetEntity.createdAt,
|
||||
drift.localAssetEntity.adjustmentTime,
|
||||
drift.localAssetEntity.latitude,
|
||||
drift.localAssetEntity.longitude,
|
||||
])
|
||||
..where(
|
||||
])..where(
|
||||
drift.localAssetEntity.id.isNotNull() &
|
||||
drift.localAssetEntity.iCloudId.isNotNull() &
|
||||
drift.remoteAssetEntity.ownerId.equals(userId) &
|
||||
drift.remoteAssetCloudIdEntity.cloudId.isNull(),
|
||||
);
|
||||
return query.map((row) {
|
||||
final createdAt = row.read(drift.localAssetEntity.createdAt)!;
|
||||
final adjustmentTime = row.read(drift.localAssetEntity.adjustmentTime);
|
||||
final latitude = row.read(drift.localAssetEntity.latitude);
|
||||
final longitude = row.read(drift.localAssetEntity.longitude);
|
||||
final eTag =
|
||||
"${createdAt.millisecondsSinceEpoch ~/ 1000}$kUploadETagDelimiter${(adjustmentTime?.millisecondsSinceEpoch ?? 0) ~/ 1000}$kUploadETagDelimiter${latitude ?? 0}$kUploadETagDelimiter${longitude ?? 0}";
|
||||
return (
|
||||
assetId: row.read(drift.remoteAssetEntity.id)!,
|
||||
cloudId: row.read(drift.localAssetEntity.iCloudId)!,
|
||||
eTag: eTag,
|
||||
remoteAssetId: row.read(drift.remoteAssetEntity.id)!,
|
||||
localAsset: row.readTable(drift.localAssetEntity).toDto(),
|
||||
);
|
||||
}).get();
|
||||
}
|
||||
|
||||
17
mobile/lib/extensions/drift_extensions.dart
Normal file
17
mobile/lib/extensions/drift_extensions.dart
Normal file
@@ -0,0 +1,17 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
// ignore: invalid_use_of_internal_member, implementation_imports
|
||||
import 'package:drift/src/runtime/query_builder/expressions/internal.dart';
|
||||
|
||||
extension DoubleTruncateExpression<T extends num> on Expression<T> {
|
||||
Expression<T> truncateTo(int fractionDigits) {
|
||||
final mod = Constant(pow(10, fractionDigits).toDouble());
|
||||
return BaseInfixOperator(
|
||||
BaseInfixOperator(this, '*', mod, precedence: Precedence.mulDivide).cast(DriftSqlType.int),
|
||||
'/',
|
||||
mod,
|
||||
precedence: Precedence.mulDivide,
|
||||
);
|
||||
}
|
||||
}
|
||||
8
mobile/lib/extensions/num_extensions.dart
Normal file
8
mobile/lib/extensions/num_extensions.dart
Normal file
@@ -0,0 +1,8 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
extension DoubleTruncate on double {
|
||||
double truncateTo(int fractionDigits) {
|
||||
final mod = math.pow(10.0, fractionDigits);
|
||||
return ((this * mod).truncate() / mod);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,10 @@ SELECT
|
||||
rae.live_photo_video_id,
|
||||
0 as orientation,
|
||||
rae.stack_id,
|
||||
NULL as i_cloud_id
|
||||
NULL as i_cloud_id,
|
||||
NULL as latitude,
|
||||
NULL as longitude,
|
||||
NULL as adjustmentTime
|
||||
FROM
|
||||
remote_asset_entity rae
|
||||
LEFT JOIN
|
||||
@@ -55,7 +58,10 @@ SELECT
|
||||
NULL as live_photo_video_id,
|
||||
lae.orientation,
|
||||
NULL as stack_id,
|
||||
lae.i_cloud_id
|
||||
lae.i_cloud_id,
|
||||
lae.latitude,
|
||||
lae.longitude,
|
||||
lae.adjustment_time
|
||||
FROM
|
||||
local_asset_entity lae
|
||||
WHERE NOT EXISTS (
|
||||
|
||||
@@ -29,7 +29,7 @@ class MergedAssetDrift extends i1.ModularAccessor {
|
||||
);
|
||||
$arrayStartIndex += generatedlimit.amountOfVariables;
|
||||
return customSelect(
|
||||
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_in_seconds, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_in_seconds, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
|
||||
'SELECT rae.id AS remote_id, (SELECT lae.id FROM local_asset_entity AS lae WHERE lae.checksum = rae.checksum LIMIT 1) AS local_id, rae.name, rae.type, rae.created_at AS created_at, rae.updated_at, rae.width, rae.height, rae.duration_in_seconds, rae.is_favorite, rae.thumb_hash, rae.checksum, rae.owner_id, rae.live_photo_video_id, 0 AS orientation, rae.stack_id, NULL AS i_cloud_id, NULL AS latitude, NULL AS longitude, NULL AS adjustmentTime FROM remote_asset_entity AS rae LEFT JOIN stack_entity AS se ON rae.stack_id = se.id WHERE rae.deleted_at IS NULL AND rae.visibility = 0 AND rae.owner_id IN ($expandeduserIds) AND(rae.stack_id IS NULL OR rae.id = se.primary_asset_id)UNION ALL SELECT NULL AS remote_id, lae.id AS local_id, lae.name, lae.type, lae.created_at AS created_at, lae.updated_at, lae.width, lae.height, lae.duration_in_seconds, lae.is_favorite, NULL AS thumb_hash, lae.checksum, NULL AS owner_id, NULL AS live_photo_video_id, lae.orientation, NULL AS stack_id, lae.i_cloud_id, lae.latitude, lae.longitude, lae.adjustment_time FROM local_asset_entity AS lae WHERE NOT EXISTS (SELECT 1 FROM remote_asset_entity AS rae WHERE rae.checksum = lae.checksum AND rae.owner_id IN ($expandeduserIds)) AND EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 0) AND NOT EXISTS (SELECT 1 FROM local_album_asset_entity AS laa INNER JOIN local_album_entity AS la ON laa.album_id = la.id WHERE laa.asset_id = lae.id AND la.backup_selection = 2) ORDER BY created_at DESC ${generatedlimit.sql}',
|
||||
variables: [
|
||||
for (var $ in userIds) i0.Variable<String>($),
|
||||
...generatedlimit.introducedVariables,
|
||||
@@ -63,6 +63,9 @@ class MergedAssetDrift extends i1.ModularAccessor {
|
||||
orientation: row.read<int>('orientation'),
|
||||
stackId: row.readNullable<String>('stack_id'),
|
||||
iCloudId: row.readNullable<String>('i_cloud_id'),
|
||||
latitude: row.readNullable<double>('latitude'),
|
||||
longitude: row.readNullable<double>('longitude'),
|
||||
adjustmentTime: row.readNullable<DateTime>('adjustmentTime'),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -131,6 +134,9 @@ class MergedAssetResult {
|
||||
final int orientation;
|
||||
final String? stackId;
|
||||
final String? iCloudId;
|
||||
final double? latitude;
|
||||
final double? longitude;
|
||||
final DateTime? adjustmentTime;
|
||||
MergedAssetResult({
|
||||
this.remoteId,
|
||||
this.localId,
|
||||
@@ -149,6 +155,9 @@ class MergedAssetResult {
|
||||
required this.orientation,
|
||||
this.stackId,
|
||||
this.iCloudId,
|
||||
this.latitude,
|
||||
this.longitude,
|
||||
this.adjustmentTime,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:immich_mobile/constants/constants.dart';
|
||||
import 'package:immich_mobile/domain/models/album/local_album.model.dart';
|
||||
import 'package:immich_mobile/domain/models/asset/base_asset.model.dart';
|
||||
import 'package:immich_mobile/extensions/drift_extensions.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart';
|
||||
import 'package:immich_mobile/infrastructure/entities/local_asset.entity.drift.dart';
|
||||
@@ -133,10 +136,17 @@ class DriftLocalAssetRepository extends DriftDatabaseRepository {
|
||||
}
|
||||
|
||||
Future<Map<String, String>> getHashMappingFromCloudId() async {
|
||||
final createdAt = coalesce([_db.localAssetEntity.createdAt.strftime('%s'), const Constant('0')]);
|
||||
final createdAt = _db.localAssetEntity.createdAt.strftime('%s');
|
||||
final adjustmentTime = coalesce([_db.localAssetEntity.adjustmentTime.strftime('%s'), const Constant('0')]);
|
||||
final latitude = coalesce([_db.localAssetEntity.latitude.cast(DriftSqlType.string), const Constant('0')]);
|
||||
final longitude = coalesce([_db.localAssetEntity.longitude.cast(DriftSqlType.string), const Constant('0')]);
|
||||
final latitude = coalesce([
|
||||
_db.localAssetEntity.latitude,
|
||||
const Constant(0.0),
|
||||
]).truncateTo(2).cast(DriftSqlType.string);
|
||||
final longitude = coalesce([
|
||||
_db.localAssetEntity.longitude,
|
||||
const Constant(0.0),
|
||||
]).truncateTo(2).cast(DriftSqlType.string);
|
||||
|
||||
final delimiter = const Constant(kUploadETagDelimiter);
|
||||
final eTag = createdAt + delimiter + adjustmentTime + delimiter + latitude + delimiter + longitude;
|
||||
|
||||
|
||||
@@ -85,6 +85,9 @@ class DriftTimelineRepository extends DriftDatabaseRepository {
|
||||
durationInSeconds: row.durationInSeconds,
|
||||
orientation: row.orientation,
|
||||
cloudId: row.iCloudId,
|
||||
latitude: row.latitude,
|
||||
longitude: row.longitude,
|
||||
adjustmentTime: row.adjustmentTime,
|
||||
),
|
||||
)
|
||||
.get();
|
||||
|
||||
Reference in New Issue
Block a user