diff --git a/lib/src/database/daos/mediafiles.dao.dart b/lib/src/database/daos/mediafiles.dao.dart index b1e09d9..dff6008 100644 --- a/lib/src/database/daos/mediafiles.dao.dart +++ b/lib/src/database/daos/mediafiles.dao.dart @@ -100,6 +100,14 @@ class MediaFilesDao extends DatabaseAccessor .get(); } + Future> getAllNonHashedStoredMediaFiles() async { + return (select(mediaFiles) + ..where( + (t) => t.stored.equals(true) & t.storedFileHash.isNull(), + )) + .get(); + } + Future> getAllMediaFilesPendingUpload() async { return (select(mediaFiles) ..where( @@ -111,7 +119,10 @@ class MediaFilesDao extends DatabaseAccessor } Stream> watchAllStoredMediaFiles() { - return (select(mediaFiles)..where((t) => t.stored.equals(true))).watch(); + final query = (select(mediaFiles)..where((t) => t.stored.equals(true))) + .join([]) + ..groupBy([mediaFiles.storedFileHash]); + return query.map((row) => row.readTable(mediaFiles)).watch(); } Stream> watchNewestMediaFiles() { diff --git a/lib/src/database/schemas/twonly_db/drift_schema_v5.json b/lib/src/database/schemas/twonly_db/drift_schema_v5.json index ef4e377..3a68c21 100644 --- a/lib/src/database/schemas/twonly_db/drift_schema_v5.json +++ b/lib/src/database/schemas/twonly_db/drift_schema_v5.json @@ -1 +1 @@ -{"_meta":{"description":"This file contains a serialized version of schema entities for drift.","version":"1.2.0"},"options":{"store_date_time_values_as_text":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"contacts","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"username","getter_name":"username","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"display_name","getter_name":"displayName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"nick_name","getter_name":"nickName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"avatar_svg_compressed","getter_name":"avatarSvgCompressed","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_profile_counter","getter_name":"senderProfileCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"accepted","getter_name":"accepted","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"accepted\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"accepted\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_by_user","getter_name":"deletedByUser","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"deleted_by_user\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"deleted_by_user\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"requested","getter_name":"requested","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"requested\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"requested\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"blocked","getter_name":"blocked","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"blocked\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"blocked\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"verified","getter_name":"verified","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"verified\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"verified\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"account_deleted","getter_name":"accountDeleted","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"account_deleted\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"account_deleted\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["user_id"]}},{"id":1,"references":[],"type":"table","data":{"name":"groups","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_group_admin","getter_name":"isGroupAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_group_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_group_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"is_direct_chat","getter_name":"isDirectChat","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_direct_chat\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_direct_chat\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"pinned","getter_name":"pinned","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"pinned\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"pinned\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"archived","getter_name":"archived","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"archived\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"archived\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"joined_group","getter_name":"joinedGroup","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"joined_group\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"joined_group\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"left_group","getter_name":"leftGroup","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"left_group\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"left_group\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_content","getter_name":"deletedContent","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"deleted_content\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"deleted_content\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"state_version_id","getter_name":"stateVersionId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"state_encryption_key","getter_name":"stateEncryptionKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"my_group_private_key","getter_name":"myGroupPrivateKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_name","getter_name":"groupName","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"draft_message","getter_name":"draftMessage","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"total_media_counter","getter_name":"totalMediaCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"also_best_friend","getter_name":"alsoBestFriend","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"also_best_friend\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"also_best_friend\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"delete_messages_after_milliseconds","getter_name":"deleteMessagesAfterMilliseconds","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('86400000')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]},{"name":"last_message_send","getter_name":"lastMessageSend","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message_received","getter_name":"lastMessageReceived","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_flame_counter_change","getter_name":"lastFlameCounterChange","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_flame_sync","getter_name":"lastFlameSync","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"flame_counter","getter_name":"flameCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"max_flame_counter","getter_name":"maxFlameCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"max_flame_counter_from","getter_name":"maxFlameCounterFrom","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message_exchange","getter_name":"lastMessageExchange","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_id"]}},{"id":2,"references":[],"type":"table","data":{"name":"media_files","was_declared_in_moor":false,"columns":[{"name":"media_id","getter_name":"mediaId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MediaType.values)","dart_type_name":"MediaType"}},{"name":"upload_state","getter_name":"uploadState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(UploadState.values)","dart_type_name":"UploadState"}},{"name":"download_state","getter_name":"downloadState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(DownloadState.values)","dart_type_name":"DownloadState"}},{"name":"requires_authentication","getter_name":"requiresAuthentication","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"requires_authentication\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"requires_authentication\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"stored","getter_name":"stored","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"stored\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"stored\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"is_draft_media","getter_name":"isDraftMedia","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_draft_media\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_draft_media\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"reupload_requested_by","getter_name":"reuploadRequestedBy","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"IntListTypeConverter()","dart_type_name":"List"}},{"name":"display_limit_in_milliseconds","getter_name":"displayLimitInMilliseconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"remove_audio","getter_name":"removeAudio","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"remove_audio\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"remove_audio\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"download_token","getter_name":"downloadToken","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_key","getter_name":"encryptionKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_mac","getter_name":"encryptionMac","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_nonce","getter_name":"encryptionNonce","moor_type":"blob","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["media_id"]}},{"id":3,"references":[1,0,2],"type":"table","data":{"name":"messages","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_id","getter_name":"senderId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MessageType.values)","dart_type_name":"MessageType"}},{"name":"content","getter_name":"content","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"media_id","getter_name":"mediaId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES media_files (media_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES media_files (media_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"media_files","column":"media_id"},"initially_deferred":false,"on_update":null,"on_delete":"setNull"}}]},{"name":"media_stored","getter_name":"mediaStored","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"media_stored\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"media_stored\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"media_reopened","getter_name":"mediaReopened","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"media_reopened\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"media_reopened\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"download_token","getter_name":"downloadToken","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quotes_message_id","getter_name":"quotesMessageId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_deleted_from_sender","getter_name":"isDeletedFromSender","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_deleted_from_sender\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_deleted_from_sender\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"opened_at","getter_name":"openedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"opened_by_all","getter_name":"openedByAll","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]},{"name":"modified_at","getter_name":"modifiedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_user","getter_name":"ackByUser","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_server","getter_name":"ackByServer","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"message_histories","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"content","getter_name":"content","moor_type":"string","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":5,"references":[3,0],"type":"table","data":{"name":"reactions","was_declared_in_moor":false,"columns":[{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"emoji","getter_name":"emoji","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_id","getter_name":"senderId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id","sender_id","emoji"]}},{"id":6,"references":[1,0],"type":"table","data":{"name":"group_members","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"member_state","getter_name":"memberState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MemberState.values)","dart_type_name":"MemberState"}},{"name":"group_public_key","getter_name":"groupPublicKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message","getter_name":"lastMessage","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_id","contact_id"]}},{"id":7,"references":[0,3],"type":"table","data":{"name":"receipts","was_declared_in_moor":false,"columns":[{"name":"receipt_id","getter_name":"receiptId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message","getter_name":"message","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"contact_will_sends_receipt","getter_name":"contactWillSendsReceipt","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"contact_will_sends_receipt\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"contact_will_sends_receipt\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"mark_for_retry","getter_name":"markForRetry","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_server_at","getter_name":"ackByServerAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"retry_count","getter_name":"retryCount","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"last_retry","getter_name":"lastRetry","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["receipt_id"]}},{"id":8,"references":[],"type":"table","data":{"name":"received_receipts","was_declared_in_moor":false,"columns":[{"name":"receipt_id","getter_name":"receiptId","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["receipt_id"]}},{"id":9,"references":[],"type":"table","data":{"name":"signal_identity_key_stores","was_declared_in_moor":false,"columns":[{"name":"device_id","getter_name":"deviceId","moor_type":"int","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":"identity_key","getter_name":"identityKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["device_id","name"]}},{"id":10,"references":[],"type":"table","data":{"name":"signal_pre_key_stores","was_declared_in_moor":false,"columns":[{"name":"pre_key_id","getter_name":"preKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"pre_key","getter_name":"preKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["pre_key_id"]}},{"id":11,"references":[],"type":"table","data":{"name":"signal_sender_key_stores","was_declared_in_moor":false,"columns":[{"name":"sender_key_name","getter_name":"senderKeyName","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_key","getter_name":"senderKey","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["sender_key_name"]}},{"id":12,"references":[],"type":"table","data":{"name":"signal_session_stores","was_declared_in_moor":false,"columns":[{"name":"device_id","getter_name":"deviceId","moor_type":"int","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":"session_record","getter_name":"sessionRecord","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["device_id","name"]}},{"id":13,"references":[0],"type":"table","data":{"name":"signal_contact_pre_keys","was_declared_in_moor":false,"columns":[{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"pre_key_id","getter_name":"preKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"pre_key","getter_name":"preKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["contact_id","pre_key_id"]}},{"id":14,"references":[0],"type":"table","data":{"name":"signal_contact_signed_pre_keys","was_declared_in_moor":false,"columns":[{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"signed_pre_key_id","getter_name":"signedPreKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"signed_pre_key","getter_name":"signedPreKey","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"signed_pre_key_signature","getter_name":"signedPreKeySignature","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["contact_id"]}},{"id":15,"references":[3],"type":"table","data":{"name":"message_actions","was_declared_in_moor":false,"columns":[{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MessageActionType.values)","dart_type_name":"MessageActionType"}},{"name":"action_at","getter_name":"actionAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id","contact_id","type"]}},{"id":16,"references":[1,0],"type":"table","data":{"name":"group_histories","was_declared_in_moor":false,"columns":[{"name":"group_history_id","getter_name":"groupHistoryId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"affected_contact_id","getter_name":"affectedContactId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"old_group_name","getter_name":"oldGroupName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"new_group_name","getter_name":"newGroupName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"new_delete_messages_after_milliseconds","getter_name":"newDeleteMessagesAfterMilliseconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(GroupActionType.values)","dart_type_name":"GroupActionType"}},{"name":"action_at","getter_name":"actionAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_history_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":false},"entities":[{"id":0,"references":[],"type":"table","data":{"name":"contacts","was_declared_in_moor":false,"columns":[{"name":"user_id","getter_name":"userId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"username","getter_name":"username","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"display_name","getter_name":"displayName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"nick_name","getter_name":"nickName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"avatar_svg_compressed","getter_name":"avatarSvgCompressed","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_profile_counter","getter_name":"senderProfileCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"accepted","getter_name":"accepted","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"accepted\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"accepted\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_by_user","getter_name":"deletedByUser","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"deleted_by_user\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"deleted_by_user\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"requested","getter_name":"requested","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"requested\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"requested\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"blocked","getter_name":"blocked","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"blocked\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"blocked\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"verified","getter_name":"verified","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"verified\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"verified\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"account_deleted","getter_name":"accountDeleted","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"account_deleted\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"account_deleted\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["user_id"]}},{"id":1,"references":[],"type":"table","data":{"name":"groups","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_group_admin","getter_name":"isGroupAdmin","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_group_admin\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_group_admin\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"is_direct_chat","getter_name":"isDirectChat","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_direct_chat\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_direct_chat\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"pinned","getter_name":"pinned","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"pinned\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"pinned\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"archived","getter_name":"archived","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"archived\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"archived\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"joined_group","getter_name":"joinedGroup","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"joined_group\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"joined_group\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"left_group","getter_name":"leftGroup","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"left_group\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"left_group\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"deleted_content","getter_name":"deletedContent","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"deleted_content\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"deleted_content\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"state_version_id","getter_name":"stateVersionId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"state_encryption_key","getter_name":"stateEncryptionKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"my_group_private_key","getter_name":"myGroupPrivateKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_name","getter_name":"groupName","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"draft_message","getter_name":"draftMessage","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"total_media_counter","getter_name":"totalMediaCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"also_best_friend","getter_name":"alsoBestFriend","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"also_best_friend\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"also_best_friend\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"delete_messages_after_milliseconds","getter_name":"deleteMessagesAfterMilliseconds","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('86400000')","default_client_dart":null,"dsl_features":[]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]},{"name":"last_message_send","getter_name":"lastMessageSend","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message_received","getter_name":"lastMessageReceived","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_flame_counter_change","getter_name":"lastFlameCounterChange","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_flame_sync","getter_name":"lastFlameSync","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"flame_counter","getter_name":"flameCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"max_flame_counter","getter_name":"maxFlameCounter","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"max_flame_counter_from","getter_name":"maxFlameCounterFrom","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message_exchange","getter_name":"lastMessageExchange","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_id"]}},{"id":2,"references":[],"type":"table","data":{"name":"media_files","was_declared_in_moor":false,"columns":[{"name":"media_id","getter_name":"mediaId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MediaType.values)","dart_type_name":"MediaType"}},{"name":"upload_state","getter_name":"uploadState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(UploadState.values)","dart_type_name":"UploadState"}},{"name":"download_state","getter_name":"downloadState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(DownloadState.values)","dart_type_name":"DownloadState"}},{"name":"requires_authentication","getter_name":"requiresAuthentication","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"requires_authentication\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"requires_authentication\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"stored","getter_name":"stored","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"stored\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"stored\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"is_draft_media","getter_name":"isDraftMedia","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_draft_media\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_draft_media\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"reupload_requested_by","getter_name":"reuploadRequestedBy","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"IntListTypeConverter()","dart_type_name":"List"}},{"name":"display_limit_in_milliseconds","getter_name":"displayLimitInMilliseconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"remove_audio","getter_name":"removeAudio","moor_type":"bool","nullable":true,"customConstraints":null,"defaultConstraints":"CHECK (\"remove_audio\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"remove_audio\" IN (0, 1))"},"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"download_token","getter_name":"downloadToken","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_key","getter_name":"encryptionKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_mac","getter_name":"encryptionMac","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"encryption_nonce","getter_name":"encryptionNonce","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"stored_file_hash","getter_name":"storedFileHash","moor_type":"blob","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["media_id"]}},{"id":3,"references":[1,0,2],"type":"table","data":{"name":"messages","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_id","getter_name":"senderId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MessageType.values)","dart_type_name":"MessageType"}},{"name":"content","getter_name":"content","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"media_id","getter_name":"mediaId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES media_files (media_id) ON DELETE SET NULL","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES media_files (media_id) ON DELETE SET NULL"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"media_files","column":"media_id"},"initially_deferred":false,"on_update":null,"on_delete":"setNull"}}]},{"name":"media_stored","getter_name":"mediaStored","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"media_stored\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"media_stored\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"media_reopened","getter_name":"mediaReopened","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"media_reopened\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"media_reopened\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"download_token","getter_name":"downloadToken","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"quotes_message_id","getter_name":"quotesMessageId","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"is_deleted_from_sender","getter_name":"isDeletedFromSender","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"is_deleted_from_sender\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"is_deleted_from_sender\" IN (0, 1))"},"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"opened_at","getter_name":"openedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"opened_by_all","getter_name":"openedByAll","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]},{"name":"modified_at","getter_name":"modifiedAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_user","getter_name":"ackByUser","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_server","getter_name":"ackByServer","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id"]}},{"id":4,"references":[3],"type":"table","data":{"name":"message_histories","was_declared_in_moor":false,"columns":[{"name":"id","getter_name":"id","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"PRIMARY KEY AUTOINCREMENT","dialectAwareDefaultConstraints":{"sqlite":"PRIMARY KEY AUTOINCREMENT"},"default_dart":null,"default_client_dart":null,"dsl_features":["auto-increment"]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"content","getter_name":"content","moor_type":"string","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["id"]}},{"id":5,"references":[3,0],"type":"table","data":{"name":"reactions","was_declared_in_moor":false,"columns":[{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"emoji","getter_name":"emoji","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_id","getter_name":"senderId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"created_at","getter_name":"createdAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id","sender_id","emoji"]}},{"id":6,"references":[1,0],"type":"table","data":{"name":"group_members","was_declared_in_moor":false,"columns":[{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"member_state","getter_name":"memberState","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MemberState.values)","dart_type_name":"MemberState"}},{"name":"group_public_key","getter_name":"groupPublicKey","moor_type":"blob","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"last_message","getter_name":"lastMessage","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_id","contact_id"]}},{"id":7,"references":[0,3],"type":"table","data":{"name":"receipts","was_declared_in_moor":false,"columns":[{"name":"receipt_id","getter_name":"receiptId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"message","getter_name":"message","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"contact_will_sends_receipt","getter_name":"contactWillSendsReceipt","moor_type":"bool","nullable":false,"customConstraints":null,"defaultConstraints":"CHECK (\"contact_will_sends_receipt\" IN (0, 1))","dialectAwareDefaultConstraints":{"sqlite":"CHECK (\"contact_will_sends_receipt\" IN (0, 1))"},"default_dart":"const CustomExpression('1')","default_client_dart":null,"dsl_features":[]},{"name":"mark_for_retry","getter_name":"markForRetry","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"ack_by_server_at","getter_name":"ackByServerAt","moor_type":"dateTime","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"retry_count","getter_name":"retryCount","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('0')","default_client_dart":null,"dsl_features":[]},{"name":"last_retry","getter_name":"lastRetry","moor_type":"dateTime","nullable":true,"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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["receipt_id"]}},{"id":8,"references":[],"type":"table","data":{"name":"received_receipts","was_declared_in_moor":false,"columns":[{"name":"receipt_id","getter_name":"receiptId","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["receipt_id"]}},{"id":9,"references":[],"type":"table","data":{"name":"signal_identity_key_stores","was_declared_in_moor":false,"columns":[{"name":"device_id","getter_name":"deviceId","moor_type":"int","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":"identity_key","getter_name":"identityKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["device_id","name"]}},{"id":10,"references":[],"type":"table","data":{"name":"signal_pre_key_stores","was_declared_in_moor":false,"columns":[{"name":"pre_key_id","getter_name":"preKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"pre_key","getter_name":"preKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["pre_key_id"]}},{"id":11,"references":[],"type":"table","data":{"name":"signal_sender_key_stores","was_declared_in_moor":false,"columns":[{"name":"sender_key_name","getter_name":"senderKeyName","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"sender_key","getter_name":"senderKey","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["sender_key_name"]}},{"id":12,"references":[],"type":"table","data":{"name":"signal_session_stores","was_declared_in_moor":false,"columns":[{"name":"device_id","getter_name":"deviceId","moor_type":"int","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":"session_record","getter_name":"sessionRecord","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["device_id","name"]}},{"id":13,"references":[0],"type":"table","data":{"name":"signal_contact_pre_keys","was_declared_in_moor":false,"columns":[{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"pre_key_id","getter_name":"preKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"pre_key","getter_name":"preKey","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["contact_id","pre_key_id"]}},{"id":14,"references":[0],"type":"table","data":{"name":"signal_contact_signed_pre_keys","was_declared_in_moor":false,"columns":[{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"signed_pre_key_id","getter_name":"signedPreKeyId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"signed_pre_key","getter_name":"signedPreKey","moor_type":"blob","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"signed_pre_key_signature","getter_name":"signedPreKeySignature","moor_type":"blob","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('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["contact_id"]}},{"id":15,"references":[3],"type":"table","data":{"name":"message_actions","was_declared_in_moor":false,"columns":[{"name":"message_id","getter_name":"messageId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES messages (message_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES messages (message_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"messages","column":"message_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(MessageActionType.values)","dart_type_name":"MessageActionType"}},{"name":"action_at","getter_name":"actionAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["message_id","contact_id","type"]}},{"id":16,"references":[1,0],"type":"table","data":{"name":"group_histories","was_declared_in_moor":false,"columns":[{"name":"group_history_id","getter_name":"groupHistoryId","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"group_id","getter_name":"groupId","moor_type":"string","nullable":false,"customConstraints":null,"defaultConstraints":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES \"groups\" (group_id) ON DELETE CASCADE"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"groups","column":"group_id"},"initially_deferred":false,"on_update":null,"on_delete":"cascade"}}]},{"name":"contact_id","getter_name":"contactId","moor_type":"int","nullable":true,"customConstraints":null,"defaultConstraints":"REFERENCES contacts (user_id)","dialectAwareDefaultConstraints":{"sqlite":"REFERENCES contacts (user_id)"},"default_dart":null,"default_client_dart":null,"dsl_features":[{"foreign_key":{"to":{"table":"contacts","column":"user_id"},"initially_deferred":false,"on_update":null,"on_delete":null}}]},{"name":"affected_contact_id","getter_name":"affectedContactId","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"old_group_name","getter_name":"oldGroupName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"new_group_name","getter_name":"newGroupName","moor_type":"string","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"new_delete_messages_after_milliseconds","getter_name":"newDeleteMessagesAfterMilliseconds","moor_type":"int","nullable":true,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[]},{"name":"type","getter_name":"type","moor_type":"string","nullable":false,"customConstraints":null,"default_dart":null,"default_client_dart":null,"dsl_features":[],"type_converter":{"dart_expr":"const EnumNameConverter(GroupActionType.values)","dart_type_name":"GroupActionType"}},{"name":"action_at","getter_name":"actionAt","moor_type":"dateTime","nullable":false,"customConstraints":null,"default_dart":"const CustomExpression('CAST(strftime(\\'%s\\', CURRENT_TIMESTAMP) AS INTEGER)')","default_client_dart":null,"dsl_features":[]}],"is_virtual":false,"without_rowid":false,"constraints":[],"explicit_pk":["group_history_id"]}}]} \ No newline at end of file diff --git a/lib/src/database/tables/mediafiles.table.dart b/lib/src/database/tables/mediafiles.table.dart index 8dc56e3..6fe34ee 100644 --- a/lib/src/database/tables/mediafiles.table.dart +++ b/lib/src/database/tables/mediafiles.table.dart @@ -59,6 +59,8 @@ class MediaFiles extends Table { BlobColumn get encryptionMac => blob().nullable()(); BlobColumn get encryptionNonce => blob().nullable()(); + BlobColumn get storedFileHash => blob().nullable()(); + DateTimeColumn get createdAt => dateTime().withDefault(currentDateAndTime)(); @override diff --git a/lib/src/database/twonly.db.dart b/lib/src/database/twonly.db.dart index dbda205..5d4f1f5 100644 --- a/lib/src/database/twonly.db.dart +++ b/lib/src/database/twonly.db.dart @@ -105,6 +105,10 @@ class TwonlyDB extends _$TwonlyDB { }, from4To5: (m, schema) async { await m.addColumn(schema.receipts, schema.receipts.markForRetry); + await m.addColumn( + schema.mediaFiles, + schema.mediaFiles.storedFileHash, + ); }, ), ); diff --git a/lib/src/database/twonly.db.g.dart b/lib/src/database/twonly.db.g.dart index 26c4e4e..a9eea8c 100644 --- a/lib/src/database/twonly.db.g.dart +++ b/lib/src/database/twonly.db.g.dart @@ -1996,6 +1996,12 @@ class $MediaFilesTable extends MediaFiles late final GeneratedColumn encryptionNonce = GeneratedColumn('encryption_nonce', aliasedName, true, type: DriftSqlType.blob, requiredDuringInsert: false); + static const VerificationMeta _storedFileHashMeta = + const VerificationMeta('storedFileHash'); + @override + late final GeneratedColumn storedFileHash = + GeneratedColumn('stored_file_hash', aliasedName, true, + type: DriftSqlType.blob, requiredDuringInsert: false); static const VerificationMeta _createdAtMeta = const VerificationMeta('createdAt'); @override @@ -2020,6 +2026,7 @@ class $MediaFilesTable extends MediaFiles encryptionKey, encryptionMac, encryptionNonce, + storedFileHash, createdAt ]; @override @@ -2091,6 +2098,12 @@ class $MediaFilesTable extends MediaFiles encryptionNonce.isAcceptableOrUnknown( data['encryption_nonce']!, _encryptionNonceMeta)); } + if (data.containsKey('stored_file_hash')) { + context.handle( + _storedFileHashMeta, + storedFileHash.isAcceptableOrUnknown( + data['stored_file_hash']!, _storedFileHashMeta)); + } if (data.containsKey('created_at')) { context.handle(_createdAtMeta, createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); @@ -2137,6 +2150,8 @@ class $MediaFilesTable extends MediaFiles .read(DriftSqlType.blob, data['${effectivePrefix}encryption_mac']), encryptionNonce: attachedDatabase.typeMapping .read(DriftSqlType.blob, data['${effectivePrefix}encryption_nonce']), + storedFileHash: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}stored_file_hash']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, ); @@ -2181,6 +2196,7 @@ class MediaFile extends DataClass implements Insertable { final Uint8List? encryptionKey; final Uint8List? encryptionMac; final Uint8List? encryptionNonce; + final Uint8List? storedFileHash; final DateTime createdAt; const MediaFile( {required this.mediaId, @@ -2197,6 +2213,7 @@ class MediaFile extends DataClass implements Insertable { this.encryptionKey, this.encryptionMac, this.encryptionNonce, + this.storedFileHash, required this.createdAt}); @override Map toColumns(bool nullToAbsent) { @@ -2241,6 +2258,9 @@ class MediaFile extends DataClass implements Insertable { if (!nullToAbsent || encryptionNonce != null) { map['encryption_nonce'] = Variable(encryptionNonce); } + if (!nullToAbsent || storedFileHash != null) { + map['stored_file_hash'] = Variable(storedFileHash); + } map['created_at'] = Variable(createdAt); return map; } @@ -2280,6 +2300,9 @@ class MediaFile extends DataClass implements Insertable { encryptionNonce: encryptionNonce == null && nullToAbsent ? const Value.absent() : Value(encryptionNonce), + storedFileHash: storedFileHash == null && nullToAbsent + ? const Value.absent() + : Value(storedFileHash), createdAt: Value(createdAt), ); } @@ -2308,6 +2331,7 @@ class MediaFile extends DataClass implements Insertable { encryptionKey: serializer.fromJson(json['encryptionKey']), encryptionMac: serializer.fromJson(json['encryptionMac']), encryptionNonce: serializer.fromJson(json['encryptionNonce']), + storedFileHash: serializer.fromJson(json['storedFileHash']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -2333,6 +2357,7 @@ class MediaFile extends DataClass implements Insertable { 'encryptionKey': serializer.toJson(encryptionKey), 'encryptionMac': serializer.toJson(encryptionMac), 'encryptionNonce': serializer.toJson(encryptionNonce), + 'storedFileHash': serializer.toJson(storedFileHash), 'createdAt': serializer.toJson(createdAt), }; } @@ -2352,6 +2377,7 @@ class MediaFile extends DataClass implements Insertable { Value encryptionKey = const Value.absent(), Value encryptionMac = const Value.absent(), Value encryptionNonce = const Value.absent(), + Value storedFileHash = const Value.absent(), DateTime? createdAt}) => MediaFile( mediaId: mediaId ?? this.mediaId, @@ -2379,6 +2405,8 @@ class MediaFile extends DataClass implements Insertable { encryptionNonce: encryptionNonce.present ? encryptionNonce.value : this.encryptionNonce, + storedFileHash: + storedFileHash.present ? storedFileHash.value : this.storedFileHash, createdAt: createdAt ?? this.createdAt, ); MediaFile copyWithCompanion(MediaFilesCompanion data) { @@ -2417,6 +2445,9 @@ class MediaFile extends DataClass implements Insertable { encryptionNonce: data.encryptionNonce.present ? data.encryptionNonce.value : this.encryptionNonce, + storedFileHash: data.storedFileHash.present + ? data.storedFileHash.value + : this.storedFileHash, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, ); } @@ -2438,6 +2469,7 @@ class MediaFile extends DataClass implements Insertable { ..write('encryptionKey: $encryptionKey, ') ..write('encryptionMac: $encryptionMac, ') ..write('encryptionNonce: $encryptionNonce, ') + ..write('storedFileHash: $storedFileHash, ') ..write('createdAt: $createdAt') ..write(')')) .toString(); @@ -2459,6 +2491,7 @@ class MediaFile extends DataClass implements Insertable { $driftBlobEquality.hash(encryptionKey), $driftBlobEquality.hash(encryptionMac), $driftBlobEquality.hash(encryptionNonce), + $driftBlobEquality.hash(storedFileHash), createdAt); @override bool operator ==(Object other) => @@ -2479,6 +2512,8 @@ class MediaFile extends DataClass implements Insertable { $driftBlobEquality.equals(other.encryptionMac, this.encryptionMac) && $driftBlobEquality.equals( other.encryptionNonce, this.encryptionNonce) && + $driftBlobEquality.equals( + other.storedFileHash, this.storedFileHash) && other.createdAt == this.createdAt); } @@ -2497,6 +2532,7 @@ class MediaFilesCompanion extends UpdateCompanion { final Value encryptionKey; final Value encryptionMac; final Value encryptionNonce; + final Value storedFileHash; final Value createdAt; final Value rowid; const MediaFilesCompanion({ @@ -2514,6 +2550,7 @@ class MediaFilesCompanion extends UpdateCompanion { this.encryptionKey = const Value.absent(), this.encryptionMac = const Value.absent(), this.encryptionNonce = const Value.absent(), + this.storedFileHash = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }); @@ -2532,6 +2569,7 @@ class MediaFilesCompanion extends UpdateCompanion { this.encryptionKey = const Value.absent(), this.encryptionMac = const Value.absent(), this.encryptionNonce = const Value.absent(), + this.storedFileHash = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }) : mediaId = Value(mediaId), @@ -2551,6 +2589,7 @@ class MediaFilesCompanion extends UpdateCompanion { Expression? encryptionKey, Expression? encryptionMac, Expression? encryptionNonce, + Expression? storedFileHash, Expression? createdAt, Expression? rowid, }) { @@ -2572,6 +2611,7 @@ class MediaFilesCompanion extends UpdateCompanion { if (encryptionKey != null) 'encryption_key': encryptionKey, if (encryptionMac != null) 'encryption_mac': encryptionMac, if (encryptionNonce != null) 'encryption_nonce': encryptionNonce, + if (storedFileHash != null) 'stored_file_hash': storedFileHash, if (createdAt != null) 'created_at': createdAt, if (rowid != null) 'rowid': rowid, }); @@ -2592,6 +2632,7 @@ class MediaFilesCompanion extends UpdateCompanion { Value? encryptionKey, Value? encryptionMac, Value? encryptionNonce, + Value? storedFileHash, Value? createdAt, Value? rowid}) { return MediaFilesCompanion( @@ -2611,6 +2652,7 @@ class MediaFilesCompanion extends UpdateCompanion { encryptionKey: encryptionKey ?? this.encryptionKey, encryptionMac: encryptionMac ?? this.encryptionMac, encryptionNonce: encryptionNonce ?? this.encryptionNonce, + storedFileHash: storedFileHash ?? this.storedFileHash, createdAt: createdAt ?? this.createdAt, rowid: rowid ?? this.rowid, ); @@ -2668,6 +2710,9 @@ class MediaFilesCompanion extends UpdateCompanion { if (encryptionNonce.present) { map['encryption_nonce'] = Variable(encryptionNonce.value); } + if (storedFileHash.present) { + map['stored_file_hash'] = Variable(storedFileHash.value); + } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } @@ -2694,6 +2739,7 @@ class MediaFilesCompanion extends UpdateCompanion { ..write('encryptionKey: $encryptionKey, ') ..write('encryptionMac: $encryptionMac, ') ..write('encryptionNonce: $encryptionNonce, ') + ..write('storedFileHash: $storedFileHash, ') ..write('createdAt: $createdAt, ') ..write('rowid: $rowid') ..write(')')) @@ -9390,6 +9436,7 @@ typedef $$MediaFilesTableCreateCompanionBuilder = MediaFilesCompanion Function({ Value encryptionKey, Value encryptionMac, Value encryptionNonce, + Value storedFileHash, Value createdAt, Value rowid, }); @@ -9408,6 +9455,7 @@ typedef $$MediaFilesTableUpdateCompanionBuilder = MediaFilesCompanion Function({ Value encryptionKey, Value encryptionMac, Value encryptionNonce, + Value storedFileHash, Value createdAt, Value rowid, }); @@ -9494,6 +9542,10 @@ class $$MediaFilesTableFilterComposer column: $table.encryptionNonce, builder: (column) => ColumnFilters(column)); + ColumnFilters get storedFileHash => $composableBuilder( + column: $table.storedFileHash, + builder: (column) => ColumnFilters(column)); + ColumnFilters get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnFilters(column)); @@ -9579,6 +9631,10 @@ class $$MediaFilesTableOrderingComposer column: $table.encryptionNonce, builder: (column) => ColumnOrderings(column)); + ColumnOrderings get storedFileHash => $composableBuilder( + column: $table.storedFileHash, + builder: (column) => ColumnOrderings(column)); + ColumnOrderings get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnOrderings(column)); } @@ -9637,6 +9693,9 @@ class $$MediaFilesTableAnnotationComposer GeneratedColumn get encryptionNonce => $composableBuilder( column: $table.encryptionNonce, builder: (column) => column); + GeneratedColumn get storedFileHash => $composableBuilder( + column: $table.storedFileHash, builder: (column) => column); + GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); @@ -9699,6 +9758,7 @@ class $$MediaFilesTableTableManager extends RootTableManager< Value encryptionKey = const Value.absent(), Value encryptionMac = const Value.absent(), Value encryptionNonce = const Value.absent(), + Value storedFileHash = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -9717,6 +9777,7 @@ class $$MediaFilesTableTableManager extends RootTableManager< encryptionKey: encryptionKey, encryptionMac: encryptionMac, encryptionNonce: encryptionNonce, + storedFileHash: storedFileHash, createdAt: createdAt, rowid: rowid, ), @@ -9735,6 +9796,7 @@ class $$MediaFilesTableTableManager extends RootTableManager< Value encryptionKey = const Value.absent(), Value encryptionMac = const Value.absent(), Value encryptionNonce = const Value.absent(), + Value storedFileHash = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => @@ -9753,6 +9815,7 @@ class $$MediaFilesTableTableManager extends RootTableManager< encryptionKey: encryptionKey, encryptionMac: encryptionMac, encryptionNonce: encryptionNonce, + storedFileHash: storedFileHash, createdAt: createdAt, rowid: rowid, ), diff --git a/lib/src/database/twonly.db.steps.dart b/lib/src/database/twonly.db.steps.dart index f457702..ed8ea29 100644 --- a/lib/src/database/twonly.db.steps.dart +++ b/lib/src/database/twonly.db.steps.dart @@ -2033,7 +2033,7 @@ final class Schema5 extends i0.VersionedSchema { attachedDatabase: database, ), alias: null); - late final Shape2 mediaFiles = Shape2( + late final Shape18 mediaFiles = Shape18( source: i0.VersionedTable( entityName: 'media_files', withoutRowId: false, @@ -2056,6 +2056,7 @@ final class Schema5 extends i0.VersionedSchema { _column_47, _column_48, _column_49, + _column_102, _column_12, ], attachedDatabase: database, @@ -2145,7 +2146,7 @@ final class Schema5 extends i0.VersionedSchema { attachedDatabase: database, ), alias: null); - late final Shape18 receipts = Shape18( + late final Shape19 receipts = Shape19( source: i0.VersionedTable( entityName: 'receipts', withoutRowId: false, @@ -2159,7 +2160,7 @@ final class Schema5 extends i0.VersionedSchema { _column_75, _column_76, _column_77, - _column_102, + _column_103, _column_78, _column_79, _column_80, @@ -2326,6 +2327,47 @@ final class Schema5 extends i0.VersionedSchema { class Shape18 extends i0.VersionedTable { Shape18({required super.source, required super.alias}) : super.aliased(); + i1.GeneratedColumn get mediaId => + columnsByName['media_id']! as i1.GeneratedColumn; + i1.GeneratedColumn get type => + columnsByName['type']! as i1.GeneratedColumn; + i1.GeneratedColumn get uploadState => + columnsByName['upload_state']! as i1.GeneratedColumn; + i1.GeneratedColumn get downloadState => + columnsByName['download_state']! as i1.GeneratedColumn; + i1.GeneratedColumn get requiresAuthentication => + columnsByName['requires_authentication']! as i1.GeneratedColumn; + i1.GeneratedColumn get stored => + columnsByName['stored']! as i1.GeneratedColumn; + i1.GeneratedColumn get isDraftMedia => + columnsByName['is_draft_media']! as i1.GeneratedColumn; + i1.GeneratedColumn get reuploadRequestedBy => + columnsByName['reupload_requested_by']! as i1.GeneratedColumn; + i1.GeneratedColumn get displayLimitInMilliseconds => + columnsByName['display_limit_in_milliseconds']! + as i1.GeneratedColumn; + i1.GeneratedColumn get removeAudio => + columnsByName['remove_audio']! as i1.GeneratedColumn; + i1.GeneratedColumn get downloadToken => + columnsByName['download_token']! as i1.GeneratedColumn; + i1.GeneratedColumn get encryptionKey => + columnsByName['encryption_key']! as i1.GeneratedColumn; + i1.GeneratedColumn get encryptionMac => + columnsByName['encryption_mac']! as i1.GeneratedColumn; + i1.GeneratedColumn get encryptionNonce => + columnsByName['encryption_nonce']! as i1.GeneratedColumn; + i1.GeneratedColumn get storedFileHash => + columnsByName['stored_file_hash']! as i1.GeneratedColumn; + i1.GeneratedColumn get createdAt => + columnsByName['created_at']! as i1.GeneratedColumn; +} + +i1.GeneratedColumn _column_102(String aliasedName) => + i1.GeneratedColumn('stored_file_hash', aliasedName, true, + type: i1.DriftSqlType.blob); + +class Shape19 extends i0.VersionedTable { + Shape19({required super.source, required super.alias}) : super.aliased(); i1.GeneratedColumn get receiptId => columnsByName['receipt_id']! as i1.GeneratedColumn; i1.GeneratedColumn get contactId => @@ -2348,7 +2390,7 @@ class Shape18 extends i0.VersionedTable { columnsByName['created_at']! as i1.GeneratedColumn; } -i1.GeneratedColumn _column_102(String aliasedName) => +i1.GeneratedColumn _column_103(String aliasedName) => i1.GeneratedColumn('mark_for_retry', aliasedName, true, type: i1.DriftSqlType.dateTime); i0.MigrationStepWithVersion migrationSteps({ diff --git a/lib/src/localization/app_de.arb b/lib/src/localization/app_de.arb index 57d87a7..d953863 100644 --- a/lib/src/localization/app_de.arb +++ b/lib/src/localization/app_de.arb @@ -461,5 +461,6 @@ "showImagePreviewWhenSending": "Bildvorschau bei der Auswahl von Empfängern anzeigen", "verifiedPublicKey": "Der öffentliche Schlüssel von {username} wurde überprüft und ist gültig.", "memoriesAYearAgo": "Vor einem Jahr", - "memoriesXYearsAgo": "Vor {years} Jahren" + "memoriesXYearsAgo": "Vor {years} Jahren", + "migrationOfMemories": "Migration von Mediendateien: {open} noch offen." } \ No newline at end of file diff --git a/lib/src/localization/app_en.arb b/lib/src/localization/app_en.arb index ddb53ec..25571df 100644 --- a/lib/src/localization/app_en.arb +++ b/lib/src/localization/app_en.arb @@ -491,5 +491,6 @@ "showImagePreviewWhenSending": "Display image preview when selecting recipients", "verifiedPublicKey": "The public key of {username} has been verified and is valid.", "memoriesAYearAgo": "One year ago", - "memoriesXYearsAgo": "{years} years ago" + "memoriesXYearsAgo": "{years} years ago", + "migrationOfMemories": "Migration of media files: {open} still to be processed." } \ No newline at end of file diff --git a/lib/src/localization/generated/app_localizations.dart b/lib/src/localization/generated/app_localizations.dart index d2acbb5..695f6d2 100644 --- a/lib/src/localization/generated/app_localizations.dart +++ b/lib/src/localization/generated/app_localizations.dart @@ -2869,6 +2869,12 @@ abstract class AppLocalizations { /// In en, this message translates to: /// **'{years} years ago'** String memoriesXYearsAgo(Object years); + + /// No description provided for @migrationOfMemories. + /// + /// In en, this message translates to: + /// **'Migration of media files: {open} still to be processed.'** + String migrationOfMemories(Object open); } class _AppLocalizationsDelegate diff --git a/lib/src/localization/generated/app_localizations_de.dart b/lib/src/localization/generated/app_localizations_de.dart index e15da68..a9a569a 100644 --- a/lib/src/localization/generated/app_localizations_de.dart +++ b/lib/src/localization/generated/app_localizations_de.dart @@ -1590,4 +1590,9 @@ class AppLocalizationsDe extends AppLocalizations { String memoriesXYearsAgo(Object years) { return 'Vor $years Jahren'; } + + @override + String migrationOfMemories(Object open) { + return 'Migration von Mediendateien: $open noch offen.'; + } } diff --git a/lib/src/localization/generated/app_localizations_en.dart b/lib/src/localization/generated/app_localizations_en.dart index 6d119c3..a45eab5 100644 --- a/lib/src/localization/generated/app_localizations_en.dart +++ b/lib/src/localization/generated/app_localizations_en.dart @@ -1580,4 +1580,9 @@ class AppLocalizationsEn extends AppLocalizations { String memoriesXYearsAgo(Object years) { return '$years years ago'; } + + @override + String migrationOfMemories(Object open) { + return 'Migration of media files: $open still to be processed.'; + } } diff --git a/lib/src/model/json/userdata.dart b/lib/src/model/json/userdata.dart index ad0852d..fc5c4cd 100644 --- a/lib/src/model/json/userdata.dart +++ b/lib/src/model/json/userdata.dart @@ -59,8 +59,8 @@ class UserData { @JsonKey(defaultValue: true) bool showFeedbackShortcut = true; - @JsonKey(defaultValue: true) - bool showShowImagePreviewWhenSending = true; + @JsonKey(defaultValue: false) + bool showShowImagePreviewWhenSending = false; @JsonKey(defaultValue: true) bool startWithCameraOpen = true; diff --git a/lib/src/services/mediafiles/mediafile.service.dart b/lib/src/services/mediafiles/mediafile.service.dart index 0d89fa1..1288ea6 100644 --- a/lib/src/services/mediafiles/mediafile.service.dart +++ b/lib/src/services/mediafiles/mediafile.service.dart @@ -8,6 +8,7 @@ import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/services/mediafiles/compression.service.dart'; import 'package:twonly/src/services/mediafiles/thumbnail.service.dart'; import 'package:twonly/src/utils/log.dart'; +import 'package:twonly/src/utils/misc.dart'; class MediaFileService { MediaFileService(this.mediaFile); @@ -223,6 +224,22 @@ class MediaFileService { ); } unawaited(createThumbnail()); + await hashStoredMedia(); + // updateFromDb is done in hashStoredMedia() + } + + Future hashStoredMedia() async { + if (!storedPath.existsSync()) { + Log.error('could not create hash value as media file is not stored.'); + return; + } + final checksum = await sha256File(storedPath); + await twonlyDB.mediaFilesDao.updateMedia( + mediaFile.mediaId, + MediaFilesCompanion( + storedFileHash: Value(Uint8List.fromList(checksum)), + ), + ); await updateFromDB(); } diff --git a/lib/src/utils/misc.dart b/lib/src/utils/misc.dart index 62aecea..8a5186c 100644 --- a/lib/src/utils/misc.dart +++ b/lib/src/utils/misc.dart @@ -1,6 +1,8 @@ import 'dart:convert'; import 'dart:io'; import 'dart:math'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_image_compress/flutter_image_compress.dart'; @@ -367,3 +369,12 @@ void printWrapped(String text) { // ignore: avoid_print pattern.allMatches(text).forEach((match) => print(match.group(0))); } + +Future> sha256File(File file) async { + final input = file.openRead(); + final sha256Sink = AccumulatorSink(); + final converter = sha256.startChunkedConversion(sha256Sink); + await input.forEach(converter.add); + converter.close(); + return sha256Sink.events.single.bytes; +} diff --git a/lib/src/views/memories/memories.view.dart b/lib/src/views/memories/memories.view.dart index 483053d..edcbfa8 100644 --- a/lib/src/views/memories/memories.view.dart +++ b/lib/src/views/memories/memories.view.dart @@ -7,6 +7,7 @@ import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/model/memory_item.model.dart'; import 'package:twonly/src/services/mediafiles/mediafile.service.dart'; import 'package:twonly/src/utils/misc.dart'; +import 'package:twonly/src/views/components/loader.dart'; import 'package:twonly/src/views/memories/memories_item_thumbnail.dart'; import 'package:twonly/src/views/memories/memories_photo_slider.view.dart'; @@ -18,6 +19,7 @@ class MemoriesView extends StatefulWidget { } class MemoriesViewState extends State { + int _filesToMigrate = 0; List galleryItems = []; Map> orderedByMonth = {}; List months = []; @@ -38,6 +40,21 @@ class MemoriesViewState extends State { } Future initAsync() async { + final nonHashedFiles = + await twonlyDB.mediaFilesDao.getAllNonHashedStoredMediaFiles(); + if (nonHashedFiles.isNotEmpty) { + setState(() { + _filesToMigrate = nonHashedFiles.length; + }); + for (final mediaFile in nonHashedFiles) { + final mediaService = MediaFileService(mediaFile); + await mediaService.hashStoredMedia(); + setState(() { + _filesToMigrate -= 1; + }); + } + _filesToMigrate = 0; + } await messageSub?.cancel(); final msgStream = twonlyDB.mediaFilesDao.watchAllStoredMediaFiles(); @@ -96,122 +113,139 @@ class MemoriesViewState extends State { @override Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Memories')), - body: Scrollbar( - child: (galleryItems.isEmpty) - ? Center( - child: Text( - context.lang.memoriesEmpty, - textAlign: TextAlign.center, - ), - ) - : ListView.builder( - itemCount: (months.length * 2) + - (_galleryItemsLastYears.isEmpty ? 0 : 1), - itemBuilder: (context, mIndex) { - if (_galleryItemsLastYears.isNotEmpty && mIndex == 0) { - return SizedBox( - height: 140, - width: MediaQuery.sizeOf(context).width, - child: ListView( - scrollDirection: Axis.horizontal, - children: _galleryItemsLastYears.entries.map( - (item) { - var text = context.lang.memoriesAYearAgo; - if (item.key > 1) { - text = context.lang.memoriesXYearsAgo(item.key); - } - return GestureDetector( - onTap: () async { - await open(context, item.value, 0); - }, - child: Container( - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), - boxShadow: const [ - BoxShadow( - spreadRadius: -12, - blurRadius: 12, - ), - ], + Widget child = Center( + child: Text( + context.lang.memoriesEmpty, + textAlign: TextAlign.center, + ), + ); + if (_filesToMigrate > 0) { + child = Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + ThreeRotatingDots( + size: 40, + color: context.color.primary, + ), + const SizedBox(height: 10), + Text( + context.lang.migrationOfMemories(_filesToMigrate), + textAlign: TextAlign.center, + ), + ], + ), + ); + } else if (galleryItems.isNotEmpty) { + child = ListView.builder( + itemCount: + (months.length * 2) + (_galleryItemsLastYears.isEmpty ? 0 : 1), + itemBuilder: (context, mIndex) { + if (_galleryItemsLastYears.isNotEmpty && mIndex == 0) { + return SizedBox( + height: 140, + width: MediaQuery.sizeOf(context).width, + child: ListView( + scrollDirection: Axis.horizontal, + children: _galleryItemsLastYears.entries.map( + (item) { + var text = context.lang.memoriesAYearAgo; + if (item.key > 1) { + text = context.lang.memoriesXYearsAgo(item.key); + } + return GestureDetector( + onTap: () async { + await open(context, item.value, 0); + }, + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + boxShadow: const [ + BoxShadow( + spreadRadius: -12, + blurRadius: 12, + ), + ], + ), + clipBehavior: Clip.hardEdge, + height: 150, + width: 120, + child: Stack( + children: [ + Positioned.fill( + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Image.file( + item.value.first.mediaService.storedPath, + fit: BoxFit.cover, ), - clipBehavior: Clip.hardEdge, - height: 150, - width: 120, - child: Stack( - children: [ - Positioned.fill( - child: ClipRRect( - borderRadius: BorderRadius.circular(12), - child: Image.file( - item.value.first.mediaService - .storedPath, - fit: BoxFit.cover, - ), - ), - ), - Positioned( - bottom: 10, - left: 0, - right: 0, - child: Text( - text, - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - fontSize: 20, - shadows: [ - Shadow( - color: - Color.fromARGB(122, 0, 0, 0), - blurRadius: 5, - ), - ], - ), - ), + ), + ), + Positioned( + bottom: 10, + left: 0, + right: 0, + child: Text( + text, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + fontSize: 20, + shadows: [ + Shadow( + color: Color.fromARGB(122, 0, 0, 0), + blurRadius: 5, ), ], ), ), - ); - }, - ).toList(), + ), + ], + ), ), ); - } - if (_galleryItemsLastYears.isNotEmpty) { - mIndex -= 1; - } - if (mIndex.isEven) { - return Padding( - padding: const EdgeInsets.all(8), - child: Text(months[(mIndex ~/ 2)]), - ); - } - final index = (mIndex - 1) ~/ 2; - return GridView.builder( - shrinkWrap: true, - physics: const ClampingScrollPhysics(), - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 4, - childAspectRatio: 9 / 16, - ), - itemCount: orderedByMonth[months[index]]!.length, - itemBuilder: (context, gIndex) { - final gaIndex = orderedByMonth[months[index]]![gIndex]; - return MemoriesItemThumbnail( - galleryItem: galleryItems[gaIndex], - onTap: () async { - await open(context, galleryItems, gaIndex); - }, - ); - }, - ); - }, + }, + ).toList(), ), + ); + } + if (_galleryItemsLastYears.isNotEmpty) { + mIndex -= 1; + } + if (mIndex.isEven) { + return Padding( + padding: const EdgeInsets.all(8), + child: Text(months[(mIndex ~/ 2)]), + ); + } + final index = (mIndex - 1) ~/ 2; + return GridView.builder( + shrinkWrap: true, + physics: const ClampingScrollPhysics(), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + childAspectRatio: 9 / 16, + ), + itemCount: orderedByMonth[months[index]]!.length, + itemBuilder: (context, gIndex) { + final gaIndex = orderedByMonth[months[index]]![gIndex]; + return MemoriesItemThumbnail( + galleryItem: galleryItems[gaIndex], + onTap: () async { + await open(context, galleryItems, gaIndex); + }, + ); + }, + ); + }, + ); + } + + return Scaffold( + appBar: AppBar(title: const Text('Memories')), + body: Scrollbar( + child: child, ), ); } diff --git a/test/drift/twonly_db/generated/schema_v5.dart b/test/drift/twonly_db/generated/schema_v5.dart index 4538c77..4ec5f8e 100644 --- a/test/drift/twonly_db/generated/schema_v5.dart +++ b/test/drift/twonly_db/generated/schema_v5.dart @@ -1626,6 +1626,9 @@ class MediaFiles extends Table with TableInfo { late final GeneratedColumn encryptionNonce = GeneratedColumn('encryption_nonce', aliasedName, true, type: DriftSqlType.blob, requiredDuringInsert: false); + late final GeneratedColumn storedFileHash = + GeneratedColumn('stored_file_hash', aliasedName, true, + type: DriftSqlType.blob, requiredDuringInsert: false); late final GeneratedColumn createdAt = GeneratedColumn( 'created_at', aliasedName, false, type: DriftSqlType.dateTime, @@ -1648,6 +1651,7 @@ class MediaFiles extends Table with TableInfo { encryptionKey, encryptionMac, encryptionNonce, + storedFileHash, createdAt ]; @override @@ -1691,6 +1695,8 @@ class MediaFiles extends Table with TableInfo { .read(DriftSqlType.blob, data['${effectivePrefix}encryption_mac']), encryptionNonce: attachedDatabase.typeMapping .read(DriftSqlType.blob, data['${effectivePrefix}encryption_nonce']), + storedFileHash: attachedDatabase.typeMapping + .read(DriftSqlType.blob, data['${effectivePrefix}stored_file_hash']), createdAt: attachedDatabase.typeMapping .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, ); @@ -1717,6 +1723,7 @@ class MediaFilesData extends DataClass implements Insertable { final i2.Uint8List? encryptionKey; final i2.Uint8List? encryptionMac; final i2.Uint8List? encryptionNonce; + final i2.Uint8List? storedFileHash; final DateTime createdAt; const MediaFilesData( {required this.mediaId, @@ -1733,6 +1740,7 @@ class MediaFilesData extends DataClass implements Insertable { this.encryptionKey, this.encryptionMac, this.encryptionNonce, + this.storedFileHash, required this.createdAt}); @override Map toColumns(bool nullToAbsent) { @@ -1770,6 +1778,9 @@ class MediaFilesData extends DataClass implements Insertable { if (!nullToAbsent || encryptionNonce != null) { map['encryption_nonce'] = Variable(encryptionNonce); } + if (!nullToAbsent || storedFileHash != null) { + map['stored_file_hash'] = Variable(storedFileHash); + } map['created_at'] = Variable(createdAt); return map; } @@ -1809,6 +1820,9 @@ class MediaFilesData extends DataClass implements Insertable { encryptionNonce: encryptionNonce == null && nullToAbsent ? const Value.absent() : Value(encryptionNonce), + storedFileHash: storedFileHash == null && nullToAbsent + ? const Value.absent() + : Value(storedFileHash), createdAt: Value(createdAt), ); } @@ -1835,6 +1849,8 @@ class MediaFilesData extends DataClass implements Insertable { encryptionMac: serializer.fromJson(json['encryptionMac']), encryptionNonce: serializer.fromJson(json['encryptionNonce']), + storedFileHash: + serializer.fromJson(json['storedFileHash']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -1857,6 +1873,7 @@ class MediaFilesData extends DataClass implements Insertable { 'encryptionKey': serializer.toJson(encryptionKey), 'encryptionMac': serializer.toJson(encryptionMac), 'encryptionNonce': serializer.toJson(encryptionNonce), + 'storedFileHash': serializer.toJson(storedFileHash), 'createdAt': serializer.toJson(createdAt), }; } @@ -1876,6 +1893,7 @@ class MediaFilesData extends DataClass implements Insertable { Value encryptionKey = const Value.absent(), Value encryptionMac = const Value.absent(), Value encryptionNonce = const Value.absent(), + Value storedFileHash = const Value.absent(), DateTime? createdAt}) => MediaFilesData( mediaId: mediaId ?? this.mediaId, @@ -1903,6 +1921,8 @@ class MediaFilesData extends DataClass implements Insertable { encryptionNonce: encryptionNonce.present ? encryptionNonce.value : this.encryptionNonce, + storedFileHash: + storedFileHash.present ? storedFileHash.value : this.storedFileHash, createdAt: createdAt ?? this.createdAt, ); MediaFilesData copyWithCompanion(MediaFilesCompanion data) { @@ -1941,6 +1961,9 @@ class MediaFilesData extends DataClass implements Insertable { encryptionNonce: data.encryptionNonce.present ? data.encryptionNonce.value : this.encryptionNonce, + storedFileHash: data.storedFileHash.present + ? data.storedFileHash.value + : this.storedFileHash, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, ); } @@ -1962,6 +1985,7 @@ class MediaFilesData extends DataClass implements Insertable { ..write('encryptionKey: $encryptionKey, ') ..write('encryptionMac: $encryptionMac, ') ..write('encryptionNonce: $encryptionNonce, ') + ..write('storedFileHash: $storedFileHash, ') ..write('createdAt: $createdAt') ..write(')')) .toString(); @@ -1983,6 +2007,7 @@ class MediaFilesData extends DataClass implements Insertable { $driftBlobEquality.hash(encryptionKey), $driftBlobEquality.hash(encryptionMac), $driftBlobEquality.hash(encryptionNonce), + $driftBlobEquality.hash(storedFileHash), createdAt); @override bool operator ==(Object other) => @@ -2003,6 +2028,8 @@ class MediaFilesData extends DataClass implements Insertable { $driftBlobEquality.equals(other.encryptionMac, this.encryptionMac) && $driftBlobEquality.equals( other.encryptionNonce, this.encryptionNonce) && + $driftBlobEquality.equals( + other.storedFileHash, this.storedFileHash) && other.createdAt == this.createdAt); } @@ -2021,6 +2048,7 @@ class MediaFilesCompanion extends UpdateCompanion { final Value encryptionKey; final Value encryptionMac; final Value encryptionNonce; + final Value storedFileHash; final Value createdAt; final Value rowid; const MediaFilesCompanion({ @@ -2038,6 +2066,7 @@ class MediaFilesCompanion extends UpdateCompanion { this.encryptionKey = const Value.absent(), this.encryptionMac = const Value.absent(), this.encryptionNonce = const Value.absent(), + this.storedFileHash = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }); @@ -2056,6 +2085,7 @@ class MediaFilesCompanion extends UpdateCompanion { this.encryptionKey = const Value.absent(), this.encryptionMac = const Value.absent(), this.encryptionNonce = const Value.absent(), + this.storedFileHash = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }) : mediaId = Value(mediaId), @@ -2075,6 +2105,7 @@ class MediaFilesCompanion extends UpdateCompanion { Expression? encryptionKey, Expression? encryptionMac, Expression? encryptionNonce, + Expression? storedFileHash, Expression? createdAt, Expression? rowid, }) { @@ -2096,6 +2127,7 @@ class MediaFilesCompanion extends UpdateCompanion { if (encryptionKey != null) 'encryption_key': encryptionKey, if (encryptionMac != null) 'encryption_mac': encryptionMac, if (encryptionNonce != null) 'encryption_nonce': encryptionNonce, + if (storedFileHash != null) 'stored_file_hash': storedFileHash, if (createdAt != null) 'created_at': createdAt, if (rowid != null) 'rowid': rowid, }); @@ -2116,6 +2148,7 @@ class MediaFilesCompanion extends UpdateCompanion { Value? encryptionKey, Value? encryptionMac, Value? encryptionNonce, + Value? storedFileHash, Value? createdAt, Value? rowid}) { return MediaFilesCompanion( @@ -2135,6 +2168,7 @@ class MediaFilesCompanion extends UpdateCompanion { encryptionKey: encryptionKey ?? this.encryptionKey, encryptionMac: encryptionMac ?? this.encryptionMac, encryptionNonce: encryptionNonce ?? this.encryptionNonce, + storedFileHash: storedFileHash ?? this.storedFileHash, createdAt: createdAt ?? this.createdAt, rowid: rowid ?? this.rowid, ); @@ -2188,6 +2222,9 @@ class MediaFilesCompanion extends UpdateCompanion { if (encryptionNonce.present) { map['encryption_nonce'] = Variable(encryptionNonce.value); } + if (storedFileHash.present) { + map['stored_file_hash'] = Variable(storedFileHash.value); + } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } @@ -2214,6 +2251,7 @@ class MediaFilesCompanion extends UpdateCompanion { ..write('encryptionKey: $encryptionKey, ') ..write('encryptionMac: $encryptionMac, ') ..write('encryptionNonce: $encryptionNonce, ') + ..write('storedFileHash: $storedFileHash, ') ..write('createdAt: $createdAt, ') ..write('rowid: $rowid') ..write(')'))