diff --git a/lib/src/database/daos/messages.dao.dart b/lib/src/database/daos/messages.dao.dart index b96904e..963ef02 100644 --- a/lib/src/database/daos/messages.dao.dart +++ b/lib/src/database/daos/messages.dao.dart @@ -348,6 +348,10 @@ class MessagesDao extends DatabaseAccessor with _$MessagesDaoMixin { return select(messages)..where((t) => t.messageId.equals(messageId)); } + Future> getMessagesByMediaId(String mediaId) async { + return (select(messages)..where((t) => t.mediaId.equals(mediaId))).get(); + } + // Future> getMessagesByMediaUploadId(int mediaUploadId) async { // return (select(messages) // ..where((t) => t.mediaUploadId.equals(mediaUploadId))) diff --git a/lib/src/database/daos/messages.dao.g.dart b/lib/src/database/daos/messages.dao.g.dart index 5f11d3a..e763f72 100644 --- a/lib/src/database/daos/messages.dao.g.dart +++ b/lib/src/database/daos/messages.dao.g.dart @@ -4,10 +4,10 @@ part of 'messages.dao.dart'; // ignore_for_file: type=lint mixin _$MessagesDaoMixin on DatabaseAccessor { + $GroupsTable get groups => attachedDatabase.groups; $ContactsTable get contacts => attachedDatabase.contacts; $MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles; $MessagesTable get messages => attachedDatabase.messages; $MessageHistoriesTable get messageHistories => attachedDatabase.messageHistories; - $GroupsTable get groups => attachedDatabase.groups; } diff --git a/lib/src/database/daos/reactions.dao.g.dart b/lib/src/database/daos/reactions.dao.g.dart index 2fcd9af..26ac0da 100644 --- a/lib/src/database/daos/reactions.dao.g.dart +++ b/lib/src/database/daos/reactions.dao.g.dart @@ -4,6 +4,7 @@ part of 'reactions.dao.dart'; // ignore_for_file: type=lint mixin _$ReactionsDaoMixin on DatabaseAccessor { + $GroupsTable get groups => attachedDatabase.groups; $ContactsTable get contacts => attachedDatabase.contacts; $MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles; $MessagesTable get messages => attachedDatabase.messages; diff --git a/lib/src/database/daos/receipts.dao.g.dart b/lib/src/database/daos/receipts.dao.g.dart index d0b9b41..5a06998 100644 --- a/lib/src/database/daos/receipts.dao.g.dart +++ b/lib/src/database/daos/receipts.dao.g.dart @@ -5,6 +5,7 @@ part of 'receipts.dao.dart'; // ignore_for_file: type=lint mixin _$ReceiptsDaoMixin on DatabaseAccessor { $ContactsTable get contacts => attachedDatabase.contacts; + $GroupsTable get groups => attachedDatabase.groups; $MediaFilesTable get mediaFiles => attachedDatabase.mediaFiles; $MessagesTable get messages => attachedDatabase.messages; $ReceiptsTable get receipts => attachedDatabase.receipts; diff --git a/lib/src/database/tables/mediafiles.table.dart b/lib/src/database/tables/mediafiles.table.dart index db4a812..34990a4 100644 --- a/lib/src/database/tables/mediafiles.table.dart +++ b/lib/src/database/tables/mediafiles.table.dart @@ -16,7 +16,7 @@ enum UploadState { receiverNotified, } -enum DownloadState { pending, downloading } +enum DownloadState { pending, downloading, reuploadRequested } @DataClassName('MediaFile') class MediaFiles extends Table { diff --git a/lib/src/database/tables/messages.table.dart b/lib/src/database/tables/messages.table.dart index 3537c63..b7ef767 100644 --- a/lib/src/database/tables/messages.table.dart +++ b/lib/src/database/tables/messages.table.dart @@ -1,11 +1,13 @@ import 'package:drift/drift.dart'; import 'package:hashlib/random.dart'; import 'package:twonly/src/database/tables/contacts.table.dart'; +import 'package:twonly/src/database/tables/groups.table.dart'; import 'package:twonly/src/database/tables/mediafiles.table.dart'; @DataClassName('Message') class Messages extends Table { - TextColumn get groupId => text()(); + TextColumn get groupId => + text().references(Groups, #groupId, onDelete: KeyAction.cascade)(); TextColumn get messageId => text().clientDefault(() => uuid.v7())(); // in case senderId is null, it was send by user itself diff --git a/lib/src/database/twonly.db.g.dart b/lib/src/database/twonly.db.g.dart index 472e56a..55b6fe6 100644 --- a/lib/src/database/twonly.db.g.dart +++ b/lib/src/database/twonly.db.g.dart @@ -1011,6 +1011,418 @@ class ContactsCompanion extends UpdateCompanion { } } +class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $GroupsTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _groupIdMeta = + const VerificationMeta('groupId'); + @override + late final GeneratedColumn groupId = GeneratedColumn( + 'group_id', aliasedName, false, + type: DriftSqlType.string, + requiredDuringInsert: false, + clientDefault: () => uuid.v4()); + static const VerificationMeta _isGroupAdminMeta = + const VerificationMeta('isGroupAdmin'); + @override + late final GeneratedColumn isGroupAdmin = GeneratedColumn( + 'is_group_admin', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_group_admin" IN (0, 1))')); + static const VerificationMeta _isGroupOfTwoMeta = + const VerificationMeta('isGroupOfTwo'); + @override + late final GeneratedColumn isGroupOfTwo = GeneratedColumn( + 'is_group_of_two', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("is_group_of_two" IN (0, 1))')); + static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); + @override + late final GeneratedColumn pinned = GeneratedColumn( + 'pinned', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _archivedMeta = + const VerificationMeta('archived'); + @override + late final GeneratedColumn archived = GeneratedColumn( + 'archived', aliasedName, false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: + GeneratedColumn.constraintIsAlways('CHECK ("archived" IN (0, 1))'), + defaultValue: const Constant(false)); + static const VerificationMeta _lastMessageExchangeMeta = + const VerificationMeta('lastMessageExchange'); + @override + late final GeneratedColumn lastMessageExchange = + GeneratedColumn('last_message_exchange', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + static const VerificationMeta _createdAtMeta = + const VerificationMeta('createdAt'); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', aliasedName, false, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + defaultValue: currentDateAndTime); + @override + List get $columns => [ + groupId, + isGroupAdmin, + isGroupOfTwo, + pinned, + archived, + lastMessageExchange, + createdAt + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'groups'; + @override + VerificationContext validateIntegrity(Insertable instance, + {bool isInserting = false}) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('group_id')) { + context.handle(_groupIdMeta, + groupId.isAcceptableOrUnknown(data['group_id']!, _groupIdMeta)); + } + if (data.containsKey('is_group_admin')) { + context.handle( + _isGroupAdminMeta, + isGroupAdmin.isAcceptableOrUnknown( + data['is_group_admin']!, _isGroupAdminMeta)); + } else if (isInserting) { + context.missing(_isGroupAdminMeta); + } + if (data.containsKey('is_group_of_two')) { + context.handle( + _isGroupOfTwoMeta, + isGroupOfTwo.isAcceptableOrUnknown( + data['is_group_of_two']!, _isGroupOfTwoMeta)); + } else if (isInserting) { + context.missing(_isGroupOfTwoMeta); + } + if (data.containsKey('pinned')) { + context.handle(_pinnedMeta, + pinned.isAcceptableOrUnknown(data['pinned']!, _pinnedMeta)); + } + if (data.containsKey('archived')) { + context.handle(_archivedMeta, + archived.isAcceptableOrUnknown(data['archived']!, _archivedMeta)); + } + if (data.containsKey('last_message_exchange')) { + context.handle( + _lastMessageExchangeMeta, + lastMessageExchange.isAcceptableOrUnknown( + data['last_message_exchange']!, _lastMessageExchangeMeta)); + } + if (data.containsKey('created_at')) { + context.handle(_createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); + } + return context; + } + + @override + Set get $primaryKey => {groupId}; + @override + Group map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Group( + groupId: attachedDatabase.typeMapping + .read(DriftSqlType.string, data['${effectivePrefix}group_id'])!, + isGroupAdmin: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_group_admin'])!, + isGroupOfTwo: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}is_group_of_two'])!, + pinned: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}pinned'])!, + archived: attachedDatabase.typeMapping + .read(DriftSqlType.bool, data['${effectivePrefix}archived'])!, + lastMessageExchange: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}last_message_exchange'])!, + createdAt: attachedDatabase.typeMapping + .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, + ); + } + + @override + $GroupsTable createAlias(String alias) { + return $GroupsTable(attachedDatabase, alias); + } +} + +class Group extends DataClass implements Insertable { + final String groupId; + final bool isGroupAdmin; + final bool isGroupOfTwo; + final bool pinned; + final bool archived; + final DateTime lastMessageExchange; + final DateTime createdAt; + const Group( + {required this.groupId, + required this.isGroupAdmin, + required this.isGroupOfTwo, + required this.pinned, + required this.archived, + required this.lastMessageExchange, + required this.createdAt}); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['group_id'] = Variable(groupId); + map['is_group_admin'] = Variable(isGroupAdmin); + map['is_group_of_two'] = Variable(isGroupOfTwo); + map['pinned'] = Variable(pinned); + map['archived'] = Variable(archived); + map['last_message_exchange'] = Variable(lastMessageExchange); + map['created_at'] = Variable(createdAt); + return map; + } + + GroupsCompanion toCompanion(bool nullToAbsent) { + return GroupsCompanion( + groupId: Value(groupId), + isGroupAdmin: Value(isGroupAdmin), + isGroupOfTwo: Value(isGroupOfTwo), + pinned: Value(pinned), + archived: Value(archived), + lastMessageExchange: Value(lastMessageExchange), + createdAt: Value(createdAt), + ); + } + + factory Group.fromJson(Map json, + {ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return Group( + groupId: serializer.fromJson(json['groupId']), + isGroupAdmin: serializer.fromJson(json['isGroupAdmin']), + isGroupOfTwo: serializer.fromJson(json['isGroupOfTwo']), + pinned: serializer.fromJson(json['pinned']), + archived: serializer.fromJson(json['archived']), + lastMessageExchange: + serializer.fromJson(json['lastMessageExchange']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'groupId': serializer.toJson(groupId), + 'isGroupAdmin': serializer.toJson(isGroupAdmin), + 'isGroupOfTwo': serializer.toJson(isGroupOfTwo), + 'pinned': serializer.toJson(pinned), + 'archived': serializer.toJson(archived), + 'lastMessageExchange': serializer.toJson(lastMessageExchange), + 'createdAt': serializer.toJson(createdAt), + }; + } + + Group copyWith( + {String? groupId, + bool? isGroupAdmin, + bool? isGroupOfTwo, + bool? pinned, + bool? archived, + DateTime? lastMessageExchange, + DateTime? createdAt}) => + Group( + groupId: groupId ?? this.groupId, + isGroupAdmin: isGroupAdmin ?? this.isGroupAdmin, + isGroupOfTwo: isGroupOfTwo ?? this.isGroupOfTwo, + pinned: pinned ?? this.pinned, + archived: archived ?? this.archived, + lastMessageExchange: lastMessageExchange ?? this.lastMessageExchange, + createdAt: createdAt ?? this.createdAt, + ); + Group copyWithCompanion(GroupsCompanion data) { + return Group( + groupId: data.groupId.present ? data.groupId.value : this.groupId, + isGroupAdmin: data.isGroupAdmin.present + ? data.isGroupAdmin.value + : this.isGroupAdmin, + isGroupOfTwo: data.isGroupOfTwo.present + ? data.isGroupOfTwo.value + : this.isGroupOfTwo, + pinned: data.pinned.present ? data.pinned.value : this.pinned, + archived: data.archived.present ? data.archived.value : this.archived, + lastMessageExchange: data.lastMessageExchange.present + ? data.lastMessageExchange.value + : this.lastMessageExchange, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('Group(') + ..write('groupId: $groupId, ') + ..write('isGroupAdmin: $isGroupAdmin, ') + ..write('isGroupOfTwo: $isGroupOfTwo, ') + ..write('pinned: $pinned, ') + ..write('archived: $archived, ') + ..write('lastMessageExchange: $lastMessageExchange, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(groupId, isGroupAdmin, isGroupOfTwo, pinned, + archived, lastMessageExchange, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is Group && + other.groupId == this.groupId && + other.isGroupAdmin == this.isGroupAdmin && + other.isGroupOfTwo == this.isGroupOfTwo && + other.pinned == this.pinned && + other.archived == this.archived && + other.lastMessageExchange == this.lastMessageExchange && + other.createdAt == this.createdAt); +} + +class GroupsCompanion extends UpdateCompanion { + final Value groupId; + final Value isGroupAdmin; + final Value isGroupOfTwo; + final Value pinned; + final Value archived; + final Value lastMessageExchange; + final Value createdAt; + final Value rowid; + const GroupsCompanion({ + this.groupId = const Value.absent(), + this.isGroupAdmin = const Value.absent(), + this.isGroupOfTwo = const Value.absent(), + this.pinned = const Value.absent(), + this.archived = const Value.absent(), + this.lastMessageExchange = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + GroupsCompanion.insert({ + this.groupId = const Value.absent(), + required bool isGroupAdmin, + required bool isGroupOfTwo, + this.pinned = const Value.absent(), + this.archived = const Value.absent(), + this.lastMessageExchange = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }) : isGroupAdmin = Value(isGroupAdmin), + isGroupOfTwo = Value(isGroupOfTwo); + static Insertable custom({ + Expression? groupId, + Expression? isGroupAdmin, + Expression? isGroupOfTwo, + Expression? pinned, + Expression? archived, + Expression? lastMessageExchange, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (groupId != null) 'group_id': groupId, + if (isGroupAdmin != null) 'is_group_admin': isGroupAdmin, + if (isGroupOfTwo != null) 'is_group_of_two': isGroupOfTwo, + if (pinned != null) 'pinned': pinned, + if (archived != null) 'archived': archived, + if (lastMessageExchange != null) + 'last_message_exchange': lastMessageExchange, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + GroupsCompanion copyWith( + {Value? groupId, + Value? isGroupAdmin, + Value? isGroupOfTwo, + Value? pinned, + Value? archived, + Value? lastMessageExchange, + Value? createdAt, + Value? rowid}) { + return GroupsCompanion( + groupId: groupId ?? this.groupId, + isGroupAdmin: isGroupAdmin ?? this.isGroupAdmin, + isGroupOfTwo: isGroupOfTwo ?? this.isGroupOfTwo, + pinned: pinned ?? this.pinned, + archived: archived ?? this.archived, + lastMessageExchange: lastMessageExchange ?? this.lastMessageExchange, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (groupId.present) { + map['group_id'] = Variable(groupId.value); + } + if (isGroupAdmin.present) { + map['is_group_admin'] = Variable(isGroupAdmin.value); + } + if (isGroupOfTwo.present) { + map['is_group_of_two'] = Variable(isGroupOfTwo.value); + } + if (pinned.present) { + map['pinned'] = Variable(pinned.value); + } + if (archived.present) { + map['archived'] = Variable(archived.value); + } + if (lastMessageExchange.present) { + map['last_message_exchange'] = + Variable(lastMessageExchange.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('GroupsCompanion(') + ..write('groupId: $groupId, ') + ..write('isGroupAdmin: $isGroupAdmin, ') + ..write('isGroupOfTwo: $isGroupOfTwo, ') + ..write('pinned: $pinned, ') + ..write('archived: $archived, ') + ..write('lastMessageExchange: $lastMessageExchange, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + class $MediaFilesTable extends MediaFiles with TableInfo<$MediaFilesTable, MediaFile> { @override @@ -1790,7 +2202,10 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> { @override late final GeneratedColumn groupId = GeneratedColumn( 'group_id', aliasedName, false, - type: DriftSqlType.string, requiredDuringInsert: true); + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES "groups" (group_id) ON DELETE CASCADE')); static const VerificationMeta _messageIdMeta = const VerificationMeta('messageId'); @override @@ -3008,418 +3423,6 @@ class ReactionsCompanion extends UpdateCompanion { } } -class $GroupsTable extends Groups with TableInfo<$GroupsTable, Group> { - @override - final GeneratedDatabase attachedDatabase; - final String? _alias; - $GroupsTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _groupIdMeta = - const VerificationMeta('groupId'); - @override - late final GeneratedColumn groupId = GeneratedColumn( - 'group_id', aliasedName, false, - type: DriftSqlType.string, - requiredDuringInsert: false, - clientDefault: () => uuid.v4()); - static const VerificationMeta _isGroupAdminMeta = - const VerificationMeta('isGroupAdmin'); - @override - late final GeneratedColumn isGroupAdmin = GeneratedColumn( - 'is_group_admin', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: true, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("is_group_admin" IN (0, 1))')); - static const VerificationMeta _isGroupOfTwoMeta = - const VerificationMeta('isGroupOfTwo'); - @override - late final GeneratedColumn isGroupOfTwo = GeneratedColumn( - 'is_group_of_two', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: true, - defaultConstraints: GeneratedColumn.constraintIsAlways( - 'CHECK ("is_group_of_two" IN (0, 1))')); - static const VerificationMeta _pinnedMeta = const VerificationMeta('pinned'); - @override - late final GeneratedColumn pinned = GeneratedColumn( - 'pinned', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("pinned" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _archivedMeta = - const VerificationMeta('archived'); - @override - late final GeneratedColumn archived = GeneratedColumn( - 'archived', aliasedName, false, - type: DriftSqlType.bool, - requiredDuringInsert: false, - defaultConstraints: - GeneratedColumn.constraintIsAlways('CHECK ("archived" IN (0, 1))'), - defaultValue: const Constant(false)); - static const VerificationMeta _lastMessageExchangeMeta = - const VerificationMeta('lastMessageExchange'); - @override - late final GeneratedColumn lastMessageExchange = - GeneratedColumn('last_message_exchange', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - static const VerificationMeta _createdAtMeta = - const VerificationMeta('createdAt'); - @override - late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', aliasedName, false, - type: DriftSqlType.dateTime, - requiredDuringInsert: false, - defaultValue: currentDateAndTime); - @override - List get $columns => [ - groupId, - isGroupAdmin, - isGroupOfTwo, - pinned, - archived, - lastMessageExchange, - createdAt - ]; - @override - String get aliasedName => _alias ?? actualTableName; - @override - String get actualTableName => $name; - static const String $name = 'groups'; - @override - VerificationContext validateIntegrity(Insertable instance, - {bool isInserting = false}) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('group_id')) { - context.handle(_groupIdMeta, - groupId.isAcceptableOrUnknown(data['group_id']!, _groupIdMeta)); - } - if (data.containsKey('is_group_admin')) { - context.handle( - _isGroupAdminMeta, - isGroupAdmin.isAcceptableOrUnknown( - data['is_group_admin']!, _isGroupAdminMeta)); - } else if (isInserting) { - context.missing(_isGroupAdminMeta); - } - if (data.containsKey('is_group_of_two')) { - context.handle( - _isGroupOfTwoMeta, - isGroupOfTwo.isAcceptableOrUnknown( - data['is_group_of_two']!, _isGroupOfTwoMeta)); - } else if (isInserting) { - context.missing(_isGroupOfTwoMeta); - } - if (data.containsKey('pinned')) { - context.handle(_pinnedMeta, - pinned.isAcceptableOrUnknown(data['pinned']!, _pinnedMeta)); - } - if (data.containsKey('archived')) { - context.handle(_archivedMeta, - archived.isAcceptableOrUnknown(data['archived']!, _archivedMeta)); - } - if (data.containsKey('last_message_exchange')) { - context.handle( - _lastMessageExchangeMeta, - lastMessageExchange.isAcceptableOrUnknown( - data['last_message_exchange']!, _lastMessageExchangeMeta)); - } - if (data.containsKey('created_at')) { - context.handle(_createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta)); - } - return context; - } - - @override - Set get $primaryKey => {groupId}; - @override - Group map(Map data, {String? tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return Group( - groupId: attachedDatabase.typeMapping - .read(DriftSqlType.string, data['${effectivePrefix}group_id'])!, - isGroupAdmin: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}is_group_admin'])!, - isGroupOfTwo: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}is_group_of_two'])!, - pinned: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}pinned'])!, - archived: attachedDatabase.typeMapping - .read(DriftSqlType.bool, data['${effectivePrefix}archived'])!, - lastMessageExchange: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, - data['${effectivePrefix}last_message_exchange'])!, - createdAt: attachedDatabase.typeMapping - .read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!, - ); - } - - @override - $GroupsTable createAlias(String alias) { - return $GroupsTable(attachedDatabase, alias); - } -} - -class Group extends DataClass implements Insertable { - final String groupId; - final bool isGroupAdmin; - final bool isGroupOfTwo; - final bool pinned; - final bool archived; - final DateTime lastMessageExchange; - final DateTime createdAt; - const Group( - {required this.groupId, - required this.isGroupAdmin, - required this.isGroupOfTwo, - required this.pinned, - required this.archived, - required this.lastMessageExchange, - required this.createdAt}); - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - map['group_id'] = Variable(groupId); - map['is_group_admin'] = Variable(isGroupAdmin); - map['is_group_of_two'] = Variable(isGroupOfTwo); - map['pinned'] = Variable(pinned); - map['archived'] = Variable(archived); - map['last_message_exchange'] = Variable(lastMessageExchange); - map['created_at'] = Variable(createdAt); - return map; - } - - GroupsCompanion toCompanion(bool nullToAbsent) { - return GroupsCompanion( - groupId: Value(groupId), - isGroupAdmin: Value(isGroupAdmin), - isGroupOfTwo: Value(isGroupOfTwo), - pinned: Value(pinned), - archived: Value(archived), - lastMessageExchange: Value(lastMessageExchange), - createdAt: Value(createdAt), - ); - } - - factory Group.fromJson(Map json, - {ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return Group( - groupId: serializer.fromJson(json['groupId']), - isGroupAdmin: serializer.fromJson(json['isGroupAdmin']), - isGroupOfTwo: serializer.fromJson(json['isGroupOfTwo']), - pinned: serializer.fromJson(json['pinned']), - archived: serializer.fromJson(json['archived']), - lastMessageExchange: - serializer.fromJson(json['lastMessageExchange']), - createdAt: serializer.fromJson(json['createdAt']), - ); - } - @override - Map toJson({ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return { - 'groupId': serializer.toJson(groupId), - 'isGroupAdmin': serializer.toJson(isGroupAdmin), - 'isGroupOfTwo': serializer.toJson(isGroupOfTwo), - 'pinned': serializer.toJson(pinned), - 'archived': serializer.toJson(archived), - 'lastMessageExchange': serializer.toJson(lastMessageExchange), - 'createdAt': serializer.toJson(createdAt), - }; - } - - Group copyWith( - {String? groupId, - bool? isGroupAdmin, - bool? isGroupOfTwo, - bool? pinned, - bool? archived, - DateTime? lastMessageExchange, - DateTime? createdAt}) => - Group( - groupId: groupId ?? this.groupId, - isGroupAdmin: isGroupAdmin ?? this.isGroupAdmin, - isGroupOfTwo: isGroupOfTwo ?? this.isGroupOfTwo, - pinned: pinned ?? this.pinned, - archived: archived ?? this.archived, - lastMessageExchange: lastMessageExchange ?? this.lastMessageExchange, - createdAt: createdAt ?? this.createdAt, - ); - Group copyWithCompanion(GroupsCompanion data) { - return Group( - groupId: data.groupId.present ? data.groupId.value : this.groupId, - isGroupAdmin: data.isGroupAdmin.present - ? data.isGroupAdmin.value - : this.isGroupAdmin, - isGroupOfTwo: data.isGroupOfTwo.present - ? data.isGroupOfTwo.value - : this.isGroupOfTwo, - pinned: data.pinned.present ? data.pinned.value : this.pinned, - archived: data.archived.present ? data.archived.value : this.archived, - lastMessageExchange: data.lastMessageExchange.present - ? data.lastMessageExchange.value - : this.lastMessageExchange, - createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - ); - } - - @override - String toString() { - return (StringBuffer('Group(') - ..write('groupId: $groupId, ') - ..write('isGroupAdmin: $isGroupAdmin, ') - ..write('isGroupOfTwo: $isGroupOfTwo, ') - ..write('pinned: $pinned, ') - ..write('archived: $archived, ') - ..write('lastMessageExchange: $lastMessageExchange, ') - ..write('createdAt: $createdAt') - ..write(')')) - .toString(); - } - - @override - int get hashCode => Object.hash(groupId, isGroupAdmin, isGroupOfTwo, pinned, - archived, lastMessageExchange, createdAt); - @override - bool operator ==(Object other) => - identical(this, other) || - (other is Group && - other.groupId == this.groupId && - other.isGroupAdmin == this.isGroupAdmin && - other.isGroupOfTwo == this.isGroupOfTwo && - other.pinned == this.pinned && - other.archived == this.archived && - other.lastMessageExchange == this.lastMessageExchange && - other.createdAt == this.createdAt); -} - -class GroupsCompanion extends UpdateCompanion { - final Value groupId; - final Value isGroupAdmin; - final Value isGroupOfTwo; - final Value pinned; - final Value archived; - final Value lastMessageExchange; - final Value createdAt; - final Value rowid; - const GroupsCompanion({ - this.groupId = const Value.absent(), - this.isGroupAdmin = const Value.absent(), - this.isGroupOfTwo = const Value.absent(), - this.pinned = const Value.absent(), - this.archived = const Value.absent(), - this.lastMessageExchange = const Value.absent(), - this.createdAt = const Value.absent(), - this.rowid = const Value.absent(), - }); - GroupsCompanion.insert({ - this.groupId = const Value.absent(), - required bool isGroupAdmin, - required bool isGroupOfTwo, - this.pinned = const Value.absent(), - this.archived = const Value.absent(), - this.lastMessageExchange = const Value.absent(), - this.createdAt = const Value.absent(), - this.rowid = const Value.absent(), - }) : isGroupAdmin = Value(isGroupAdmin), - isGroupOfTwo = Value(isGroupOfTwo); - static Insertable custom({ - Expression? groupId, - Expression? isGroupAdmin, - Expression? isGroupOfTwo, - Expression? pinned, - Expression? archived, - Expression? lastMessageExchange, - Expression? createdAt, - Expression? rowid, - }) { - return RawValuesInsertable({ - if (groupId != null) 'group_id': groupId, - if (isGroupAdmin != null) 'is_group_admin': isGroupAdmin, - if (isGroupOfTwo != null) 'is_group_of_two': isGroupOfTwo, - if (pinned != null) 'pinned': pinned, - if (archived != null) 'archived': archived, - if (lastMessageExchange != null) - 'last_message_exchange': lastMessageExchange, - if (createdAt != null) 'created_at': createdAt, - if (rowid != null) 'rowid': rowid, - }); - } - - GroupsCompanion copyWith( - {Value? groupId, - Value? isGroupAdmin, - Value? isGroupOfTwo, - Value? pinned, - Value? archived, - Value? lastMessageExchange, - Value? createdAt, - Value? rowid}) { - return GroupsCompanion( - groupId: groupId ?? this.groupId, - isGroupAdmin: isGroupAdmin ?? this.isGroupAdmin, - isGroupOfTwo: isGroupOfTwo ?? this.isGroupOfTwo, - pinned: pinned ?? this.pinned, - archived: archived ?? this.archived, - lastMessageExchange: lastMessageExchange ?? this.lastMessageExchange, - createdAt: createdAt ?? this.createdAt, - rowid: rowid ?? this.rowid, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (groupId.present) { - map['group_id'] = Variable(groupId.value); - } - if (isGroupAdmin.present) { - map['is_group_admin'] = Variable(isGroupAdmin.value); - } - if (isGroupOfTwo.present) { - map['is_group_of_two'] = Variable(isGroupOfTwo.value); - } - if (pinned.present) { - map['pinned'] = Variable(pinned.value); - } - if (archived.present) { - map['archived'] = Variable(archived.value); - } - if (lastMessageExchange.present) { - map['last_message_exchange'] = - Variable(lastMessageExchange.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (rowid.present) { - map['rowid'] = Variable(rowid.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('GroupsCompanion(') - ..write('groupId: $groupId, ') - ..write('isGroupAdmin: $isGroupAdmin, ') - ..write('isGroupOfTwo: $isGroupOfTwo, ') - ..write('pinned: $pinned, ') - ..write('archived: $archived, ') - ..write('lastMessageExchange: $lastMessageExchange, ') - ..write('createdAt: $createdAt, ') - ..write('rowid: $rowid') - ..write(')')) - .toString(); - } -} - class $GroupMembersTable extends GroupMembers with TableInfo<$GroupMembersTable, GroupMember> { @override @@ -5810,12 +5813,12 @@ abstract class _$TwonlyDB extends GeneratedDatabase { _$TwonlyDB(QueryExecutor e) : super(e); $TwonlyDBManager get managers => $TwonlyDBManager(this); late final $ContactsTable contacts = $ContactsTable(this); + late final $GroupsTable groups = $GroupsTable(this); late final $MediaFilesTable mediaFiles = $MediaFilesTable(this); late final $MessagesTable messages = $MessagesTable(this); late final $MessageHistoriesTable messageHistories = $MessageHistoriesTable(this); late final $ReactionsTable reactions = $ReactionsTable(this); - late final $GroupsTable groups = $GroupsTable(this); late final $GroupMembersTable groupMembers = $GroupMembersTable(this); late final $ReceiptsTable receipts = $ReceiptsTable(this); late final $SignalIdentityKeyStoresTable signalIdentityKeyStores = @@ -5843,11 +5846,11 @@ abstract class _$TwonlyDB extends GeneratedDatabase { @override List get allSchemaEntities => [ contacts, + groups, mediaFiles, messages, messageHistories, reactions, - groups, groupMembers, receipts, signalIdentityKeyStores, @@ -5860,6 +5863,13 @@ abstract class _$TwonlyDB extends GeneratedDatabase { @override StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules( [ + WritePropagation( + on: TableUpdateQuery.onTableName('groups', + limitUpdateKind: UpdateKind.delete), + result: [ + TableUpdate('messages', kind: UpdateKind.delete), + ], + ), WritePropagation( on: TableUpdateQuery.onTableName('messages', limitUpdateKind: UpdateKind.delete), @@ -6809,6 +6819,287 @@ typedef $$ContactsTableProcessedTableManager = ProcessedTableManager< bool receiptsRefs, bool signalContactPreKeysRefs, bool signalContactSignedPreKeysRefs})>; +typedef $$GroupsTableCreateCompanionBuilder = GroupsCompanion Function({ + Value groupId, + required bool isGroupAdmin, + required bool isGroupOfTwo, + Value pinned, + Value archived, + Value lastMessageExchange, + Value createdAt, + Value rowid, +}); +typedef $$GroupsTableUpdateCompanionBuilder = GroupsCompanion Function({ + Value groupId, + Value isGroupAdmin, + Value isGroupOfTwo, + Value pinned, + Value archived, + Value lastMessageExchange, + Value createdAt, + Value rowid, +}); + +final class $$GroupsTableReferences + extends BaseReferences<_$TwonlyDB, $GroupsTable, Group> { + $$GroupsTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$MessagesTable, List> _messagesRefsTable( + _$TwonlyDB db) => + MultiTypedResultKey.fromTable(db.messages, + aliasName: + $_aliasNameGenerator(db.groups.groupId, db.messages.groupId)); + + $$MessagesTableProcessedTableManager get messagesRefs { + final manager = $$MessagesTableTableManager($_db, $_db.messages).filter( + (f) => f.groupId.groupId.sqlEquals($_itemColumn('group_id')!)); + + final cache = $_typedResult.readTableOrNull(_messagesRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache)); + } +} + +class $$GroupsTableFilterComposer extends Composer<_$TwonlyDB, $GroupsTable> { + $$GroupsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get groupId => $composableBuilder( + column: $table.groupId, builder: (column) => ColumnFilters(column)); + + ColumnFilters get isGroupAdmin => $composableBuilder( + column: $table.isGroupAdmin, builder: (column) => ColumnFilters(column)); + + ColumnFilters get isGroupOfTwo => $composableBuilder( + column: $table.isGroupOfTwo, builder: (column) => ColumnFilters(column)); + + ColumnFilters get pinned => $composableBuilder( + column: $table.pinned, builder: (column) => ColumnFilters(column)); + + ColumnFilters get archived => $composableBuilder( + column: $table.archived, builder: (column) => ColumnFilters(column)); + + ColumnFilters get lastMessageExchange => $composableBuilder( + column: $table.lastMessageExchange, + builder: (column) => ColumnFilters(column)); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnFilters(column)); + + Expression messagesRefs( + Expression Function($$MessagesTableFilterComposer f) f) { + final $$MessagesTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.groupId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableFilterComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$GroupsTableOrderingComposer extends Composer<_$TwonlyDB, $GroupsTable> { + $$GroupsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get groupId => $composableBuilder( + column: $table.groupId, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get isGroupAdmin => $composableBuilder( + column: $table.isGroupAdmin, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get isGroupOfTwo => $composableBuilder( + column: $table.isGroupOfTwo, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get pinned => $composableBuilder( + column: $table.pinned, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get archived => $composableBuilder( + column: $table.archived, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get lastMessageExchange => $composableBuilder( + column: $table.lastMessageExchange, + builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, builder: (column) => ColumnOrderings(column)); +} + +class $$GroupsTableAnnotationComposer + extends Composer<_$TwonlyDB, $GroupsTable> { + $$GroupsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get groupId => + $composableBuilder(column: $table.groupId, builder: (column) => column); + + GeneratedColumn get isGroupAdmin => $composableBuilder( + column: $table.isGroupAdmin, builder: (column) => column); + + GeneratedColumn get isGroupOfTwo => $composableBuilder( + column: $table.isGroupOfTwo, builder: (column) => column); + + GeneratedColumn get pinned => + $composableBuilder(column: $table.pinned, builder: (column) => column); + + GeneratedColumn get archived => + $composableBuilder(column: $table.archived, builder: (column) => column); + + GeneratedColumn get lastMessageExchange => $composableBuilder( + column: $table.lastMessageExchange, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + Expression messagesRefs( + Expression Function($$MessagesTableAnnotationComposer a) f) { + final $$MessagesTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.messages, + getReferencedColumn: (t) => t.groupId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$MessagesTableAnnotationComposer( + $db: $db, + $table: $db.messages, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return f(composer); + } +} + +class $$GroupsTableTableManager extends RootTableManager< + _$TwonlyDB, + $GroupsTable, + Group, + $$GroupsTableFilterComposer, + $$GroupsTableOrderingComposer, + $$GroupsTableAnnotationComposer, + $$GroupsTableCreateCompanionBuilder, + $$GroupsTableUpdateCompanionBuilder, + (Group, $$GroupsTableReferences), + Group, + PrefetchHooks Function({bool messagesRefs})> { + $$GroupsTableTableManager(_$TwonlyDB db, $GroupsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$GroupsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$GroupsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$GroupsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value groupId = const Value.absent(), + Value isGroupAdmin = const Value.absent(), + Value isGroupOfTwo = const Value.absent(), + Value pinned = const Value.absent(), + Value archived = const Value.absent(), + Value lastMessageExchange = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + GroupsCompanion( + groupId: groupId, + isGroupAdmin: isGroupAdmin, + isGroupOfTwo: isGroupOfTwo, + pinned: pinned, + archived: archived, + lastMessageExchange: lastMessageExchange, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: ({ + Value groupId = const Value.absent(), + required bool isGroupAdmin, + required bool isGroupOfTwo, + Value pinned = const Value.absent(), + Value archived = const Value.absent(), + Value lastMessageExchange = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => + GroupsCompanion.insert( + groupId: groupId, + isGroupAdmin: isGroupAdmin, + isGroupOfTwo: isGroupOfTwo, + pinned: pinned, + archived: archived, + lastMessageExchange: lastMessageExchange, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map((e) => + (e.readTable(table), $$GroupsTableReferences(db, table, e))) + .toList(), + prefetchHooksCallback: ({messagesRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [if (messagesRefs) db.messages], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (messagesRefs) + await $_getPrefetchedData( + currentTable: table, + referencedTable: + $$GroupsTableReferences._messagesRefsTable(db), + managerFromTypedResult: (p0) => + $$GroupsTableReferences(db, table, p0).messagesRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems + .where((e) => e.groupId == item.groupId), + typedResults: items) + ]; + }, + ); + }, + )); +} + +typedef $$GroupsTableProcessedTableManager = ProcessedTableManager< + _$TwonlyDB, + $GroupsTable, + Group, + $$GroupsTableFilterComposer, + $$GroupsTableOrderingComposer, + $$GroupsTableAnnotationComposer, + $$GroupsTableCreateCompanionBuilder, + $$GroupsTableUpdateCompanionBuilder, + (Group, $$GroupsTableReferences), + Group, + PrefetchHooks Function({bool messagesRefs})>; typedef $$MediaFilesTableCreateCompanionBuilder = MediaFilesCompanion Function({ Value mediaId, required MediaType type, @@ -7262,6 +7553,20 @@ final class $$MessagesTableReferences extends BaseReferences<_$TwonlyDB, $MessagesTable, Message> { $$MessagesTableReferences(super.$_db, super.$_table, super.$_typedResult); + static $GroupsTable _groupIdTable(_$TwonlyDB db) => db.groups.createAlias( + $_aliasNameGenerator(db.messages.groupId, db.groups.groupId)); + + $$GroupsTableProcessedTableManager get groupId { + final $_column = $_itemColumn('group_id')!; + + final manager = $$GroupsTableTableManager($_db, $_db.groups) + .filter((f) => f.groupId.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_groupIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item])); + } + static $ContactsTable _senderIdTable(_$TwonlyDB db) => db.contacts.createAlias( $_aliasNameGenerator(db.messages.senderId, db.contacts.userId)); @@ -7367,9 +7672,6 @@ class $$MessagesTableFilterComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - ColumnFilters get groupId => $composableBuilder( - column: $table.groupId, builder: (column) => ColumnFilters(column)); - ColumnFilters get messageId => $composableBuilder( column: $table.messageId, builder: (column) => ColumnFilters(column)); @@ -7402,6 +7704,26 @@ class $$MessagesTableFilterComposer ColumnFilters get modifiedAt => $composableBuilder( column: $table.modifiedAt, builder: (column) => ColumnFilters(column)); + $$GroupsTableFilterComposer get groupId { + final $$GroupsTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groups, + getReferencedColumn: (t) => t.groupId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$GroupsTableFilterComposer( + $db: $db, + $table: $db.groups, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + $$ContactsTableFilterComposer get senderId { final $$ContactsTableFilterComposer composer = $composerBuilder( composer: this, @@ -7535,9 +7857,6 @@ class $$MessagesTableOrderingComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - ColumnOrderings get groupId => $composableBuilder( - column: $table.groupId, builder: (column) => ColumnOrderings(column)); - ColumnOrderings get messageId => $composableBuilder( column: $table.messageId, builder: (column) => ColumnOrderings(column)); @@ -7570,6 +7889,26 @@ class $$MessagesTableOrderingComposer ColumnOrderings get modifiedAt => $composableBuilder( column: $table.modifiedAt, builder: (column) => ColumnOrderings(column)); + $$GroupsTableOrderingComposer get groupId { + final $$GroupsTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groups, + getReferencedColumn: (t) => t.groupId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$GroupsTableOrderingComposer( + $db: $db, + $table: $db.groups, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + $$ContactsTableOrderingComposer get senderId { final $$ContactsTableOrderingComposer composer = $composerBuilder( composer: this, @@ -7640,9 +7979,6 @@ class $$MessagesTableAnnotationComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); - GeneratedColumn get groupId => - $composableBuilder(column: $table.groupId, builder: (column) => column); - GeneratedColumn get messageId => $composableBuilder(column: $table.messageId, builder: (column) => column); @@ -7673,6 +8009,26 @@ class $$MessagesTableAnnotationComposer GeneratedColumn get modifiedAt => $composableBuilder( column: $table.modifiedAt, builder: (column) => column); + $$GroupsTableAnnotationComposer get groupId { + final $$GroupsTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groups, + getReferencedColumn: (t) => t.groupId, + builder: (joinBuilder, + {$addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer}) => + $$GroupsTableAnnotationComposer( + $db: $db, + $table: $db.groups, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + )); + return composer; + } + $$ContactsTableAnnotationComposer get senderId { final $$ContactsTableAnnotationComposer composer = $composerBuilder( composer: this, @@ -7809,7 +8165,8 @@ class $$MessagesTableTableManager extends RootTableManager< (Message, $$MessagesTableReferences), Message, PrefetchHooks Function( - {bool senderId, + {bool groupId, + bool senderId, bool mediaId, bool quotesMessageId, bool messageHistoriesRefs, @@ -7898,7 +8255,8 @@ class $$MessagesTableTableManager extends RootTableManager< (e.readTable(table), $$MessagesTableReferences(db, table, e))) .toList(), prefetchHooksCallback: ( - {senderId = false, + {groupId = false, + senderId = false, mediaId = false, quotesMessageId = false, messageHistoriesRefs = false, @@ -7924,6 +8282,16 @@ class $$MessagesTableTableManager extends RootTableManager< dynamic, dynamic, dynamic>>(state) { + if (groupId) { + state = state.withJoin( + currentTable: table, + currentColumn: table.groupId, + referencedTable: + $$MessagesTableReferences._groupIdTable(db), + referencedColumn: + $$MessagesTableReferences._groupIdTable(db).groupId, + ) as T; + } if (senderId) { state = state.withJoin( currentTable: table, @@ -8017,7 +8385,8 @@ typedef $$MessagesTableProcessedTableManager = ProcessedTableManager< (Message, $$MessagesTableReferences), Message, PrefetchHooks Function( - {bool senderId, + {bool groupId, + bool senderId, bool mediaId, bool quotesMessageId, bool messageHistoriesRefs, @@ -8606,203 +8975,6 @@ typedef $$ReactionsTableProcessedTableManager = ProcessedTableManager< (Reaction, $$ReactionsTableReferences), Reaction, PrefetchHooks Function({bool messageId, bool senderId})>; -typedef $$GroupsTableCreateCompanionBuilder = GroupsCompanion Function({ - Value groupId, - required bool isGroupAdmin, - required bool isGroupOfTwo, - Value pinned, - Value archived, - Value lastMessageExchange, - Value createdAt, - Value rowid, -}); -typedef $$GroupsTableUpdateCompanionBuilder = GroupsCompanion Function({ - Value groupId, - Value isGroupAdmin, - Value isGroupOfTwo, - Value pinned, - Value archived, - Value lastMessageExchange, - Value createdAt, - Value rowid, -}); - -class $$GroupsTableFilterComposer extends Composer<_$TwonlyDB, $GroupsTable> { - $$GroupsTableFilterComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - ColumnFilters get groupId => $composableBuilder( - column: $table.groupId, builder: (column) => ColumnFilters(column)); - - ColumnFilters get isGroupAdmin => $composableBuilder( - column: $table.isGroupAdmin, builder: (column) => ColumnFilters(column)); - - ColumnFilters get isGroupOfTwo => $composableBuilder( - column: $table.isGroupOfTwo, builder: (column) => ColumnFilters(column)); - - ColumnFilters get pinned => $composableBuilder( - column: $table.pinned, builder: (column) => ColumnFilters(column)); - - ColumnFilters get archived => $composableBuilder( - column: $table.archived, builder: (column) => ColumnFilters(column)); - - ColumnFilters get lastMessageExchange => $composableBuilder( - column: $table.lastMessageExchange, - builder: (column) => ColumnFilters(column)); - - ColumnFilters get createdAt => $composableBuilder( - column: $table.createdAt, builder: (column) => ColumnFilters(column)); -} - -class $$GroupsTableOrderingComposer extends Composer<_$TwonlyDB, $GroupsTable> { - $$GroupsTableOrderingComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - ColumnOrderings get groupId => $composableBuilder( - column: $table.groupId, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get isGroupAdmin => $composableBuilder( - column: $table.isGroupAdmin, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get isGroupOfTwo => $composableBuilder( - column: $table.isGroupOfTwo, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get pinned => $composableBuilder( - column: $table.pinned, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get archived => $composableBuilder( - column: $table.archived, builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get lastMessageExchange => $composableBuilder( - column: $table.lastMessageExchange, - builder: (column) => ColumnOrderings(column)); - - ColumnOrderings get createdAt => $composableBuilder( - column: $table.createdAt, builder: (column) => ColumnOrderings(column)); -} - -class $$GroupsTableAnnotationComposer - extends Composer<_$TwonlyDB, $GroupsTable> { - $$GroupsTableAnnotationComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - GeneratedColumn get groupId => - $composableBuilder(column: $table.groupId, builder: (column) => column); - - GeneratedColumn get isGroupAdmin => $composableBuilder( - column: $table.isGroupAdmin, builder: (column) => column); - - GeneratedColumn get isGroupOfTwo => $composableBuilder( - column: $table.isGroupOfTwo, builder: (column) => column); - - GeneratedColumn get pinned => - $composableBuilder(column: $table.pinned, builder: (column) => column); - - GeneratedColumn get archived => - $composableBuilder(column: $table.archived, builder: (column) => column); - - GeneratedColumn get lastMessageExchange => $composableBuilder( - column: $table.lastMessageExchange, builder: (column) => column); - - GeneratedColumn get createdAt => - $composableBuilder(column: $table.createdAt, builder: (column) => column); -} - -class $$GroupsTableTableManager extends RootTableManager< - _$TwonlyDB, - $GroupsTable, - Group, - $$GroupsTableFilterComposer, - $$GroupsTableOrderingComposer, - $$GroupsTableAnnotationComposer, - $$GroupsTableCreateCompanionBuilder, - $$GroupsTableUpdateCompanionBuilder, - (Group, BaseReferences<_$TwonlyDB, $GroupsTable, Group>), - Group, - PrefetchHooks Function()> { - $$GroupsTableTableManager(_$TwonlyDB db, $GroupsTable table) - : super(TableManagerState( - db: db, - table: table, - createFilteringComposer: () => - $$GroupsTableFilterComposer($db: db, $table: table), - createOrderingComposer: () => - $$GroupsTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: () => - $$GroupsTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: ({ - Value groupId = const Value.absent(), - Value isGroupAdmin = const Value.absent(), - Value isGroupOfTwo = const Value.absent(), - Value pinned = const Value.absent(), - Value archived = const Value.absent(), - Value lastMessageExchange = const Value.absent(), - Value createdAt = const Value.absent(), - Value rowid = const Value.absent(), - }) => - GroupsCompanion( - groupId: groupId, - isGroupAdmin: isGroupAdmin, - isGroupOfTwo: isGroupOfTwo, - pinned: pinned, - archived: archived, - lastMessageExchange: lastMessageExchange, - createdAt: createdAt, - rowid: rowid, - ), - createCompanionCallback: ({ - Value groupId = const Value.absent(), - required bool isGroupAdmin, - required bool isGroupOfTwo, - Value pinned = const Value.absent(), - Value archived = const Value.absent(), - Value lastMessageExchange = const Value.absent(), - Value createdAt = const Value.absent(), - Value rowid = const Value.absent(), - }) => - GroupsCompanion.insert( - groupId: groupId, - isGroupAdmin: isGroupAdmin, - isGroupOfTwo: isGroupOfTwo, - pinned: pinned, - archived: archived, - lastMessageExchange: lastMessageExchange, - createdAt: createdAt, - rowid: rowid, - ), - withReferenceMapper: (p0) => p0 - .map((e) => (e.readTable(table), BaseReferences(db, table, e))) - .toList(), - prefetchHooksCallback: null, - )); -} - -typedef $$GroupsTableProcessedTableManager = ProcessedTableManager< - _$TwonlyDB, - $GroupsTable, - Group, - $$GroupsTableFilterComposer, - $$GroupsTableOrderingComposer, - $$GroupsTableAnnotationComposer, - $$GroupsTableCreateCompanionBuilder, - $$GroupsTableUpdateCompanionBuilder, - (Group, BaseReferences<_$TwonlyDB, $GroupsTable, Group>), - Group, - PrefetchHooks Function()>; typedef $$GroupMembersTableCreateCompanionBuilder = GroupMembersCompanion Function({ required String groupId, @@ -10636,6 +10808,8 @@ class $TwonlyDBManager { $TwonlyDBManager(this._db); $$ContactsTableTableManager get contacts => $$ContactsTableTableManager(_db, _db.contacts); + $$GroupsTableTableManager get groups => + $$GroupsTableTableManager(_db, _db.groups); $$MediaFilesTableTableManager get mediaFiles => $$MediaFilesTableTableManager(_db, _db.mediaFiles); $$MessagesTableTableManager get messages => @@ -10644,8 +10818,6 @@ class $TwonlyDBManager { $$MessageHistoriesTableTableManager(_db, _db.messageHistories); $$ReactionsTableTableManager get reactions => $$ReactionsTableTableManager(_db, _db.reactions); - $$GroupsTableTableManager get groups => - $$GroupsTableTableManager(_db, _db.groups); $$GroupMembersTableTableManager get groupMembers => $$GroupMembersTableTableManager(_db, _db.groupMembers); $$ReceiptsTableTableManager get receipts => diff --git a/lib/src/services/api/utils.dart b/lib/src/services/api/utils.dart index c5b119a..af05082 100644 --- a/lib/src/services/api/utils.dart +++ b/lib/src/services/api/utils.dart @@ -1,15 +1,16 @@ import 'package:drift/drift.dart'; import 'package:fixnum/fixnum.dart'; import 'package:twonly/globals.dart'; -import 'package:twonly/src/database/tables/messages_table.dart'; +import 'package:twonly/src/database/tables/mediafiles.table.dart'; import 'package:twonly/src/database/twonly.db.dart'; -import 'package:twonly/src/model/json/message_old.dart'; import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pb.dart' as client; import 'package:twonly/src/model/protobuf/api/websocket/client_to_server.pbserver.dart'; import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart'; import 'package:twonly/src/model/protobuf/api/websocket/server_to_client.pb.dart' as server; +import 'package:twonly/src/model/protobuf/client/generated/messages.pbserver.dart' + hide Message; import 'package:twonly/src/services/api/messages.dart'; import 'package:twonly/src/services/signal/session.signal.dart'; @@ -57,44 +58,41 @@ ClientToServer createClientToServerFromApplicationData( } Future deleteContact(int contactId) async { - await twonlyDB.messagesDao.deleteAllMessagesByContactId(contactId); await twonlyDB.signalDao.deleteAllByContactId(contactId); await deleteSessionWithTarget(contactId); await twonlyDB.contactsDao.deleteContactByUserId(contactId); } Future rejectUser(int contactId) async { - await encryptAndSendMessageAsync( - null, + await sendCipherText( contactId, - MessageJson( - kind: MessageKind.rejectRequest, - timestamp: DateTime.now(), - content: MessageContent(), + EncryptedContent( + contactRequest: EncryptedContent_ContactRequest( + type: EncryptedContent_ContactRequest_Type.REJECT, + ), ), ); } -Future handleMediaError(Message message) async { - await twonlyDB.messagesDao.updateMessageByMessageId( - message.messageId, - const MessagesCompanion( - errorWhileSending: Value(true), - mediaRetransmissionState: Value( - MediaRetransmitting.requested, +Future handleMediaError(MediaFile media) async { + await twonlyDB.mediaFilesDao.updateMedia( + media.mediaId, + const MediaFilesCompanion( + downloadState: Value(DownloadState.reuploadRequested), + ), + ); + final messages = + await twonlyDB.messagesDao.getMessagesByMediaId(media.mediaId); + if (messages.length != 1) return; + final message = messages.first; + if (message.senderId == null) return; + await sendCipherText( + message.senderId!, + EncryptedContent( + mediaUpdate: EncryptedContent_MediaUpdate( + type: EncryptedContent_MediaUpdate_Type.DECRYPTION_ERROR, + targetMessageId: message.messageId, ), ), ); - if (message.messageOtherId != null) { - await encryptAndSendMessageAsync( - null, - message.contactId, - MessageJson( - kind: MessageKind.receiveMediaError, - timestamp: DateTime.now(), - content: MessageContent(), - messageReceiverId: message.messageOtherId, - ), - ); - } } diff --git a/lib/src/services/flame.service.dart b/lib/src/services/flame.service.dart index 929dc0b..1f98386 100644 --- a/lib/src/services/flame.service.dart +++ b/lib/src/services/flame.service.dart @@ -1,10 +1,10 @@ import 'package:collection/collection.dart'; import 'package:drift/drift.dart'; +import 'package:fixnum/fixnum.dart'; import 'package:twonly/globals.dart'; import 'package:twonly/src/database/daos/contacts.dao.dart'; -import 'package:twonly/src/database/tables/messages_table.dart'; import 'package:twonly/src/database/twonly.db.dart'; -import 'package:twonly/src/model/json/message_old.dart' as my; +import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart'; import 'package:twonly/src/services/api/messages.dart'; import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/storage.dart'; @@ -38,17 +38,15 @@ Future syncFlameCounters() async { // only sync when flame counter is higher than three days if (flameCounter < 1 && bestFriend.userId != contact.userId) continue; - await encryptAndSendMessageAsync( - null, + await sendCipherText( contact.userId, - my.MessageJson( - kind: MessageKind.flameSync, - content: my.FlameSyncContent( - flameCounter: flameCounter, - lastFlameCounterChange: contact.lastFlameCounterChange!, + EncryptedContent( + flameSync: EncryptedContent_FlameSync( + flameCounter: Int64(flameCounter), + lastFlameCounterChange: + Int64(contact.lastFlameCounterChange!.millisecondsSinceEpoch), bestFriend: contact.userId == bestFriend.userId, ), - timestamp: DateTime.now(), ), ); diff --git a/lib/src/services/notifications/background.notifications.dart b/lib/src/services/notifications/background.notifications.dart index fde1e92..a675212 100644 --- a/lib/src/services/notifications/background.notifications.dart +++ b/lib/src/services/notifications/background.notifications.dart @@ -7,9 +7,11 @@ import 'package:cryptography_plus/cryptography_plus.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:path_provider/path_provider.dart'; import 'package:twonly/src/constants/secure_storage_keys.dart'; +import 'package:twonly/src/model/protobuf/client/generated/push_notification.pb.dart'; import 'package:twonly/src/model/protobuf/client/generated/push_notification.pbenum.dart'; import 'package:twonly/src/services/notifications/pushkeys.notifications.dart'; import 'package:twonly/src/utils/log.dart'; +import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/views/camera/share_image_editor_view.dart' show gMediaShowInfinite; @@ -75,7 +77,10 @@ Future handlePushData(String pushDataB64) async { ); } else if (foundPushUser != null) { if (pushNotification.hasMessageId()) { - if (pushNotification.messageId <= foundPushUser.lastMessageId) { + if (isUUIDNewer( + foundPushUser.lastMessageId, + pushNotification.messageId, + )) { Log.info( 'Got a push notification for a message which was already opened.', );