From 445f9174eaea85c205db5d13e81e43db2879c60a Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 2 Jul 2025 14:18:37 -0500 Subject: [PATCH] feat: memories sync (#19644) * feat: memories sync * Update mobile/lib/infrastructure/repositories/sync_stream.repository.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update mobile/lib/infrastructure/repositories/sync_stream.repository.dart Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * show sync information * tests and pr feedback * pr feedback --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../drift_schemas/main/drift_schema_v1.json | 1332 ++++++++++++++++- mobile/lib/domain/models/memory.model.dart | 202 +++ .../domain/services/sync_stream.service.dart | 8 + .../entities/memory.entity.dart | 36 + .../entities/memory.entity.drift.dart | 970 ++++++++++++ .../entities/memory_asset.entity.dart | 17 + .../entities/memory_asset.entity.drift.dart | 550 +++++++ .../repositories/db.repository.dart | 4 + .../repositories/db.repository.drift.dart | 44 +- .../repositories/memory.repository.dart | 37 + .../repositories/sync_api.repository.dart | 6 + .../repositories/sync_stream.repository.dart | 164 +- .../pages/dev/media_stat.page.dart | 8 + mobile/lib/providers/memory.provider.dart | 6 + .../services/sync_stream_service_test.dart | 97 ++ mobile/test/fixtures/sync_stream.stub.dart | 43 + 16 files changed, 3491 insertions(+), 33 deletions(-) create mode 100644 mobile/lib/domain/models/memory.model.dart create mode 100644 mobile/lib/infrastructure/entities/memory.entity.dart create mode 100644 mobile/lib/infrastructure/entities/memory.entity.drift.dart create mode 100644 mobile/lib/infrastructure/entities/memory_asset.entity.dart create mode 100644 mobile/lib/infrastructure/entities/memory_asset.entity.drift.dart create mode 100644 mobile/lib/infrastructure/repositories/memory.repository.dart diff --git a/mobile/drift_schemas/main/drift_schema_v1.json b/mobile/drift_schemas/main/drift_schema_v1.json index 30f92cf8db..32ba52e366 100644 --- a/mobile/drift_schemas/main/drift_schema_v1.json +++ b/mobile/drift_schemas/main/drift_schema_v1.json @@ -1 +1,1331 @@ -{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":true},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"user_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_admin","getter_name":"isAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"email","getter_name":"email","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"profile_image_path","getter_name":"profileImagePath","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"quota_size_in_bytes","getter_name":"quotaSizeInBytes","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quota_usage_in_bytes","getter_name":"quotaUsageInBytes","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":1,"references":[0],"type":"table","data":{"name":"remote_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"local_date_time","getter_name":"localDateTime","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"thumb_hash","getter_name":"thumbHash","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"deleted_at","getter_name":"deletedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"visibility","getter_name":"visibility","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetVisibility.values)","dart_type_name":"AssetVisibility"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":2,"references":[],"type":"table","data":{"name":"local_asset_entity","was_declared_in_moor":false,"columns":[{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AssetType.values)","dart_type_name":"AssetType"}},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"duration_in_seconds","getter_name":"durationInSeconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"checksum","getter_name":"checksum","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_favorite","getter_name":"isFavorite","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_favorite\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_favorite\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":3,"references":[2],"type":"index","data":{"on":2,"name":"idx_local_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}},{"id":4,"references":[1],"type":"index","data":{"on":1,"name":"UQ_remote_asset_owner_checksum","sql":null,"unique":true,"columns":["checksum","owner_id"]}},{"id":5,"references":[1],"type":"index","data":{"on":1,"name":"idx_remote_asset_checksum","sql":null,"unique":false,"columns":["checksum"]}},{"id":6,"references":[0],"type":"table","data":{"name":"user_metadata_entity","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"preferences","getter_name":"preferences","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"userPreferenceConverter","dart_type_name":"UserPreferences"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["user_id"]}},{"id":7,"references":[0],"type":"table","data":{"name":"partner_entity","was_declared_in_moor":false,"columns":[{"name":"shared_by_id","getter_name":"sharedById","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"shared_with_id","getter_name":"sharedWithId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"in_timeline","getter_name":"inTimeline","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"in_timeline\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"in_timeline\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["shared_by_id","shared_with_id"]}},{"id":8,"references":[],"type":"table","data":{"name":"local_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"backup_selection","getter_name":"backupSelection","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(BackupSelection.values)","dart_type_name":"BackupSelection"}},{"name":"is_ios_shared_album","getter_name":"isIosSharedAlbum","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_ios_shared_album\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_ios_shared_album\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"marker","getter_name":"marker_","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"marker\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"marker\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":9,"references":[2,8],"type":"table","data":{"name":"local_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES local_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES local_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":10,"references":[1],"type":"table","data":{"name":"remote_exif_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"city","getter_name":"city","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"state","getter_name":"state","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"country","getter_name":"country","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"date_time_original","getter_name":"dateTimeOriginal","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"height","getter_name":"height","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"width","getter_name":"width","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"exposure_time","getter_name":"exposureTime","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"f_number","getter_name":"fNumber","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"file_size","getter_name":"fileSize","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"focal_length","getter_name":"focalLength","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"latitude","getter_name":"latitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"longitude","getter_name":"longitude","moor_type":"double","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"iso","getter_name":"iso","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"make","getter_name":"make","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"model","getter_name":"model","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"lens","getter_name":"lens","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"orientation","getter_name":"orientation","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"time_zone","getter_name":"timeZone","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"rating","getter_name":"rating","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"projection_type","getter_name":"projectionType","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id"]}},{"id":11,"references":[0,1],"type":"table","data":{"name":"remote_album_entity","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"name","getter_name":"name","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"description","getter_name":"description","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('\\'\\'')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"updated_at","getter_name":"updatedAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CURRENT_TIMESTAMP')","default_client_dart":null,"dsl_features":[]},{"name":"owner_id","getter_name":"ownerId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"thumbnail_asset_id","getter_name":"thumbnailAssetId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"is_activity_enabled","getter_name":"isActivityEnabled","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_activity_enabled\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_activity_enabled\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"order","getter_name":"order","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumAssetOrder.values)","dart_type_name":"AlbumAssetOrder"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["id"]}},{"id":12,"references":[1,11],"type":"table","data":{"name":"remote_album_asset_entity","was_declared_in_moor":false,"columns":[{"name":"asset_id","getter_name":"assetId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_asset_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["asset_id","album_id"]}},{"id":13,"references":[11,0],"type":"table","data":{"name":"remote_album_user_entity","was_declared_in_moor":false,"columns":[{"name":"album_id","getter_name":"albumId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES remote_album_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES remote_album_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"user_id","getter_name":"userId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES user_entity (id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES user_entity (id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":["unknown"]},{"name":"role","getter_name":"role","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumIndexConverter(AlbumUserRole.values)","dart_type_name":"AlbumUserRole"}}],"is_virtual":false,"without_rowid":true,"constraints":[],"strict":true,"explicit_pk":["album_id","user_id"]}}]} \ No newline at end of file +{ + "_meta": { + "description": "This file contains a serialized version of schema entities for drift.", + "version": "1.2.0" + }, + "options": { "store_date_time_values_as_text": true }, + "entities": [ + { + "id": 0, + "references": [], + "type": "table", + "data": { + "name": "user_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_admin", + "getter_name": "isAdmin", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_admin\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_admin\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "email", + "getter_name": "email", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "profile_image_path", + "getter_name": "profileImagePath", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quota_size_in_bytes", + "getter_name": "quotaSizeInBytes", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "quota_usage_in_bytes", + "getter_name": "quotaUsageInBytes", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 1, + "references": [0], + "type": "table", + "data": { + "name": "remote_asset_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(AssetType.values)", + "dart_type_name": "AssetType" + } + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "width", + "getter_name": "width", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "height", + "getter_name": "height", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "duration_in_seconds", + "getter_name": "durationInSeconds", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "checksum", + "getter_name": "checksum", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_favorite", + "getter_name": "isFavorite", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_favorite\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_favorite\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "owner_id", + "getter_name": "ownerId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "local_date_time", + "getter_name": "localDateTime", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "thumb_hash", + "getter_name": "thumbHash", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "deleted_at", + "getter_name": "deletedAt", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "visibility", + "getter_name": "visibility", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(AssetVisibility.values)", + "dart_type_name": "AssetVisibility" + } + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 2, + "references": [], + "type": "table", + "data": { + "name": "local_asset_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(AssetType.values)", + "dart_type_name": "AssetType" + } + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "width", + "getter_name": "width", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "height", + "getter_name": "height", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "duration_in_seconds", + "getter_name": "durationInSeconds", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "checksum", + "getter_name": "checksum", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_favorite", + "getter_name": "isFavorite", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_favorite\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_favorite\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 3, + "references": [2], + "type": "index", + "data": { + "on": 2, + "name": "idx_local_asset_checksum", + "sql": null, + "unique": false, + "columns": ["checksum"] + } + }, + { + "id": 4, + "references": [1], + "type": "index", + "data": { + "on": 1, + "name": "UQ_remote_asset_owner_checksum", + "sql": null, + "unique": true, + "columns": ["checksum", "owner_id"] + } + }, + { + "id": 5, + "references": [1], + "type": "index", + "data": { + "on": 1, + "name": "idx_remote_asset_checksum", + "sql": null, + "unique": false, + "columns": ["checksum"] + } + }, + { + "id": 6, + "references": [0], + "type": "table", + "data": { + "name": "user_metadata_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "user_id", + "getter_name": "userId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "preferences", + "getter_name": "preferences", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "userPreferenceConverter", + "dart_type_name": "UserPreferences" + } + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["user_id"] + } + }, + { + "id": 7, + "references": [0], + "type": "table", + "data": { + "name": "partner_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "shared_by_id", + "getter_name": "sharedById", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "shared_with_id", + "getter_name": "sharedWithId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "in_timeline", + "getter_name": "inTimeline", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"in_timeline\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"in_timeline\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["shared_by_id", "shared_with_id"] + } + }, + { + "id": 8, + "references": [], + "type": "table", + "data": { + "name": "local_album_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "backup_selection", + "getter_name": "backupSelection", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(BackupSelection.values)", + "dart_type_name": "BackupSelection" + } + }, + { + "name": "is_ios_shared_album", + "getter_name": "isIosSharedAlbum", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_ios_shared_album\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_ios_shared_album\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "marker", + "getter_name": "marker_", + "moor_type": "bool", + "nullable": true, + "customConstraints": null, + "defaultConstraints": "CHECK (\"marker\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"marker\" IN (0, 1))" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 9, + "references": [2, 8], + "type": "table", + "data": { + "name": "local_album_asset_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "asset_id", + "getter_name": "assetId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES local_asset_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES local_asset_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "album_id", + "getter_name": "albumId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES local_album_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES local_album_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["asset_id", "album_id"] + } + }, + { + "id": 10, + "references": [1], + "type": "table", + "data": { + "name": "remote_exif_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "asset_id", + "getter_name": "assetId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "city", + "getter_name": "city", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "state", + "getter_name": "state", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "country", + "getter_name": "country", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "date_time_original", + "getter_name": "dateTimeOriginal", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "description", + "getter_name": "description", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "height", + "getter_name": "height", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "width", + "getter_name": "width", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "exposure_time", + "getter_name": "exposureTime", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "f_number", + "getter_name": "fNumber", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "file_size", + "getter_name": "fileSize", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "focal_length", + "getter_name": "focalLength", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "latitude", + "getter_name": "latitude", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "longitude", + "getter_name": "longitude", + "moor_type": "double", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "iso", + "getter_name": "iso", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "make", + "getter_name": "make", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "model", + "getter_name": "model", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "orientation", + "getter_name": "orientation", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "time_zone", + "getter_name": "timeZone", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "rating", + "getter_name": "rating", + "moor_type": "int", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "projection_type", + "getter_name": "projectionType", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["asset_id"] + } + }, + { + "id": 11, + "references": [0, 1], + "type": "table", + "data": { + "name": "remote_album_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "name", + "getter_name": "name", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "description", + "getter_name": "description", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('\\'\\'')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "owner_id", + "getter_name": "ownerId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "thumbnail_asset_id", + "getter_name": "thumbnailAssetId", + "moor_type": "string", + "nullable": true, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_asset_entity (id) ON DELETE SET NULL", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_asset_entity (id) ON DELETE SET NULL" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "is_activity_enabled", + "getter_name": "isActivityEnabled", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_activity_enabled\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_activity_enabled\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('1')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "order", + "getter_name": "order", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(AlbumAssetOrder.values)", + "dart_type_name": "AlbumAssetOrder" + } + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 12, + "references": [1, 11], + "type": "table", + "data": { + "name": "remote_album_asset_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "asset_id", + "getter_name": "assetId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "album_id", + "getter_name": "albumId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_album_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_album_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["asset_id", "album_id"] + } + }, + { + "id": 13, + "references": [11, 0], + "type": "table", + "data": { + "name": "remote_album_user_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "album_id", + "getter_name": "albumId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_album_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_album_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "user_id", + "getter_name": "userId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "role", + "getter_name": "role", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(AlbumUserRole.values)", + "dart_type_name": "AlbumUserRole" + } + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["album_id", "user_id"] + } + }, + { + "id": 14, + "references": [0], + "type": "table", + "data": { + "name": "memory_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "id", + "getter_name": "id", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "created_at", + "getter_name": "createdAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "updated_at", + "getter_name": "updatedAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": "const CustomExpression('CURRENT_TIMESTAMP')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "deleted_at", + "getter_name": "deletedAt", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "owner_id", + "getter_name": "ownerId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES user_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES user_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "type", + "getter_name": "type", + "moor_type": "int", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [], + "type_converter": { + "dart_expr": "const EnumIndexConverter(MemoryType.values)", + "dart_type_name": "MemoryType" + } + }, + { + "name": "data", + "getter_name": "data", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "is_saved", + "getter_name": "isSaved", + "moor_type": "bool", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "CHECK (\"is_saved\" IN (0, 1))", + "dialectAwareDefaultConstraints": { + "sqlite": "CHECK (\"is_saved\" IN (0, 1))" + }, + "default_dart": "const CustomExpression('0')", + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "memory_at", + "getter_name": "memoryAt", + "moor_type": "dateTime", + "nullable": false, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "seen_at", + "getter_name": "seenAt", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "show_at", + "getter_name": "showAt", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + }, + { + "name": "hide_at", + "getter_name": "hideAt", + "moor_type": "dateTime", + "nullable": true, + "customConstraints": null, + "default_dart": null, + "default_client_dart": null, + "dsl_features": [] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["id"] + } + }, + { + "id": 15, + "references": [1, 14], + "type": "table", + "data": { + "name": "memory_asset_entity", + "was_declared_in_moor": false, + "columns": [ + { + "name": "asset_id", + "getter_name": "assetId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES remote_asset_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + }, + { + "name": "memory_id", + "getter_name": "memoryId", + "moor_type": "string", + "nullable": false, + "customConstraints": null, + "defaultConstraints": "REFERENCES memory_entity (id) ON DELETE CASCADE", + "dialectAwareDefaultConstraints": { + "sqlite": "REFERENCES memory_entity (id) ON DELETE CASCADE" + }, + "default_dart": null, + "default_client_dart": null, + "dsl_features": ["unknown"] + } + ], + "is_virtual": false, + "without_rowid": true, + "constraints": [], + "strict": true, + "explicit_pk": ["asset_id", "memory_id"] + } + } + ] +} diff --git a/mobile/lib/domain/models/memory.model.dart b/mobile/lib/domain/models/memory.model.dart new file mode 100644 index 0000000000..d24e1ae1c6 --- /dev/null +++ b/mobile/lib/domain/models/memory.model.dart @@ -0,0 +1,202 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'dart:convert'; + +enum MemoryTypeEnum { + // do not change this order! + onThisDay, +} + +class MemoryData { + final int year; + + const MemoryData({ + required this.year, + }); + + MemoryData copyWith({ + int? year, + }) { + return MemoryData( + year: year ?? this.year, + ); + } + + Map toMap() { + return { + 'year': year, + }; + } + + factory MemoryData.fromMap(Map map) { + return MemoryData( + year: map['year'] as int, + ); + } + + String toJson() => json.encode(toMap()); + + factory MemoryData.fromJson(String source) => + MemoryData.fromMap(json.decode(source) as Map); + + @override + String toString() => 'MemoryData(year: $year)'; + + @override + bool operator ==(covariant MemoryData other) { + if (identical(this, other)) return true; + + return other.year == year; + } + + @override + int get hashCode => year.hashCode; +} + +// Model for a memory stored in the server +class Memory { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + + // enum + final MemoryTypeEnum type; + final MemoryData data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + + const Memory({ + required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt, + }); + + Memory copyWith({ + String? id, + DateTime? createdAt, + DateTime? updatedAt, + DateTime? deletedAt, + String? ownerId, + MemoryTypeEnum? type, + MemoryData? data, + bool? isSaved, + DateTime? memoryAt, + DateTime? seenAt, + DateTime? showAt, + DateTime? hideAt, + }) { + return Memory( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + Map toMap() { + return { + 'id': id, + 'createdAt': createdAt.millisecondsSinceEpoch, + 'updatedAt': updatedAt.millisecondsSinceEpoch, + 'deletedAt': deletedAt?.millisecondsSinceEpoch, + 'ownerId': ownerId, + 'type': type.index, + 'data': data.toMap(), + 'isSaved': isSaved, + 'memoryAt': memoryAt.millisecondsSinceEpoch, + 'seenAt': seenAt?.millisecondsSinceEpoch, + 'showAt': showAt?.millisecondsSinceEpoch, + 'hideAt': hideAt?.millisecondsSinceEpoch, + }; + } + + factory Memory.fromMap(Map map) { + return Memory( + id: map['id'] as String, + createdAt: DateTime.fromMillisecondsSinceEpoch(map['createdAt'] as int), + updatedAt: DateTime.fromMillisecondsSinceEpoch(map['updatedAt'] as int), + deletedAt: map['deletedAt'] != null + ? DateTime.fromMillisecondsSinceEpoch(map['deletedAt'] as int) + : null, + ownerId: map['ownerId'] as String, + type: MemoryTypeEnum.values[map['type'] as int], + data: MemoryData.fromMap(map['data'] as Map), + isSaved: map['isSaved'] as bool, + memoryAt: DateTime.fromMillisecondsSinceEpoch(map['memoryAt'] as int), + seenAt: map['seenAt'] != null + ? DateTime.fromMillisecondsSinceEpoch(map['seenAt'] as int) + : null, + showAt: map['showAt'] != null + ? DateTime.fromMillisecondsSinceEpoch(map['showAt'] as int) + : null, + hideAt: map['hideAt'] != null + ? DateTime.fromMillisecondsSinceEpoch(map['hideAt'] as int) + : null, + ); + } + + String toJson() => json.encode(toMap()); + + factory Memory.fromJson(String source) => + Memory.fromMap(json.decode(source) as Map); + + @override + String toString() { + return 'Memory(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, ownerId: $ownerId, type: $type, data: $data, isSaved: $isSaved, memoryAt: $memoryAt, seenAt: $seenAt, showAt: $showAt, hideAt: $hideAt)'; + } + + @override + bool operator ==(covariant Memory other) { + if (identical(this, other)) return true; + + return other.id == id && + other.createdAt == createdAt && + other.updatedAt == updatedAt && + other.deletedAt == deletedAt && + other.ownerId == ownerId && + other.type == type && + other.data == data && + other.isSaved == isSaved && + other.memoryAt == memoryAt && + other.seenAt == seenAt && + other.showAt == showAt && + other.hideAt == hideAt; + } + + @override + int get hashCode { + return id.hashCode ^ + createdAt.hashCode ^ + updatedAt.hashCode ^ + deletedAt.hashCode ^ + ownerId.hashCode ^ + type.hashCode ^ + data.hashCode ^ + isSaved.hashCode ^ + memoryAt.hashCode ^ + seenAt.hashCode ^ + showAt.hashCode ^ + hideAt.hashCode; + } +} diff --git a/mobile/lib/domain/services/sync_stream.service.dart b/mobile/lib/domain/services/sync_stream.service.dart index 2160018df5..c4e40726b5 100644 --- a/mobile/lib/domain/services/sync_stream.service.dart +++ b/mobile/lib/domain/services/sync_stream.service.dart @@ -146,6 +146,14 @@ class SyncStreamService { // to acknowledge that the client has processed all the backfill events case SyncEntityType.syncAckV1: return; + case SyncEntityType.memoryV1: + return _syncStreamRepository.updateMemoriesV1(data.cast()); + case SyncEntityType.memoryDeleteV1: + return _syncStreamRepository.deleteMemoriesV1(data.cast()); + case SyncEntityType.memoryToAssetV1: + return _syncStreamRepository.updateMemoryAssetsV1(data.cast()); + case SyncEntityType.memoryToAssetDeleteV1: + return _syncStreamRepository.deleteMemoryAssetsV1(data.cast()); default: _logger.warning("Unknown sync data type: $type"); } diff --git a/mobile/lib/infrastructure/entities/memory.entity.dart b/mobile/lib/infrastructure/entities/memory.entity.dart new file mode 100644 index 0000000000..0e19802103 --- /dev/null +++ b/mobile/lib/infrastructure/entities/memory.entity.dart @@ -0,0 +1,36 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/memory.model.dart'; +import 'package:immich_mobile/infrastructure/entities/user.entity.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class MemoryEntity extends Table with DriftDefaultsMixin { + const MemoryEntity(); + + TextColumn get id => text()(); + + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); + + DateTimeColumn get updatedAt => dateTime().withDefault(currentDateAndTime)(); + + DateTimeColumn get deletedAt => dateTime().nullable()(); + + TextColumn get ownerId => + text().references(UserEntity, #id, onDelete: KeyAction.cascade)(); + + IntColumn get type => intEnum()(); + + TextColumn get data => text()(); + + BoolColumn get isSaved => boolean().withDefault(const Constant(false))(); + + DateTimeColumn get memoryAt => dateTime()(); + + DateTimeColumn get seenAt => dateTime().nullable()(); + + DateTimeColumn get showAt => dateTime().nullable()(); + + DateTimeColumn get hideAt => dateTime().nullable()(); + + @override + Set get primaryKey => {id}; +} diff --git a/mobile/lib/infrastructure/entities/memory.entity.drift.dart b/mobile/lib/infrastructure/entities/memory.entity.drift.dart new file mode 100644 index 0000000000..cb88651ba4 --- /dev/null +++ b/mobile/lib/infrastructure/entities/memory.entity.drift.dart @@ -0,0 +1,970 @@ +// dart format width=80 +// ignore_for_file: type=lint +import 'package:drift/drift.dart' as i0; +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart' + as i1; +import 'package:immich_mobile/domain/models/memory.model.dart' as i2; +import 'package:immich_mobile/infrastructure/entities/memory.entity.dart' as i3; +import 'package:drift/src/runtime/query_builder/query_builder.dart' as i4; +import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart' + as i5; +import 'package:drift/internal/modular.dart' as i6; + +typedef $$MemoryEntityTableCreateCompanionBuilder = i1.MemoryEntityCompanion + Function({ + required String id, + i0.Value createdAt, + i0.Value updatedAt, + i0.Value deletedAt, + required String ownerId, + required i2.MemoryTypeEnum type, + required String data, + i0.Value isSaved, + required DateTime memoryAt, + i0.Value seenAt, + i0.Value showAt, + i0.Value hideAt, +}); +typedef $$MemoryEntityTableUpdateCompanionBuilder = i1.MemoryEntityCompanion + Function({ + i0.Value id, + i0.Value createdAt, + i0.Value updatedAt, + i0.Value deletedAt, + i0.Value ownerId, + i0.Value type, + i0.Value data, + i0.Value isSaved, + i0.Value memoryAt, + i0.Value seenAt, + i0.Value showAt, + i0.Value hideAt, +}); + +final class $$MemoryEntityTableReferences extends i0.BaseReferences< + i0.GeneratedDatabase, i1.$MemoryEntityTable, i1.MemoryEntityData> { + $$MemoryEntityTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static i5.$UserEntityTable _ownerIdTable(i0.GeneratedDatabase db) => + i6.ReadDatabaseContainer(db) + .resultSet('user_entity') + .createAlias(i0.$_aliasNameGenerator( + i6.ReadDatabaseContainer(db) + .resultSet('memory_entity') + .ownerId, + i6.ReadDatabaseContainer(db) + .resultSet('user_entity') + .id)); + + i5.$$UserEntityTableProcessedTableManager get ownerId { + final $_column = $_itemColumn('owner_id')!; + + final manager = i5 + .$$UserEntityTableTableManager( + $_db, + i6.ReadDatabaseContainer($_db) + .resultSet('user_entity')) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_ownerIdTable($_db)); + if (item == null) return manager; + return i0.ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } +} + +class $$MemoryEntityTableFilterComposer + extends i0.Composer { + $$MemoryEntityTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get updatedAt => $composableBuilder( + column: $table.updatedAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get deletedAt => $composableBuilder( + column: $table.deletedAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnWithTypeConverterFilters + get type => $composableBuilder( + column: $table.type, + builder: (column) => i0.ColumnWithTypeConverterFilters(column)); + + i0.ColumnFilters get data => $composableBuilder( + column: $table.data, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get isSaved => $composableBuilder( + column: $table.isSaved, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get memoryAt => $composableBuilder( + column: $table.memoryAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get seenAt => $composableBuilder( + column: $table.seenAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get showAt => $composableBuilder( + column: $table.showAt, builder: (column) => i0.ColumnFilters(column)); + + i0.ColumnFilters get hideAt => $composableBuilder( + column: $table.hideAt, builder: (column) => i0.ColumnFilters(column)); + + i5.$$UserEntityTableFilterComposer get ownerId { + final i5.$$UserEntityTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.ownerId, + referencedTable: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$UserEntityTableFilterComposer( + $db: $db, + $table: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryEntityTableOrderingComposer + extends i0.Composer { + $$MemoryEntityTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get updatedAt => $composableBuilder( + column: $table.updatedAt, + builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get deletedAt => $composableBuilder( + column: $table.deletedAt, + builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get type => $composableBuilder( + column: $table.type, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get data => $composableBuilder( + column: $table.data, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get isSaved => $composableBuilder( + column: $table.isSaved, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get memoryAt => $composableBuilder( + column: $table.memoryAt, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get seenAt => $composableBuilder( + column: $table.seenAt, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get showAt => $composableBuilder( + column: $table.showAt, builder: (column) => i0.ColumnOrderings(column)); + + i0.ColumnOrderings get hideAt => $composableBuilder( + column: $table.hideAt, builder: (column) => i0.ColumnOrderings(column)); + + i5.$$UserEntityTableOrderingComposer get ownerId { + final i5.$$UserEntityTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.ownerId, + referencedTable: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$UserEntityTableOrderingComposer( + $db: $db, + $table: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryEntityTableAnnotationComposer + extends i0.Composer { + $$MemoryEntityTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i0.GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + i0.GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + i0.GeneratedColumn get updatedAt => + $composableBuilder(column: $table.updatedAt, builder: (column) => column); + + i0.GeneratedColumn get deletedAt => + $composableBuilder(column: $table.deletedAt, builder: (column) => column); + + i0.GeneratedColumnWithTypeConverter get type => + $composableBuilder(column: $table.type, builder: (column) => column); + + i0.GeneratedColumn get data => + $composableBuilder(column: $table.data, builder: (column) => column); + + i0.GeneratedColumn get isSaved => + $composableBuilder(column: $table.isSaved, builder: (column) => column); + + i0.GeneratedColumn get memoryAt => + $composableBuilder(column: $table.memoryAt, builder: (column) => column); + + i0.GeneratedColumn get seenAt => + $composableBuilder(column: $table.seenAt, builder: (column) => column); + + i0.GeneratedColumn get showAt => + $composableBuilder(column: $table.showAt, builder: (column) => column); + + i0.GeneratedColumn get hideAt => + $composableBuilder(column: $table.hideAt, builder: (column) => column); + + i5.$$UserEntityTableAnnotationComposer get ownerId { + final i5.$$UserEntityTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.ownerId, + referencedTable: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$UserEntityTableAnnotationComposer( + $db: $db, + $table: i6.ReadDatabaseContainer($db) + .resultSet('user_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryEntityTableTableManager extends i0.RootTableManager< + i0.GeneratedDatabase, + i1.$MemoryEntityTable, + i1.MemoryEntityData, + i1.$$MemoryEntityTableFilterComposer, + i1.$$MemoryEntityTableOrderingComposer, + i1.$$MemoryEntityTableAnnotationComposer, + $$MemoryEntityTableCreateCompanionBuilder, + $$MemoryEntityTableUpdateCompanionBuilder, + (i1.MemoryEntityData, i1.$$MemoryEntityTableReferences), + i1.MemoryEntityData, + i0.PrefetchHooks Function({bool ownerId})> { + $$MemoryEntityTableTableManager( + i0.GeneratedDatabase db, i1.$MemoryEntityTable table) + : super(i0.TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + i1.$$MemoryEntityTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + i1.$$MemoryEntityTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + i1.$$MemoryEntityTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + i0.Value id = const i0.Value.absent(), + i0.Value createdAt = const i0.Value.absent(), + i0.Value updatedAt = const i0.Value.absent(), + i0.Value deletedAt = const i0.Value.absent(), + i0.Value ownerId = const i0.Value.absent(), + i0.Value type = const i0.Value.absent(), + i0.Value data = const i0.Value.absent(), + i0.Value isSaved = const i0.Value.absent(), + i0.Value memoryAt = const i0.Value.absent(), + i0.Value seenAt = const i0.Value.absent(), + i0.Value showAt = const i0.Value.absent(), + i0.Value hideAt = const i0.Value.absent(), + }) => + i1.MemoryEntityCompanion( + id: id, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + ownerId: ownerId, + type: type, + data: data, + isSaved: isSaved, + memoryAt: memoryAt, + seenAt: seenAt, + showAt: showAt, + hideAt: hideAt, + ), + createCompanionCallback: ({ + required String id, + i0.Value createdAt = const i0.Value.absent(), + i0.Value updatedAt = const i0.Value.absent(), + i0.Value deletedAt = const i0.Value.absent(), + required String ownerId, + required i2.MemoryTypeEnum type, + required String data, + i0.Value isSaved = const i0.Value.absent(), + required DateTime memoryAt, + i0.Value seenAt = const i0.Value.absent(), + i0.Value showAt = const i0.Value.absent(), + i0.Value hideAt = const i0.Value.absent(), + }) => + i1.MemoryEntityCompanion.insert( + id: id, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + ownerId: ownerId, + type: type, + data: data, + isSaved: isSaved, + memoryAt: memoryAt, + seenAt: seenAt, + showAt: showAt, + hideAt: hideAt, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + i1.$$MemoryEntityTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ({ownerId = false}) { + return i0.PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: < + T extends i0.TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (ownerId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.ownerId, + referencedTable: + i1.$$MemoryEntityTableReferences._ownerIdTable(db), + referencedColumn: + i1.$$MemoryEntityTableReferences._ownerIdTable(db).id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + )); +} + +typedef $$MemoryEntityTableProcessedTableManager = i0.ProcessedTableManager< + i0.GeneratedDatabase, + i1.$MemoryEntityTable, + i1.MemoryEntityData, + i1.$$MemoryEntityTableFilterComposer, + i1.$$MemoryEntityTableOrderingComposer, + i1.$$MemoryEntityTableAnnotationComposer, + $$MemoryEntityTableCreateCompanionBuilder, + $$MemoryEntityTableUpdateCompanionBuilder, + (i1.MemoryEntityData, i1.$$MemoryEntityTableReferences), + i1.MemoryEntityData, + i0.PrefetchHooks Function({bool ownerId})>; + +class $MemoryEntityTable extends i3.MemoryEntity + with i0.TableInfo<$MemoryEntityTable, i1.MemoryEntityData> { + @override + final i0.GeneratedDatabase attachedDatabase; + final String? _alias; + $MemoryEntityTable(this.attachedDatabase, [this._alias]); + static const i0.VerificationMeta _idMeta = const i0.VerificationMeta('id'); + @override + late final i0.GeneratedColumn id = i0.GeneratedColumn( + 'id', aliasedName, false, + type: i0.DriftSqlType.string, requiredDuringInsert: true); + static const i0.VerificationMeta _createdAtMeta = + const i0.VerificationMeta('createdAt'); + @override + late final i0.GeneratedColumn createdAt = + i0.GeneratedColumn('created_at', aliasedName, false, + type: i0.DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: i4.currentDateAndTime); + static const i0.VerificationMeta _updatedAtMeta = + const i0.VerificationMeta('updatedAt'); + @override + late final i0.GeneratedColumn updatedAt = + i0.GeneratedColumn('updated_at', aliasedName, false, + type: i0.DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: i4.currentDateAndTime); + static const i0.VerificationMeta _deletedAtMeta = + const i0.VerificationMeta('deletedAt'); + @override + late final i0.GeneratedColumn deletedAt = + i0.GeneratedColumn('deleted_at', aliasedName, true, + type: i0.DriftSqlType.dateTime, requiredDuringInsert: false); + static const i0.VerificationMeta _ownerIdMeta = + const i0.VerificationMeta('ownerId'); + @override + late final i0.GeneratedColumn ownerId = i0.GeneratedColumn( + 'owner_id', aliasedName, false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'REFERENCES user_entity (id) ON DELETE CASCADE')); + @override + late final i0.GeneratedColumnWithTypeConverter type = + i0.GeneratedColumn('type', aliasedName, false, + type: i0.DriftSqlType.int, requiredDuringInsert: true) + .withConverter( + i1.$MemoryEntityTable.$convertertype); + static const i0.VerificationMeta _dataMeta = + const i0.VerificationMeta('data'); + @override + late final i0.GeneratedColumn data = i0.GeneratedColumn( + 'data', aliasedName, false, + type: i0.DriftSqlType.string, requiredDuringInsert: true); + static const i0.VerificationMeta _isSavedMeta = + const i0.VerificationMeta('isSaved'); + @override + late final i0.GeneratedColumn isSaved = i0.GeneratedColumn( + 'is_saved', aliasedName, false, + type: i0.DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + i0.GeneratedColumn.constraintIsAlways('CHECK ("is_saved" IN (0, 1))'), + defaultValue: const i4.Constant(false)); + static const i0.VerificationMeta _memoryAtMeta = + const i0.VerificationMeta('memoryAt'); + @override + late final i0.GeneratedColumn memoryAt = + i0.GeneratedColumn('memory_at', aliasedName, false, + type: i0.DriftSqlType.dateTime, requiredDuringInsert: true); + static const i0.VerificationMeta _seenAtMeta = + const i0.VerificationMeta('seenAt'); + @override + late final i0.GeneratedColumn seenAt = i0.GeneratedColumn( + 'seen_at', aliasedName, true, + type: i0.DriftSqlType.dateTime, requiredDuringInsert: false); + static const i0.VerificationMeta _showAtMeta = + const i0.VerificationMeta('showAt'); + @override + late final i0.GeneratedColumn showAt = i0.GeneratedColumn( + 'show_at', aliasedName, true, + type: i0.DriftSqlType.dateTime, requiredDuringInsert: false); + static const i0.VerificationMeta _hideAtMeta = + const i0.VerificationMeta('hideAt'); + @override + late final i0.GeneratedColumn hideAt = i0.GeneratedColumn( + 'hide_at', aliasedName, true, + type: i0.DriftSqlType.dateTime, requiredDuringInsert: false); + @override + List get $columns => [ + id, + createdAt, + updatedAt, + deletedAt, + ownerId, + type, + data, + isSaved, + memoryAt, + seenAt, + showAt, + hideAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_entity'; + @override + i0.VerificationContext validateIntegrity( + i0.Insertable instance, + {bool isInserting = false}) { + final context = i0.VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + if (data.containsKey('updated_at')) { + context.handle(_updatedAtMeta, + updatedAt.isAcceptableOrUnknown(data['updated_at']!, _updatedAtMeta)); + } + if (data.containsKey('deleted_at')) { + context.handle(_deletedAtMeta, + deletedAt.isAcceptableOrUnknown(data['deleted_at']!, _deletedAtMeta)); + } + if (data.containsKey('owner_id')) { + context.handle(_ownerIdMeta, + ownerId.isAcceptableOrUnknown(data['owner_id']!, _ownerIdMeta)); + } else if (isInserting) { + context.missing(_ownerIdMeta); + } + if (data.containsKey('data')) { + context.handle( + _dataMeta, this.data.isAcceptableOrUnknown(data['data']!, _dataMeta)); + } else if (isInserting) { + context.missing(_dataMeta); + } + if (data.containsKey('is_saved')) { + context.handle(_isSavedMeta, + isSaved.isAcceptableOrUnknown(data['is_saved']!, _isSavedMeta)); + } + if (data.containsKey('memory_at')) { + context.handle(_memoryAtMeta, + memoryAt.isAcceptableOrUnknown(data['memory_at']!, _memoryAtMeta)); + } else if (isInserting) { + context.missing(_memoryAtMeta); + } + if (data.containsKey('seen_at')) { + context.handle(_seenAtMeta, + seenAt.isAcceptableOrUnknown(data['seen_at']!, _seenAtMeta)); + } + if (data.containsKey('show_at')) { + context.handle(_showAtMeta, + showAt.isAcceptableOrUnknown(data['show_at']!, _showAtMeta)); + } + if (data.containsKey('hide_at')) { + context.handle(_hideAtMeta, + hideAt.isAcceptableOrUnknown(data['hide_at']!, _hideAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + i1.MemoryEntityData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return i1.MemoryEntityData( + id: attachedDatabase.typeMapping + .read(i0.DriftSqlType.string, data['${effectivePrefix}id'])!, + createdAt: attachedDatabase.typeMapping.read( + i0.DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + updatedAt: attachedDatabase.typeMapping.read( + i0.DriftSqlType.dateTime, data['${effectivePrefix}updated_at'])!, + deletedAt: attachedDatabase.typeMapping + .read(i0.DriftSqlType.dateTime, data['${effectivePrefix}deleted_at']), + ownerId: attachedDatabase.typeMapping + .read(i0.DriftSqlType.string, data['${effectivePrefix}owner_id'])!, + type: i1.$MemoryEntityTable.$convertertype.fromSql(attachedDatabase + .typeMapping + .read(i0.DriftSqlType.int, data['${effectivePrefix}type'])!), + data: attachedDatabase.typeMapping + .read(i0.DriftSqlType.string, data['${effectivePrefix}data'])!, + isSaved: attachedDatabase.typeMapping + .read(i0.DriftSqlType.bool, data['${effectivePrefix}is_saved'])!, + memoryAt: attachedDatabase.typeMapping + .read(i0.DriftSqlType.dateTime, data['${effectivePrefix}memory_at'])!, + seenAt: attachedDatabase.typeMapping + .read(i0.DriftSqlType.dateTime, data['${effectivePrefix}seen_at']), + showAt: attachedDatabase.typeMapping + .read(i0.DriftSqlType.dateTime, data['${effectivePrefix}show_at']), + hideAt: attachedDatabase.typeMapping + .read(i0.DriftSqlType.dateTime, data['${effectivePrefix}hide_at']), + ); + } + + @override + $MemoryEntityTable createAlias(String alias) { + return $MemoryEntityTable(attachedDatabase, alias); + } + + static i0.JsonTypeConverter2 $convertertype = + const i0.EnumIndexConverter(i2.MemoryTypeEnum.values); + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryEntityData extends i0.DataClass + implements i0.Insertable { + final String id; + final DateTime createdAt; + final DateTime updatedAt; + final DateTime? deletedAt; + final String ownerId; + final i2.MemoryTypeEnum type; + final String data; + final bool isSaved; + final DateTime memoryAt; + final DateTime? seenAt; + final DateTime? showAt; + final DateTime? hideAt; + const MemoryEntityData( + {required this.id, + required this.createdAt, + required this.updatedAt, + this.deletedAt, + required this.ownerId, + required this.type, + required this.data, + required this.isSaved, + required this.memoryAt, + this.seenAt, + this.showAt, + this.hideAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = i0.Variable(id); + map['created_at'] = i0.Variable(createdAt); + map['updated_at'] = i0.Variable(updatedAt); + if (!nullToAbsent || deletedAt != null) { + map['deleted_at'] = i0.Variable(deletedAt); + } + map['owner_id'] = i0.Variable(ownerId); + { + map['type'] = + i0.Variable(i1.$MemoryEntityTable.$convertertype.toSql(type)); + } + map['data'] = i0.Variable(data); + map['is_saved'] = i0.Variable(isSaved); + map['memory_at'] = i0.Variable(memoryAt); + if (!nullToAbsent || seenAt != null) { + map['seen_at'] = i0.Variable(seenAt); + } + if (!nullToAbsent || showAt != null) { + map['show_at'] = i0.Variable(showAt); + } + if (!nullToAbsent || hideAt != null) { + map['hide_at'] = i0.Variable(hideAt); + } + return map; + } + + factory MemoryEntityData.fromJson(Map json, + {i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return MemoryEntityData( + id: serializer.fromJson(json['id']), + createdAt: serializer.fromJson(json['createdAt']), + updatedAt: serializer.fromJson(json['updatedAt']), + deletedAt: serializer.fromJson(json['deletedAt']), + ownerId: serializer.fromJson(json['ownerId']), + type: i1.$MemoryEntityTable.$convertertype + .fromJson(serializer.fromJson(json['type'])), + data: serializer.fromJson(json['data']), + isSaved: serializer.fromJson(json['isSaved']), + memoryAt: serializer.fromJson(json['memoryAt']), + seenAt: serializer.fromJson(json['seenAt']), + showAt: serializer.fromJson(json['showAt']), + hideAt: serializer.fromJson(json['hideAt']), + ); + } + @override + Map toJson({i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'createdAt': serializer.toJson(createdAt), + 'updatedAt': serializer.toJson(updatedAt), + 'deletedAt': serializer.toJson(deletedAt), + 'ownerId': serializer.toJson(ownerId), + 'type': serializer + .toJson(i1.$MemoryEntityTable.$convertertype.toJson(type)), + 'data': serializer.toJson(data), + 'isSaved': serializer.toJson(isSaved), + 'memoryAt': serializer.toJson(memoryAt), + 'seenAt': serializer.toJson(seenAt), + 'showAt': serializer.toJson(showAt), + 'hideAt': serializer.toJson(hideAt), + }; + } + + i1.MemoryEntityData copyWith( + {String? id, + DateTime? createdAt, + DateTime? updatedAt, + i0.Value deletedAt = const i0.Value.absent(), + String? ownerId, + i2.MemoryTypeEnum? type, + String? data, + bool? isSaved, + DateTime? memoryAt, + i0.Value seenAt = const i0.Value.absent(), + i0.Value showAt = const i0.Value.absent(), + i0.Value hideAt = const i0.Value.absent()}) => + i1.MemoryEntityData( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt.present ? deletedAt.value : this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt.present ? seenAt.value : this.seenAt, + showAt: showAt.present ? showAt.value : this.showAt, + hideAt: hideAt.present ? hideAt.value : this.hideAt, + ); + MemoryEntityData copyWithCompanion(i1.MemoryEntityCompanion data) { + return MemoryEntityData( + id: data.id.present ? data.id.value : this.id, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + updatedAt: data.updatedAt.present ? data.updatedAt.value : this.updatedAt, + deletedAt: data.deletedAt.present ? data.deletedAt.value : this.deletedAt, + ownerId: data.ownerId.present ? data.ownerId.value : this.ownerId, + type: data.type.present ? data.type.value : this.type, + data: data.data.present ? data.data.value : this.data, + isSaved: data.isSaved.present ? data.isSaved.value : this.isSaved, + memoryAt: data.memoryAt.present ? data.memoryAt.value : this.memoryAt, + seenAt: data.seenAt.present ? data.seenAt.value : this.seenAt, + showAt: data.showAt.present ? data.showAt.value : this.showAt, + hideAt: data.hideAt.present ? data.hideAt.value : this.hideAt, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryEntityData(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, createdAt, updatedAt, deletedAt, ownerId, + type, data, isSaved, memoryAt, seenAt, showAt, hideAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is i1.MemoryEntityData && + other.id == this.id && + other.createdAt == this.createdAt && + other.updatedAt == this.updatedAt && + other.deletedAt == this.deletedAt && + other.ownerId == this.ownerId && + other.type == this.type && + other.data == this.data && + other.isSaved == this.isSaved && + other.memoryAt == this.memoryAt && + other.seenAt == this.seenAt && + other.showAt == this.showAt && + other.hideAt == this.hideAt); +} + +class MemoryEntityCompanion extends i0.UpdateCompanion { + final i0.Value id; + final i0.Value createdAt; + final i0.Value updatedAt; + final i0.Value deletedAt; + final i0.Value ownerId; + final i0.Value type; + final i0.Value data; + final i0.Value isSaved; + final i0.Value memoryAt; + final i0.Value seenAt; + final i0.Value showAt; + final i0.Value hideAt; + const MemoryEntityCompanion({ + this.id = const i0.Value.absent(), + this.createdAt = const i0.Value.absent(), + this.updatedAt = const i0.Value.absent(), + this.deletedAt = const i0.Value.absent(), + this.ownerId = const i0.Value.absent(), + this.type = const i0.Value.absent(), + this.data = const i0.Value.absent(), + this.isSaved = const i0.Value.absent(), + this.memoryAt = const i0.Value.absent(), + this.seenAt = const i0.Value.absent(), + this.showAt = const i0.Value.absent(), + this.hideAt = const i0.Value.absent(), + }); + MemoryEntityCompanion.insert({ + required String id, + this.createdAt = const i0.Value.absent(), + this.updatedAt = const i0.Value.absent(), + this.deletedAt = const i0.Value.absent(), + required String ownerId, + required i2.MemoryTypeEnum type, + required String data, + this.isSaved = const i0.Value.absent(), + required DateTime memoryAt, + this.seenAt = const i0.Value.absent(), + this.showAt = const i0.Value.absent(), + this.hideAt = const i0.Value.absent(), + }) : id = i0.Value(id), + ownerId = i0.Value(ownerId), + type = i0.Value(type), + data = i0.Value(data), + memoryAt = i0.Value(memoryAt); + static i0.Insertable custom({ + i0.Expression? id, + i0.Expression? createdAt, + i0.Expression? updatedAt, + i0.Expression? deletedAt, + i0.Expression? ownerId, + i0.Expression? type, + i0.Expression? data, + i0.Expression? isSaved, + i0.Expression? memoryAt, + i0.Expression? seenAt, + i0.Expression? showAt, + i0.Expression? hideAt, + }) { + return i0.RawValuesInsertable({ + if (id != null) 'id': id, + if (createdAt != null) 'created_at': createdAt, + if (updatedAt != null) 'updated_at': updatedAt, + if (deletedAt != null) 'deleted_at': deletedAt, + if (ownerId != null) 'owner_id': ownerId, + if (type != null) 'type': type, + if (data != null) 'data': data, + if (isSaved != null) 'is_saved': isSaved, + if (memoryAt != null) 'memory_at': memoryAt, + if (seenAt != null) 'seen_at': seenAt, + if (showAt != null) 'show_at': showAt, + if (hideAt != null) 'hide_at': hideAt, + }); + } + + i1.MemoryEntityCompanion copyWith( + {i0.Value? id, + i0.Value? createdAt, + i0.Value? updatedAt, + i0.Value? deletedAt, + i0.Value? ownerId, + i0.Value? type, + i0.Value? data, + i0.Value? isSaved, + i0.Value? memoryAt, + i0.Value? seenAt, + i0.Value? showAt, + i0.Value? hideAt}) { + return i1.MemoryEntityCompanion( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ownerId: ownerId ?? this.ownerId, + type: type ?? this.type, + data: data ?? this.data, + isSaved: isSaved ?? this.isSaved, + memoryAt: memoryAt ?? this.memoryAt, + seenAt: seenAt ?? this.seenAt, + showAt: showAt ?? this.showAt, + hideAt: hideAt ?? this.hideAt, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = i0.Variable(id.value); + } + if (createdAt.present) { + map['created_at'] = i0.Variable(createdAt.value); + } + if (updatedAt.present) { + map['updated_at'] = i0.Variable(updatedAt.value); + } + if (deletedAt.present) { + map['deleted_at'] = i0.Variable(deletedAt.value); + } + if (ownerId.present) { + map['owner_id'] = i0.Variable(ownerId.value); + } + if (type.present) { + map['type'] = i0.Variable( + i1.$MemoryEntityTable.$convertertype.toSql(type.value)); + } + if (data.present) { + map['data'] = i0.Variable(data.value); + } + if (isSaved.present) { + map['is_saved'] = i0.Variable(isSaved.value); + } + if (memoryAt.present) { + map['memory_at'] = i0.Variable(memoryAt.value); + } + if (seenAt.present) { + map['seen_at'] = i0.Variable(seenAt.value); + } + if (showAt.present) { + map['show_at'] = i0.Variable(showAt.value); + } + if (hideAt.present) { + map['hide_at'] = i0.Variable(hideAt.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryEntityCompanion(') + ..write('id: $id, ') + ..write('createdAt: $createdAt, ') + ..write('updatedAt: $updatedAt, ') + ..write('deletedAt: $deletedAt, ') + ..write('ownerId: $ownerId, ') + ..write('type: $type, ') + ..write('data: $data, ') + ..write('isSaved: $isSaved, ') + ..write('memoryAt: $memoryAt, ') + ..write('seenAt: $seenAt, ') + ..write('showAt: $showAt, ') + ..write('hideAt: $hideAt') + ..write(')')) + .toString(); + } +} diff --git a/mobile/lib/infrastructure/entities/memory_asset.entity.dart b/mobile/lib/infrastructure/entities/memory_asset.entity.dart new file mode 100644 index 0000000000..c304b03724 --- /dev/null +++ b/mobile/lib/infrastructure/entities/memory_asset.entity.dart @@ -0,0 +1,17 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/infrastructure/entities/memory.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.dart'; +import 'package:immich_mobile/infrastructure/utils/drift_default.mixin.dart'; + +class MemoryAssetEntity extends Table with DriftDefaultsMixin { + const MemoryAssetEntity(); + + TextColumn get assetId => + text().references(RemoteAssetEntity, #id, onDelete: KeyAction.cascade)(); + + TextColumn get memoryId => + text().references(MemoryEntity, #id, onDelete: KeyAction.cascade)(); + + @override + Set get primaryKey => {assetId, memoryId}; +} diff --git a/mobile/lib/infrastructure/entities/memory_asset.entity.drift.dart b/mobile/lib/infrastructure/entities/memory_asset.entity.drift.dart new file mode 100644 index 0000000000..9253e8bc05 --- /dev/null +++ b/mobile/lib/infrastructure/entities/memory_asset.entity.drift.dart @@ -0,0 +1,550 @@ +// dart format width=80 +// ignore_for_file: type=lint +import 'package:drift/drift.dart' as i0; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart' + as i1; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart' + as i2; +import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart' + as i3; +import 'package:drift/internal/modular.dart' as i4; +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart' + as i5; + +typedef $$MemoryAssetEntityTableCreateCompanionBuilder + = i1.MemoryAssetEntityCompanion Function({ + required String assetId, + required String memoryId, +}); +typedef $$MemoryAssetEntityTableUpdateCompanionBuilder + = i1.MemoryAssetEntityCompanion Function({ + i0.Value assetId, + i0.Value memoryId, +}); + +final class $$MemoryAssetEntityTableReferences extends i0.BaseReferences< + i0.GeneratedDatabase, + i1.$MemoryAssetEntityTable, + i1.MemoryAssetEntityData> { + $$MemoryAssetEntityTableReferences( + super.$_db, super.$_table, super.$_typedResult); + + static i3.$RemoteAssetEntityTable _assetIdTable(i0.GeneratedDatabase db) => + i4.ReadDatabaseContainer(db) + .resultSet('remote_asset_entity') + .createAlias(i0.$_aliasNameGenerator( + i4.ReadDatabaseContainer(db) + .resultSet('memory_asset_entity') + .assetId, + i4.ReadDatabaseContainer(db) + .resultSet('remote_asset_entity') + .id)); + + i3.$$RemoteAssetEntityTableProcessedTableManager get assetId { + final $_column = $_itemColumn('asset_id')!; + + final manager = i3 + .$$RemoteAssetEntityTableTableManager( + $_db, + i4.ReadDatabaseContainer($_db) + .resultSet('remote_asset_entity')) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_assetIdTable($_db)); + if (item == null) return manager; + return i0.ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } + + static i5.$MemoryEntityTable _memoryIdTable(i0.GeneratedDatabase db) => + i4.ReadDatabaseContainer(db) + .resultSet('memory_entity') + .createAlias(i0.$_aliasNameGenerator( + i4.ReadDatabaseContainer(db) + .resultSet('memory_asset_entity') + .memoryId, + i4.ReadDatabaseContainer(db) + .resultSet('memory_entity') + .id)); + + i5.$$MemoryEntityTableProcessedTableManager get memoryId { + final $_column = $_itemColumn('memory_id')!; + + final manager = i5 + .$$MemoryEntityTableTableManager( + $_db, + i4.ReadDatabaseContainer($_db) + .resultSet('memory_entity')) + .filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_memoryIdTable($_db)); + if (item == null) return manager; + return i0.ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } +} + +class $$MemoryAssetEntityTableFilterComposer + extends i0.Composer { + $$MemoryAssetEntityTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i3.$$RemoteAssetEntityTableFilterComposer get assetId { + final i3.$$RemoteAssetEntityTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.assetId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('remote_asset_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i3.$$RemoteAssetEntityTableFilterComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet('remote_asset_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + + i5.$$MemoryEntityTableFilterComposer get memoryId { + final i5.$$MemoryEntityTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.memoryId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$MemoryEntityTableFilterComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryAssetEntityTableOrderingComposer + extends i0.Composer { + $$MemoryAssetEntityTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i3.$$RemoteAssetEntityTableOrderingComposer get assetId { + final i3.$$RemoteAssetEntityTableOrderingComposer composer = + $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.assetId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('remote_asset_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i3.$$RemoteAssetEntityTableOrderingComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet( + 'remote_asset_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + + i5.$$MemoryEntityTableOrderingComposer get memoryId { + final i5.$$MemoryEntityTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.memoryId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$MemoryEntityTableOrderingComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryAssetEntityTableAnnotationComposer + extends i0.Composer { + $$MemoryAssetEntityTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + i3.$$RemoteAssetEntityTableAnnotationComposer get assetId { + final i3.$$RemoteAssetEntityTableAnnotationComposer composer = + $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.assetId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('remote_asset_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i3.$$RemoteAssetEntityTableAnnotationComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet( + 'remote_asset_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + + i5.$$MemoryEntityTableAnnotationComposer get memoryId { + final i5.$$MemoryEntityTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.memoryId, + referencedTable: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + getReferencedColumn: (t) => t.id, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + i5.$$MemoryEntityTableAnnotationComposer( + $db: $db, + $table: i4.ReadDatabaseContainer($db) + .resultSet('memory_entity'), + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } +} + +class $$MemoryAssetEntityTableTableManager extends i0.RootTableManager< + i0.GeneratedDatabase, + i1.$MemoryAssetEntityTable, + i1.MemoryAssetEntityData, + i1.$$MemoryAssetEntityTableFilterComposer, + i1.$$MemoryAssetEntityTableOrderingComposer, + i1.$$MemoryAssetEntityTableAnnotationComposer, + $$MemoryAssetEntityTableCreateCompanionBuilder, + $$MemoryAssetEntityTableUpdateCompanionBuilder, + (i1.MemoryAssetEntityData, i1.$$MemoryAssetEntityTableReferences), + i1.MemoryAssetEntityData, + i0.PrefetchHooks Function({bool assetId, bool memoryId})> { + $$MemoryAssetEntityTableTableManager( + i0.GeneratedDatabase db, i1.$MemoryAssetEntityTable table) + : super(i0.TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + i1.$$MemoryAssetEntityTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => i1 + .$$MemoryAssetEntityTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + i1.$$MemoryAssetEntityTableAnnotationComposer( + $db: db, $table: table), + updateCompanionCallback: ({ + i0.Value assetId = const i0.Value.absent(), + i0.Value memoryId = const i0.Value.absent(), + }) => + i1.MemoryAssetEntityCompanion( + assetId: assetId, + memoryId: memoryId, + ), + createCompanionCallback: ({ + required String assetId, + required String memoryId, + }) => + i1.MemoryAssetEntityCompanion.insert( + assetId: assetId, + memoryId: memoryId, + ), + withReferenceMapper: (p0) => p0 + .map((e) => ( + e.readTable(table), + i1.$$MemoryAssetEntityTableReferences(db, table, e) + )) + .toList(), + prefetchHooksCallback: ({assetId = false, memoryId = false}) { + return i0.PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: < + T extends i0.TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic>>(state) { + if (assetId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.assetId, + referencedTable: + i1.$$MemoryAssetEntityTableReferences._assetIdTable(db), + referencedColumn: i1.$$MemoryAssetEntityTableReferences + ._assetIdTable(db) + .id, + ) as T; + } + if (memoryId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.memoryId, + referencedTable: i1.$$MemoryAssetEntityTableReferences + ._memoryIdTable(db), + referencedColumn: i1.$$MemoryAssetEntityTableReferences + ._memoryIdTable(db) + .id, + ) as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + )); +} + +typedef $$MemoryAssetEntityTableProcessedTableManager + = i0.ProcessedTableManager< + i0.GeneratedDatabase, + i1.$MemoryAssetEntityTable, + i1.MemoryAssetEntityData, + i1.$$MemoryAssetEntityTableFilterComposer, + i1.$$MemoryAssetEntityTableOrderingComposer, + i1.$$MemoryAssetEntityTableAnnotationComposer, + $$MemoryAssetEntityTableCreateCompanionBuilder, + $$MemoryAssetEntityTableUpdateCompanionBuilder, + (i1.MemoryAssetEntityData, i1.$$MemoryAssetEntityTableReferences), + i1.MemoryAssetEntityData, + i0.PrefetchHooks Function({bool assetId, bool memoryId})>; + +class $MemoryAssetEntityTable extends i2.MemoryAssetEntity + with i0.TableInfo<$MemoryAssetEntityTable, i1.MemoryAssetEntityData> { + @override + final i0.GeneratedDatabase attachedDatabase; + final String? _alias; + $MemoryAssetEntityTable(this.attachedDatabase, [this._alias]); + static const i0.VerificationMeta _assetIdMeta = + const i0.VerificationMeta('assetId'); + @override + late final i0.GeneratedColumn assetId = i0.GeneratedColumn( + 'asset_id', aliasedName, false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'REFERENCES remote_asset_entity (id) ON DELETE CASCADE')); + static const i0.VerificationMeta _memoryIdMeta = + const i0.VerificationMeta('memoryId'); + @override + late final i0.GeneratedColumn memoryId = i0.GeneratedColumn( + 'memory_id', aliasedName, false, + type: i0.DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: i0.GeneratedColumn.constraintIsAlways( + 'REFERENCES memory_entity (id) ON DELETE CASCADE')); + @override + List get $columns => [assetId, memoryId]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'memory_asset_entity'; + @override + i0.VerificationContext validateIntegrity( + i0.Insertable instance, + {bool isInserting = false}) { + final context = i0.VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('asset_id')) { + context.handle(_assetIdMeta, + assetId.isAcceptableOrUnknown(data['asset_id']!, _assetIdMeta)); + } else if (isInserting) { + context.missing(_assetIdMeta); + } + if (data.containsKey('memory_id')) { + context.handle(_memoryIdMeta, + memoryId.isAcceptableOrUnknown(data['memory_id']!, _memoryIdMeta)); + } else if (isInserting) { + context.missing(_memoryIdMeta); + } + return context; + } + + @override + Set get $primaryKey => {assetId, memoryId}; + @override + i1.MemoryAssetEntityData map(Map data, + {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return i1.MemoryAssetEntityData( + assetId: attachedDatabase.typeMapping + .read(i0.DriftSqlType.string, data['${effectivePrefix}asset_id'])!, + memoryId: attachedDatabase.typeMapping + .read(i0.DriftSqlType.string, data['${effectivePrefix}memory_id'])!, + ); + } + + @override + $MemoryAssetEntityTable createAlias(String alias) { + return $MemoryAssetEntityTable(attachedDatabase, alias); + } + + @override + bool get withoutRowId => true; + @override + bool get isStrict => true; +} + +class MemoryAssetEntityData extends i0.DataClass + implements i0.Insertable { + final String assetId; + final String memoryId; + const MemoryAssetEntityData({required this.assetId, required this.memoryId}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['asset_id'] = i0.Variable(assetId); + map['memory_id'] = i0.Variable(memoryId); + return map; + } + + factory MemoryAssetEntityData.fromJson(Map json, + {i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return MemoryAssetEntityData( + assetId: serializer.fromJson(json['assetId']), + memoryId: serializer.fromJson(json['memoryId']), + ); + } + @override + Map toJson({i0.ValueSerializer? serializer}) { + serializer ??= i0.driftRuntimeOptions.defaultSerializer; + return { + 'assetId': serializer.toJson(assetId), + 'memoryId': serializer.toJson(memoryId), + }; + } + + i1.MemoryAssetEntityData copyWith({String? assetId, String? memoryId}) => + i1.MemoryAssetEntityData( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + MemoryAssetEntityData copyWithCompanion(i1.MemoryAssetEntityCompanion data) { + return MemoryAssetEntityData( + assetId: data.assetId.present ? data.assetId.value : this.assetId, + memoryId: data.memoryId.present ? data.memoryId.value : this.memoryId, + ); + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityData(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(assetId, memoryId); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is i1.MemoryAssetEntityData && + other.assetId == this.assetId && + other.memoryId == this.memoryId); +} + +class MemoryAssetEntityCompanion + extends i0.UpdateCompanion { + final i0.Value assetId; + final i0.Value memoryId; + const MemoryAssetEntityCompanion({ + this.assetId = const i0.Value.absent(), + this.memoryId = const i0.Value.absent(), + }); + MemoryAssetEntityCompanion.insert({ + required String assetId, + required String memoryId, + }) : assetId = i0.Value(assetId), + memoryId = i0.Value(memoryId); + static i0.Insertable custom({ + i0.Expression? assetId, + i0.Expression? memoryId, + }) { + return i0.RawValuesInsertable({ + if (assetId != null) 'asset_id': assetId, + if (memoryId != null) 'memory_id': memoryId, + }); + } + + i1.MemoryAssetEntityCompanion copyWith( + {i0.Value? assetId, i0.Value? memoryId}) { + return i1.MemoryAssetEntityCompanion( + assetId: assetId ?? this.assetId, + memoryId: memoryId ?? this.memoryId, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (assetId.present) { + map['asset_id'] = i0.Variable(assetId.value); + } + if (memoryId.present) { + map['memory_id'] = i0.Variable(memoryId.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MemoryAssetEntityCompanion(') + ..write('assetId: $assetId, ') + ..write('memoryId: $memoryId') + ..write(')')) + .toString(); + } +} diff --git a/mobile/lib/infrastructure/repositories/db.repository.dart b/mobile/lib/infrastructure/repositories/db.repository.dart index dbe491b035..e71598a999 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.dart @@ -7,6 +7,8 @@ import 'package:immich_mobile/infrastructure/entities/exif.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_album_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/local_asset.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/memory.entity.dart'; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album.entity.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.dart'; @@ -46,6 +48,8 @@ class IsarDatabaseRepository implements IDatabaseRepository { RemoteAlbumEntity, RemoteAlbumAssetEntity, RemoteAlbumUserEntity, + MemoryEntity, + MemoryAssetEntity, ], include: { 'package:immich_mobile/infrastructure/entities/merged_asset.drift', diff --git a/mobile/lib/infrastructure/repositories/db.repository.drift.dart b/mobile/lib/infrastructure/repositories/db.repository.drift.dart index 69fd84b79a..925591def8 100644 --- a/mobile/lib/infrastructure/repositories/db.repository.drift.dart +++ b/mobile/lib/infrastructure/repositories/db.repository.drift.dart @@ -23,9 +23,13 @@ import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity. as i10; import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart' as i11; -import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart' +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart' as i12; -import 'package:drift/internal/modular.dart' as i13; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart' + as i13; +import 'package:immich_mobile/infrastructure/entities/merged_asset.drift.dart' + as i14; +import 'package:drift/internal/modular.dart' as i15; abstract class $Drift extends i0.GeneratedDatabase { $Drift(i0.QueryExecutor e) : super(e); @@ -51,8 +55,11 @@ abstract class $Drift extends i0.GeneratedDatabase { i10.$RemoteAlbumAssetEntityTable(this); late final i11.$RemoteAlbumUserEntityTable remoteAlbumUserEntity = i11.$RemoteAlbumUserEntityTable(this); - i12.MergedAssetDrift get mergedAssetDrift => i13.ReadDatabaseContainer(this) - .accessor(i12.MergedAssetDrift.new); + late final i12.$MemoryEntityTable memoryEntity = i12.$MemoryEntityTable(this); + late final i13.$MemoryAssetEntityTable memoryAssetEntity = + i13.$MemoryAssetEntityTable(this); + i14.MergedAssetDrift get mergedAssetDrift => i15.ReadDatabaseContainer(this) + .accessor(i14.MergedAssetDrift.new); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -71,7 +78,9 @@ abstract class $Drift extends i0.GeneratedDatabase { remoteExifEntity, remoteAlbumEntity, remoteAlbumAssetEntity, - remoteAlbumUserEntity + remoteAlbumUserEntity, + memoryEntity, + memoryAssetEntity ]; @override i0.StreamQueryUpdateRules get streamUpdateRules => @@ -175,6 +184,27 @@ abstract class $Drift extends i0.GeneratedDatabase { kind: i0.UpdateKind.delete), ], ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName('user_entity', + limitUpdateKind: i0.UpdateKind.delete), + result: [ + i0.TableUpdate('memory_entity', kind: i0.UpdateKind.delete), + ], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName('remote_asset_entity', + limitUpdateKind: i0.UpdateKind.delete), + result: [ + i0.TableUpdate('memory_asset_entity', kind: i0.UpdateKind.delete), + ], + ), + i0.WritePropagation( + on: i0.TableUpdateQuery.onTableName('memory_entity', + limitUpdateKind: i0.UpdateKind.delete), + result: [ + i0.TableUpdate('memory_asset_entity', kind: i0.UpdateKind.delete), + ], + ), ], ); @override @@ -208,4 +238,8 @@ class $DriftManager { _db, _db.remoteAlbumAssetEntity); i11.$$RemoteAlbumUserEntityTableTableManager get remoteAlbumUserEntity => i11 .$$RemoteAlbumUserEntityTableTableManager(_db, _db.remoteAlbumUserEntity); + i12.$$MemoryEntityTableTableManager get memoryEntity => + i12.$$MemoryEntityTableTableManager(_db, _db.memoryEntity); + i13.$$MemoryAssetEntityTableTableManager get memoryAssetEntity => + i13.$$MemoryAssetEntityTableTableManager(_db, _db.memoryAssetEntity); } diff --git a/mobile/lib/infrastructure/repositories/memory.repository.dart b/mobile/lib/infrastructure/repositories/memory.repository.dart new file mode 100644 index 0000000000..1f70f9dcd2 --- /dev/null +++ b/mobile/lib/infrastructure/repositories/memory.repository.dart @@ -0,0 +1,37 @@ +import 'package:drift/drift.dart'; +import 'package:immich_mobile/domain/models/memory.model.dart'; +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; + +class DriftMemoryRepository extends DriftDatabaseRepository { + final Drift _db; + const DriftMemoryRepository(this._db) : super(_db); + + Future> getAll(String userId) { + final query = _db.memoryEntity.select() + ..where((e) => e.ownerId.equals(userId)); + + return query.map((memory) { + return memory.toDto(); + }).get(); + } +} + +extension on MemoryEntityData { + Memory toDto() { + return Memory( + id: id, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + ownerId: ownerId, + type: type, + data: MemoryData.fromJson(data), + isSaved: isSaved, + memoryAt: memoryAt, + seenAt: seenAt, + showAt: showAt, + hideAt: hideAt, + ); + } +} diff --git a/mobile/lib/infrastructure/repositories/sync_api.repository.dart b/mobile/lib/infrastructure/repositories/sync_api.repository.dart index ccc79fa818..99199a7fc6 100644 --- a/mobile/lib/infrastructure/repositories/sync_api.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_api.repository.dart @@ -52,6 +52,8 @@ class SyncApiRepository { SyncRequestType.albumAssetsV1, SyncRequestType.albumAssetExifsV1, SyncRequestType.albumToAssetsV1, + SyncRequestType.memoriesV1, + SyncRequestType.memoryToAssetsV1, ], ).toJson(), ); @@ -157,6 +159,10 @@ const _kResponseMap = { SyncEntityType.albumToAssetBackfillV1: SyncAlbumToAssetV1.fromJson, SyncEntityType.albumToAssetDeleteV1: SyncAlbumToAssetDeleteV1.fromJson, SyncEntityType.syncAckV1: _SyncAckV1.fromJson, + SyncEntityType.memoryV1: SyncMemoryV1.fromJson, + SyncEntityType.memoryDeleteV1: SyncMemoryDeleteV1.fromJson, + SyncEntityType.memoryToAssetV1: SyncMemoryAssetV1.fromJson, + SyncEntityType.memoryToAssetDeleteV1: SyncMemoryAssetDeleteV1.fromJson, }; class _SyncAckV1 { diff --git a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart index 015e09d663..b88083aa02 100644 --- a/mobile/lib/infrastructure/repositories/sync_stream.repository.dart +++ b/mobile/lib/infrastructure/repositories/sync_stream.repository.dart @@ -1,12 +1,17 @@ +import 'dart:convert'; + import 'package:drift/drift.dart'; import 'package:immich_mobile/domain/models/album/album.model.dart'; import 'package:immich_mobile/domain/models/asset/base_asset.model.dart'; +import 'package:immich_mobile/domain/models/memory.model.dart'; import 'package:immich_mobile/infrastructure/entities/exif.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/memory_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/partner.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album_asset.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_album_user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/remote_asset.entity.drift.dart'; +import 'package:immich_mobile/infrastructure/entities/memory.entity.drift.dart'; import 'package:immich_mobile/infrastructure/entities/user.entity.drift.dart'; import 'package:immich_mobile/infrastructure/repositories/db.repository.dart'; import 'package:logging/logging.dart'; @@ -64,8 +69,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: SyncPartnerDeleteV1', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: SyncPartnerDeleteV1', error, stackTrace); rethrow; } } @@ -87,8 +92,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: SyncPartnerV1', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: SyncPartnerV1', error, stackTrace); rethrow; } } @@ -98,10 +103,11 @@ class SyncStreamRepository extends DriftDatabaseRepository { String debugLabel = 'user', }) async { try { - await _db.remoteAssetEntity - .deleteWhere((row) => row.id.isIn(data.map((e) => e.assetId))); - } catch (e, s) { - _logger.severe('Error: deleteAssetsV1 - $debugLabel', e, s); + await _db.remoteAssetEntity.deleteWhere( + (row) => row.id.isIn(data.map((error) => error.assetId)), + ); + } catch (error, stackTrace) { + _logger.severe('Error: deleteAssetsV1 - $debugLabel', error, stackTrace); rethrow; } } @@ -136,8 +142,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: updateAssetsV1 - $debugLabel', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: updateAssetsV1 - $debugLabel', error, stackTrace); rethrow; } } @@ -180,18 +186,23 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: updateAssetsExifV1 - $debugLabel', e, s); + } catch (error, stackTrace) { + _logger.severe( + 'Error: updateAssetsExifV1 - $debugLabel', + error, + stackTrace, + ); rethrow; } } Future deleteAlbumsV1(Iterable data) async { try { - await _db.remoteAlbumEntity - .deleteWhere((row) => row.id.isIn(data.map((e) => e.albumId))); - } catch (e, s) { - _logger.severe('Error: deleteAlbumsV1', e, s); + await _db.remoteAlbumEntity.deleteWhere( + (row) => row.id.isIn(data.map((e) => e.albumId)), + ); + } catch (error, stackTrace) { + _logger.severe('Error: deleteAlbumsV1', error, stackTrace); rethrow; } } @@ -218,8 +229,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: updateAlbumsV1', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: updateAlbumsV1', error, stackTrace); rethrow; } } @@ -237,8 +248,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: deleteAlbumUsersV1', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: deleteAlbumUsersV1', error, stackTrace); rethrow; } } @@ -264,8 +275,12 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: updateAlbumUsersV1 - $debugLabel', e, s); + } catch (error, stackTrace) { + _logger.severe( + 'Error: updateAlbumUsersV1 - $debugLabel', + error, + stackTrace, + ); rethrow; } } @@ -285,8 +300,8 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: deleteAlbumToAssetsV1', e, s); + } catch (error, stackTrace) { + _logger.severe('Error: deleteAlbumToAssetsV1', error, stackTrace); rethrow; } } @@ -310,8 +325,96 @@ class SyncStreamRepository extends DriftDatabaseRepository { ); } }); - } catch (e, s) { - _logger.severe('Error: updateAlbumToAssetsV1 - $debugLabel', e, s); + } catch (error, stackTrace) { + _logger.severe( + 'Error: updateAlbumToAssetsV1 - $debugLabel', + error, + stackTrace, + ); + rethrow; + } + } + + Future updateMemoriesV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final memory in data) { + final companion = MemoryEntityCompanion( + createdAt: Value(memory.createdAt), + deletedAt: Value(memory.deletedAt), + ownerId: Value(memory.ownerId), + type: Value(memory.type.toMemoryType()), + data: Value(jsonEncode(memory.data)), + isSaved: Value(memory.isSaved), + memoryAt: Value(memory.memoryAt), + seenAt: Value.absentIfNull(memory.seenAt), + showAt: Value.absentIfNull(memory.showAt), + hideAt: Value.absentIfNull(memory.hideAt), + ); + + batch.insert( + _db.memoryEntity, + companion.copyWith(id: Value(memory.id)), + onConflict: DoUpdate((_) => companion), + ); + } + }); + } catch (error, stackTrace) { + _logger.severe('Error: updateMemoriesV1', error, stackTrace); + rethrow; + } + } + + Future deleteMemoriesV1(Iterable data) async { + try { + await _db.memoryEntity.deleteWhere( + (row) => row.id.isIn(data.map((e) => e.memoryId)), + ); + } catch (error, stackTrace) { + _logger.severe('Error: deleteMemoriesV1', error, stackTrace); + rethrow; + } + } + + Future updateMemoryAssetsV1(Iterable data) async { + try { + await _db.batch((batch) { + for (final asset in data) { + final companion = MemoryAssetEntityCompanion( + memoryId: Value(asset.memoryId), + assetId: Value(asset.assetId), + ); + + batch.insert( + _db.memoryAssetEntity, + companion, + onConflict: DoNothing(), + ); + } + }); + } catch (error, stackTrace) { + _logger.severe('Error: updateMemoryAssetsV1', error, stackTrace); + rethrow; + } + } + + Future deleteMemoryAssetsV1( + Iterable data, + ) async { + try { + await _db.batch((batch) { + for (final asset in data) { + batch.delete( + _db.memoryAssetEntity, + MemoryAssetEntityCompanion( + memoryId: Value(asset.memoryId), + assetId: Value(asset.assetId), + ), + ); + } + }); + } catch (error, stackTrace) { + _logger.severe('Error: deleteMemoryAssetsV1', error, stackTrace); rethrow; } } @@ -335,6 +438,13 @@ extension on AssetOrder { }; } +extension on MemoryType { + MemoryTypeEnum toMemoryType() => switch (this) { + MemoryType.onThisDay => MemoryTypeEnum.onThisDay, + _ => throw Exception('Unknown MemoryType value: $this'), + }; +} + extension on api.AlbumUserRole { AlbumUserRole toAlbumUserRole() => switch (this) { api.AlbumUserRole.editor => AlbumUserRole.editor, @@ -357,7 +467,7 @@ extension on String { Duration? toDuration() { try { final parts = split(':') - .map((e) => double.parse(e).toInt()) + .map((error) => double.parse(error).toInt()) .toList(growable: false); return Duration(hours: parts[0], minutes: parts[1], seconds: parts[2]); diff --git a/mobile/lib/presentation/pages/dev/media_stat.page.dart b/mobile/lib/presentation/pages/dev/media_stat.page.dart index 10d09f8de5..f0a648fd5a 100644 --- a/mobile/lib/presentation/pages/dev/media_stat.page.dart +++ b/mobile/lib/presentation/pages/dev/media_stat.page.dart @@ -154,6 +154,14 @@ final _remoteStats = [ name: 'Remote Albums', load: (db) => db.managers.remoteAlbumEntity.count(), ), + _Stat( + name: 'Memories', + load: (db) => db.managers.memoryEntity.count(), + ), + _Stat( + name: 'Memories Assets', + load: (db) => db.managers.memoryAssetEntity.count(), + ), ]; @RoutePage() diff --git a/mobile/lib/providers/memory.provider.dart b/mobile/lib/providers/memory.provider.dart index aed546002d..37f84dca93 100644 --- a/mobile/lib/providers/memory.provider.dart +++ b/mobile/lib/providers/memory.provider.dart @@ -1,5 +1,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:immich_mobile/infrastructure/repositories/memory.repository.dart'; import 'package:immich_mobile/models/memories/memory.model.dart'; +import 'package:immich_mobile/providers/infrastructure/db.provider.dart'; import 'package:immich_mobile/services/memory.service.dart'; final memoryFutureProvider = @@ -8,3 +10,7 @@ final memoryFutureProvider = return await service.getMemoryLane(); }); + +final driftMemoryProvider = Provider( + (ref) => DriftMemoryRepository(ref.watch(driftProvider)), +); diff --git a/mobile/test/domain/services/sync_stream_service_test.dart b/mobile/test/domain/services/sync_stream_service_test.dart index a0b61bcaff..28288422fd 100644 --- a/mobile/test/domain/services/sync_stream_service_test.dart +++ b/mobile/test/domain/services/sync_stream_service_test.dart @@ -81,6 +81,14 @@ void main() { debugLabel: any(named: 'debugLabel'), ), ).thenAnswer(successHandler); + when(() => mockSyncStreamRepo.updateMemoriesV1(any())) + .thenAnswer(successHandler); + when(() => mockSyncStreamRepo.deleteMemoriesV1(any())) + .thenAnswer(successHandler); + when(() => mockSyncStreamRepo.updateMemoryAssetsV1(any())) + .thenAnswer(successHandler); + when(() => mockSyncStreamRepo.deleteMemoryAssetsV1(any())) + .thenAnswer(successHandler); sut = SyncStreamService( syncApiRepository: mockSyncApiRepo, @@ -227,5 +235,94 @@ void main() { verify(() => mockSyncApiRepo.ack(["2"])).called(1); }, ); + + test("processes memory sync events successfully", () async { + final events = [ + SyncStreamStub.memoryV1, + SyncStreamStub.memoryDeleteV1, + SyncStreamStub.memoryToAssetV1, + SyncStreamStub.memoryToAssetDeleteV1, + ]; + + await simulateEvents(events); + + verifyInOrder([ + () => mockSyncStreamRepo.updateMemoriesV1(any()), + () => mockSyncApiRepo.ack(["5"]), + () => mockSyncStreamRepo.deleteMemoriesV1(any()), + () => mockSyncApiRepo.ack(["6"]), + () => mockSyncStreamRepo.updateMemoryAssetsV1(any()), + () => mockSyncApiRepo.ack(["7"]), + () => mockSyncStreamRepo.deleteMemoryAssetsV1(any()), + () => mockSyncApiRepo.ack(["8"]), + ]); + verifyNever(() => mockAbortCallbackWrapper()); + }); + + test("processes mixed memory and user events in correct order", () async { + final events = [ + SyncStreamStub.memoryDeleteV1, + SyncStreamStub.userV1Admin, + SyncStreamStub.memoryToAssetV1, + SyncStreamStub.memoryV1, + ]; + + await simulateEvents(events); + + verifyInOrder([ + () => mockSyncStreamRepo.deleteMemoriesV1(any()), + () => mockSyncApiRepo.ack(["6"]), + () => mockSyncStreamRepo.updateUsersV1(any()), + () => mockSyncApiRepo.ack(["1"]), + () => mockSyncStreamRepo.updateMemoryAssetsV1(any()), + () => mockSyncApiRepo.ack(["7"]), + () => mockSyncStreamRepo.updateMemoriesV1(any()), + () => mockSyncApiRepo.ack(["5"]), + ]); + verifyNever(() => mockAbortCallbackWrapper()); + }); + + test("handles memory sync failure gracefully", () async { + when(() => mockSyncStreamRepo.updateMemoriesV1(any())) + .thenThrow(Exception("Memory sync failed")); + + final events = [ + SyncStreamStub.memoryV1, + SyncStreamStub.userV1Admin, + ]; + + expect( + () async => await simulateEvents(events), + throwsA(isA()), + ); + }); + + test("processes memory asset events with correct data types", () async { + final events = [SyncStreamStub.memoryToAssetV1]; + + await simulateEvents(events); + + verify(() => mockSyncStreamRepo.updateMemoryAssetsV1(any())).called(1); + verify(() => mockSyncApiRepo.ack(["7"])).called(1); + }); + + test("processes memory delete events with correct data types", () async { + final events = [SyncStreamStub.memoryDeleteV1]; + + await simulateEvents(events); + + verify(() => mockSyncStreamRepo.deleteMemoriesV1(any())).called(1); + verify(() => mockSyncApiRepo.ack(["6"])).called(1); + }); + + test("processes memory create/update events with correct data types", + () async { + final events = [SyncStreamStub.memoryV1]; + + await simulateEvents(events); + + verify(() => mockSyncStreamRepo.updateMemoriesV1(any())).called(1); + verify(() => mockSyncApiRepo.ack(["5"])).called(1); + }); }); } diff --git a/mobile/test/fixtures/sync_stream.stub.dart b/mobile/test/fixtures/sync_stream.stub.dart index ba97f1434a..de2d58bc9d 100644 --- a/mobile/test/fixtures/sync_stream.stub.dart +++ b/mobile/test/fixtures/sync_stream.stub.dart @@ -42,4 +42,47 @@ abstract final class SyncStreamStub { data: SyncPartnerDeleteV1(sharedById: "3", sharedWithId: "4"), ack: "4", ); + + static final memoryV1 = SyncEvent( + type: SyncEntityType.memoryV1, + data: SyncMemoryV1( + createdAt: DateTime(2023, 1, 1), + data: {"year": 2023, "title": "Test Memory"}, + deletedAt: null, + hideAt: null, + id: "memory-1", + isSaved: false, + memoryAt: DateTime(2023, 1, 1), + ownerId: "user-1", + seenAt: null, + showAt: DateTime(2023, 1, 1), + type: MemoryType.onThisDay, + updatedAt: DateTime(2023, 1, 1), + ), + ack: "5", + ); + + static final memoryDeleteV1 = SyncEvent( + type: SyncEntityType.memoryDeleteV1, + data: SyncMemoryDeleteV1(memoryId: "memory-2"), + ack: "6", + ); + + static final memoryToAssetV1 = SyncEvent( + type: SyncEntityType.memoryToAssetV1, + data: SyncMemoryAssetV1( + assetId: "asset-1", + memoryId: "memory-1", + ), + ack: "7", + ); + + static final memoryToAssetDeleteV1 = SyncEvent( + type: SyncEntityType.memoryToAssetDeleteV1, + data: SyncMemoryAssetDeleteV1( + assetId: "asset-2", + memoryId: "memory-1", + ), + ack: "8", + ); }