removed unused functions
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run

This commit is contained in:
otsmr 2026-08-28 14:52:28 +02:00
parent bd65268dd2
commit b09d79f5d6
9 changed files with 27 additions and 578 deletions

View file

@ -12,17 +12,7 @@ class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
// of this object. // of this object.
// ignore: matching_super_parameters // ignore: matching_super_parameters
ContactsDao(super.db); ContactsDao(super.db);
Future<int> insertOnConflictUpdate(ContactsCompanion contact) async {
Future<int?> insertContact(ContactsCompanion contact) async {
try {
return await into(contacts).insert(contact);
} catch (e) {
Log.error(e);
return null;
}
}
Future<int> insertOnConflictUpdate(ContactsCompanion contact) async {
try { try {
return await into(contacts).insertOnConflictUpdate(contact); return await into(contacts).insertOnConflictUpdate(contact);
} catch (e) { } catch (e) {
@ -174,27 +164,7 @@ class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
})) }))
.watch(); .watch();
} }
Stream<List<Contact>> watchAllContacts() {
Future<List<Contact>> getContactsAnnouncedViaUserDiscovery() async {
return (select(contacts)..where((t) {
var expr =
t.userDiscoveryVersion.isNotNull() &
t.userDiscoveryExcluded.equals(false) &
t.accountDeleted.equals(false) &
t.mediaSendCounter.isBiggerOrEqualValue(
userService.currentUser.requiredSendImages,
);
if (userService.currentUser.userDiscoveryRequiresManualApproval) {
expr = expr & t.userDiscoveryManualApproved.equals(true);
}
return expr;
}))
.get();
}
Stream<List<Contact>> watchAllContacts() {
return select(contacts).watch(); return select(contacts).watch();
} }
} }

View file

@ -2,11 +2,9 @@ import 'package:clock/clock.dart' show clock;
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:hashlib/random.dart'; import 'package:hashlib/random.dart';
import 'package:twonly/locator.dart'; import 'package:twonly/locator.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/tables/groups.table.dart'; import 'package:twonly/src/database/tables/groups.table.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/flame.service.dart'; import 'package:twonly/src/services/flame.service.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
part 'groups.dao.g.dart'; part 'groups.dao.g.dart';
@ -23,17 +21,7 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
// of this object. // of this object.
// ignore: matching_super_parameters // ignore: matching_super_parameters
GroupsDao(super.db); GroupsDao(super.db);
Future<void> deleteGroup(String groupId) async {
Future<bool> isContactInGroup(int contactId, String groupId) async {
final entry =
await (select(groupMembers)..where(
(t) => t.contactId.equals(contactId) & t.groupId.equals(groupId),
))
.getSingleOrNull();
return entry != null;
}
Future<void> deleteGroup(String groupId) async {
await (delete(groups)..where((t) => t.groupId.equals(groupId))).go(); await (delete(groups)..where((t) => t.groupId.equals(groupId))).go();
} }
@ -61,22 +49,10 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
groupMembers, groupMembers,
)..where((t) => t.groupId.equals(groupId))).get(); )..where((t) => t.groupId.equals(groupId))).get();
} }
Future<Group?> createNewGroup(GroupsCompanion group) async {
Future<GroupMember?> getGroupMemberByPublicKey(Uint8List publicKey) async {
return (select(
groupMembers,
)..where((t) => t.groupPublicKey.equals(publicKey))).getSingleOrNull();
}
Future<Group?> createNewGroup(GroupsCompanion group) async {
return _insertGroup(group); return _insertGroup(group);
} }
Future<void> insertGroupAction(GroupHistoriesCompanion action) async {
Future<void> insertOrUpdateGroupMember(GroupMembersCompanion members) async {
await into(groupMembers).insertOnConflictUpdate(members);
}
Future<void> insertGroupAction(GroupHistoriesCompanion action) async {
var insertAction = action; var insertAction = action;
if (!action.groupHistoryId.present) { if (!action.groupHistoryId.present) {
insertAction = action.copyWith( insertAction = action.copyWith(
@ -101,26 +77,7 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
..orderBy([(t) => OrderingTerm.asc(t.actionAt)])) ..orderBy([(t) => OrderingTerm.asc(t.actionAt)]))
.watch(); .watch();
} }
Future<Group?> createNewDirectChat(
Future<void> updateMember(
String groupId,
int contactId,
GroupMembersCompanion updates,
) async {
await (update(groupMembers)..where(
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
))
.write(updates);
}
Future<void> removeMember(String groupId, int contactId) async {
await (delete(groupMembers)..where(
(c) => c.groupId.equals(groupId) & c.contactId.equals(contactId),
))
.go();
}
Future<Group?> createNewDirectChat(
int contactId, int contactId,
GroupsCompanion group, GroupsCompanion group,
) async { ) async {
@ -231,18 +188,7 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
groups, groups,
)..where((t) => t.groupId.equals(groupId))).watchSingleOrNull(); )..where((t) => t.groupId.equals(groupId))).watchSingleOrNull();
} }
Stream<List<Group>> watchGroupsForChatList() {
Stream<Group?> watchDirectChat(int contactId) {
final groupId = getUUIDforDirectChat(
contactId,
userService.currentUser.userId,
);
return (select(
groups,
)..where((t) => t.groupId.equals(groupId))).watchSingleOrNull();
}
Stream<List<Group>> watchGroupsForChatList() {
return (select(groups) return (select(groups)
..where((t) => t.deletedContent.equals(false)) ..where((t) => t.deletedContent.equals(false))
..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)])) ..orderBy([(t) => OrderingTerm.desc(t.lastMessageExchange)]))
@ -280,33 +226,7 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
Future<List<Group>> getAllGroups() { Future<List<Group>> getAllGroups() {
return select(groups).get(); return select(groups).get();
} }
Future<Group?> getDirectChat(int userId) async {
Future<List<Group>> getAllNotJoinedGroups() {
return (select(groups)..where(
(t) => t.joinedGroup.equals(false) & t.isDirectChat.equals(false),
))
.get();
}
Future<List<GroupMember>> getAllGroupMemberWithoutPublicKey() async {
try {
final query =
((select(groupMembers)..where((t) => t.groupPublicKey.isNull())).join(
[
leftOuterJoin(
groups,
groups.groupId.equalsExp(groupMembers.groupId),
),
],
)..where(groups.isDirectChat.equals(false)));
return await query.map((row) => row.readTable(groupMembers)).get();
} catch (e) {
Log.error(e);
return [];
}
}
Future<Group?> getDirectChat(int userId) async {
final query = final query =
((select(groups)..where((t) => t.isDirectChat.equals(true))).join([ ((select(groups)..where((t) => t.isDirectChat.equals(true))).join([
leftOuterJoin( leftOuterJoin(
@ -317,29 +237,7 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
return query.map((row) => row.readTable(groups)).getSingleOrNull(); return query.map((row) => row.readTable(groups)).getSingleOrNull();
} }
Stream<int> watchSumTotalMediaCounter() {
Future<Group?> createOrGetDirectChat(int contactId) async {
var directChat = await getDirectChat(contactId);
if (directChat == null) {
final contact = await attachedDatabase.contactsDao.getContactById(
contactId,
);
if (contact == null) {
Log.error('Contact $contactId not found, cannot create direct chat');
return null;
}
await createNewDirectChat(
contactId,
GroupsCompanion(
groupName: Value(getContactDisplayName(contact)),
),
);
directChat = await getDirectChat(contactId);
}
return directChat;
}
Stream<int> watchSumTotalMediaCounter() {
final query = selectOnly(groups) final query = selectOnly(groups)
..addColumns([groups.totalMediaCounter.sum()]); ..addColumns([groups.totalMediaCounter.sum()]);
return query.watch().map((rows) { return query.watch().map((rows) {
@ -397,18 +295,4 @@ class GroupsDao extends DatabaseAccessor<TwonlyDB> with _$GroupsDaoMixin {
return query.map((row) => row.readTable(groups)).watch(); return query.map((row) => row.readTable(groups)).watch();
} }
Future<List<Group>> getGroupsForMember(int contactId) {
final query =
select(groups).join([
innerJoin(
groupMembers,
groupMembers.groupId.equalsExp(groups.groupId),
),
])..where(
groupMembers.contactId.equals(contactId),
);
return query.map((row) => row.readTable(groups)).get();
}
} }

View file

@ -43,42 +43,7 @@ class KeyVerificationDao extends DatabaseAccessor<TwonlyDB>
/// Returns a map of contactId the verification type of the earliest /// Returns a map of contactId the verification type of the earliest
/// [KeyVerification] row for that contact. /// [KeyVerification] row for that contact.
Future<Map<int, VerificationType>> Stream<List<(KeyVerification, Contact?)>> watchContactVerification(
getFirstVerificationTypeByContacts() async {
final rows = await (select(
keyVerifications,
)..orderBy([(kv) => OrderingTerm.asc(kv.createdAt)])).get();
final result = <int, VerificationType>{};
for (final row in rows) {
result.putIfAbsent(row.contactId, () => row.type);
}
return result;
}
Future<bool> isContactVerified(int contactId) async {
final verifierKv = alias(keyVerifications, 'verifierKv');
final query = select(keyVerifications).join([
leftOuterJoin(
verifierKv,
verifierKv.contactId.equalsExp(keyVerifications.verifiedBy),
),
])..where(keyVerifications.contactId.equals(contactId));
final rows = await query.get();
for (final row in rows) {
final kv = row.readTable(keyVerifications);
final hasVerifierKv = row.readTableOrNull(verifierKv) != null;
if (kv.type == VerificationType.contactSharedByVerified) {
if (hasVerifierKv) return true;
} else {
return true;
}
}
return false;
}
Stream<List<(KeyVerification, Contact?)>> watchContactVerification(
int contactId, int contactId,
) { ) {
final verifier = alias(contacts, 'verifier'); final verifier = alias(contacts, 'verifier');
@ -159,57 +124,7 @@ class KeyVerificationDao extends DatabaseAccessor<TwonlyDB>
}).toList(); }).toList();
}); });
} }
Stream<VerificationStatus> watchAllGroupMembersVerified(String groupId) {
Future<int> getTransferredTrustVerificationsCount() async {
final kv = keyVerifications;
final ur = userDiscoveryUserRelations;
final query = selectOnly(ur, distinct: true)
..addColumns([ur.announcedUserId])
..join([
innerJoin(contacts, contacts.userId.equalsExp(ur.fromContactId)),
innerJoin(kv, kv.contactId.equalsExp(ur.fromContactId)),
])
..where(
ur.publicKeyVerifiedTimestamp.isNotNull() &
ur.announcedUserId.equalsExp(ur.fromContactId).not(),
)
..groupBy([ur.announcedUserId]);
final rows = await query.get();
return rows.length;
}
Future<int> getCountOfContactsWithVerificationBadge() async {
final kv = keyVerifications;
final ur = userDiscoveryUserRelations;
final query = selectOnly(ur, distinct: true)
..addColumns([ur.announcedUserId])
..join([
innerJoin(contacts, contacts.userId.equalsExp(ur.fromContactId)),
innerJoin(kv, kv.contactId.equalsExp(ur.fromContactId)),
])
..where(
ur.publicKeyVerifiedTimestamp.isNotNull() &
ur.announcedUserId.equalsExp(ur.fromContactId).not(),
)
..groupBy([ur.announcedUserId]);
final rows = await query.get();
final transferredIds = rows.map((r) => r.read(ur.announcedUserId)!).toSet();
final directVerifications = await select(kv).get();
final directIds = directVerifications.map((v) => v.contactId).toSet();
// Reduce transferred contacts where announcedUserId is already in KeyVerifications
transferredIds.removeWhere(directIds.contains);
// Add count of all users who are in the KeyVerification table
return transferredIds.length + directIds.length;
}
Stream<VerificationStatus> watchAllGroupMembersVerified(String groupId) {
final gm = groupMembers; final gm = groupMembers;
final directKv = alias(keyVerifications, 'directKv'); final directKv = alias(keyVerifications, 'directKv');
final ur = userDiscoveryUserRelations; final ur = userDiscoveryUserRelations;
@ -376,24 +291,7 @@ class KeyVerificationDao extends DatabaseAccessor<TwonlyDB>
Log.error(e); Log.error(e);
} }
} }
Future<void> deleteKeyVerificationById(
Future<void> deleteKeyVerification(int contactId) async {
try {
await (delete(
keyVerifications,
)..where((kv) => kv.contactId.equals(contactId))).go();
if (userService.currentUser.isUserDiscoveryEnabled) {
await FlutterUserDiscovery.updateVerificationStateForUser(
callbackId: isolateCallbackId,
contactId: contactId,
);
}
} catch (e) {
Log.error(e);
}
}
Future<void> deleteKeyVerificationById(
int verificationId, int verificationId,
int contactId, int contactId,
) async { ) async {

View file

@ -18,14 +18,7 @@ class LabelsDao extends DatabaseAccessor<TwonlyDB> with _$LabelsDaoMixin {
labels, labels,
)..orderBy([(t) => OrderingTerm(expression: t.name)])).watch(); )..orderBy([(t) => OrderingTerm(expression: t.name)])).watch();
} }
Stream<List<Label>> watchContactLabels(int contactId) {
Future<List<Label>> getAllLabels() {
return (select(
labels,
)..orderBy([(t) => OrderingTerm(expression: t.name)])).get();
}
Stream<List<Label>> watchContactLabels(int contactId) {
final query = select(contactLabels).join([ final query = select(contactLabels).join([
innerJoin(labels, labels.id.equalsExp(contactLabels.labelId)), innerJoin(labels, labels.id.equalsExp(contactLabels.labelId)),
])..where(contactLabels.contactId.equals(contactId)); ])..where(contactLabels.contactId.equals(contactId));
@ -50,18 +43,7 @@ class LabelsDao extends DatabaseAccessor<TwonlyDB> with _$LabelsDaoMixin {
.toList(), .toList(),
); );
} }
Future<void> setContactLabels(int contactId, List<int> labelIds) async {
Future<List<Label>> getContactLabels(int contactId) {
final query = select(contactLabels).join([
innerJoin(labels, labels.id.equalsExp(contactLabels.labelId)),
])..where(contactLabels.contactId.equals(contactId));
return query.get().then(
(rows) => rows.map((row) => row.readTable(labels)).toList(),
);
}
Future<void> setContactLabels(int contactId, List<int> labelIds) async {
final sanitizedLabelIds = labelIds.take(3).toList(); final sanitizedLabelIds = labelIds.take(3).toList();
await transaction(() async { await transaction(() async {
await (delete( await (delete(

View file

@ -88,21 +88,7 @@ class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
mediaFiles, mediaFiles,
)..where((t) => t.mediaId.equals(mediaId))).watchSingleOrNull(); )..where((t) => t.mediaId.equals(mediaId))).watchSingleOrNull();
} }
Future<List<MediaFile>> getAllMediaFilesPendingDownload() async {
Future<void> resetPendingDownloadState() async {
await (update(mediaFiles)..where(
(c) => c.downloadState.equals(
DownloadState.downloading.name,
),
))
.write(
const MediaFilesCompanion(
downloadState: Value(DownloadState.pending),
),
);
}
Future<List<MediaFile>> getAllMediaFilesPendingDownload() async {
return (select(mediaFiles)..where( return (select(mediaFiles)..where(
(t) => (t) =>
t.downloadState.equals(DownloadState.pending.name) | t.downloadState.equals(DownloadState.pending.name) |
@ -158,15 +144,7 @@ class MediaFilesDao extends DatabaseAccessor<TwonlyDB>
]); ]);
return query.map((row) => row.readTable(mediaFiles)).watch(); return query.map((row) => row.readTable(mediaFiles)).watch();
} }
Stream<List<MediaFile>> watchMediaFilesByIds(Set<String> mediaIds) {
Stream<List<MediaFile>> watchNewestMediaFiles() {
return (select(mediaFiles)
..orderBy([(t) => OrderingTerm.desc(t.createdAt)])
..limit(100))
.watch();
}
Stream<List<MediaFile>> watchMediaFilesByIds(Set<String> mediaIds) {
if (mediaIds.isEmpty) return Stream.value(const []); if (mediaIds.isEmpty) return Stream.value(const []);
return (select( return (select(
mediaFiles, mediaFiles,

View file

@ -285,20 +285,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
.map((row) => (row.readTable(groupMembers), row.readTable(contacts))) .map((row) => (row.readTable(groupMembers), row.readTable(contacts)))
.watch(); .watch();
} }
Future<void> purgeMessageTable() async {
Stream<List<MessageAction>> watchMessageActionChanges(String messageId) {
return (select(
messageActions,
)..where((t) => t.messageId.equals(messageId))).watch();
}
Stream<Message?> watchMessageById(String messageId) {
return (select(
messages,
)..where((t) => t.messageId.equals(messageId))).watchSingleOrNull();
}
Future<void> purgeMessageTable() async {
final allGroups = await select(groups).get(); final allGroups = await select(groups).get();
final groupedByTime = <int, List<String>>{}; final groupedByTime = <int, List<String>>{};
@ -635,26 +622,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
return null; return null;
} }
} }
Future<void> deleteMessagesById(String messageId) {
Future<MessageAction?> getLastMessageAction(String messageId) async {
return (((select(messageActions)..where(
(t) => t.messageId.equals(messageId),
))
..orderBy([(t) => OrderingTerm.desc(t.actionAt)]))
..limit(1))
.getSingleOrNull();
}
Stream<MessageAction?> watchLastMessageAction(String messageId) {
return (((select(messageActions)..where(
(t) => t.messageId.equals(messageId),
))
..orderBy([(t) => OrderingTerm.desc(t.actionAt)]))
..limit(1))
.watchSingleOrNull();
}
Future<void> deleteMessagesById(String messageId) {
return (delete(messages)..where((t) => t.messageId.equals(messageId))).go(); return (delete(messages)..where((t) => t.messageId.equals(messageId))).go();
} }
@ -697,19 +665,7 @@ class MessagesDao extends DatabaseAccessor<TwonlyDB> with _$MessagesDaoMixin {
)) ))
.watch(); .watch();
} }
Stream<List<MessageHistory>> watchMessageHistory(String messageId) {
Stream<List<MessageAction>> watchMessageActionsForGroup(String groupId) {
final query = select(messageActions).join([
innerJoin(
messages,
messages.messageId.equalsExp(messageActions.messageId),
useColumns: false,
),
])..where(messages.groupId.equals(groupId));
return query.map((row) => row.readTable(messageActions)).watch();
}
Stream<List<MessageHistory>> watchMessageHistory(String messageId) {
return (select(messageHistories) return (select(messageHistories)
..where((t) => t.messageId.equals(messageId)) ..where((t) => t.messageId.equals(messageId))
..orderBy([(t) => OrderingTerm.desc(t.createdAt)])) ..orderBy([(t) => OrderingTerm.desc(t.createdAt)]))

View file

@ -115,22 +115,7 @@ class ReactionsDao extends DatabaseAccessor<TwonlyDB> with _$ReactionsDaoMixin {
..orderBy([(reaction) => OrderingTerm.desc(reaction.createdAt)])) ..orderBy([(reaction) => OrderingTerm.desc(reaction.createdAt)]))
.watch(); .watch();
} }
Stream<Reaction?> watchLastReactions(String groupId) {
Stream<List<Reaction>> watchReactionsForGroup(String groupId) {
final query =
select(reactions).join([
innerJoin(
messages,
messages.messageId.equalsExp(reactions.messageId),
useColumns: false,
),
])
..where(messages.groupId.equals(groupId))
..orderBy([OrderingTerm.desc(reactions.createdAt)]);
return query.map((row) => row.readTable(reactions)).watch();
}
Stream<Reaction?> watchLastReactions(String groupId) {
final query = final query =
(select(reactions)).join( (select(reactions)).join(
[ [

View file

@ -1,11 +1,9 @@
import 'package:clock/clock.dart'; import 'package:clock/clock.dart';
import 'package:drift/drift.dart'; 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/contacts.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart'; import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/tables/receipts.table.dart'; import 'package:twonly/src/database/tables/receipts.table.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/services/api/mediafiles/upload.api.dart';
import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/utils/log.dart';
part 'receipts.dao.g.dart'; part 'receipts.dao.g.dart';
@ -18,36 +16,7 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
// of this object. // of this object.
// ignore: matching_super_parameters // ignore: matching_super_parameters
ReceiptsDao(super.db); ReceiptsDao(super.db);
Future<void> deleteReceipt(String receiptId) async {
Future<void> confirmReceipt(String receiptId, int fromUserId) async {
final receipt =
await (select(receipts)..where(
(t) =>
t.receiptId.equals(receiptId) &
t.contactId.equals(fromUserId),
))
.getSingleOrNull();
if (receipt == null) return;
if (receipt.messageId != null) {
await into(messageActions).insertOnConflictUpdate(
MessageActionsCompanion(
messageId: Value(receipt.messageId!),
contactId: Value(fromUserId),
type: const Value(MessageActionType.ackByUserAt),
),
);
await handleMediaRelatedResponseFromReceiver(receipt.messageId!);
}
await (delete(receipts)..where(
(t) => t.receiptId.equals(receiptId) & t.contactId.equals(fromUserId),
))
.go();
}
Future<void> deleteReceipt(String receiptId) async {
await (delete(receipts)..where( await (delete(receipts)..where(
(t) => t.receiptId.equals(receiptId), (t) => t.receiptId.equals(receiptId),
)) ))
@ -89,27 +58,7 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
.go(); .go();
} }
} }
Future<Receipt?> getReceiptById(String receiptId) async {
Future<Receipt?> insertReceipt(ReceiptsCompanion entry) async {
try {
var insertEntry = entry;
if (entry.receiptId == const Value.absent()) {
insertEntry = entry.copyWith(
receiptId: Value(uuid.v4()),
);
}
await into(receipts).insert(insertEntry);
final receiptId = insertEntry.receiptId.value;
return await (select(
receipts,
)..where((t) => t.receiptId.equals(receiptId))).getSingle();
} catch (e) {
// ignore error, receipts is already in the database...
return null;
}
}
Future<Receipt?> getReceiptById(String receiptId) async {
try { try {
return await (select(receipts)..where( return await (select(receipts)..where(
(t) => t.receiptId.equals(receiptId), (t) => t.receiptId.equals(receiptId),
@ -120,37 +69,7 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
return null; return null;
} }
} }
Future<List<Receipt>> getReceiptsForMediaRetransmissions() async {
Future<List<Receipt>> getReceiptsByContactAndMessageId(
int contactId,
String messageId,
) async {
return (select(receipts)..where(
(t) => t.contactId.equals(contactId) & t.messageId.equals(messageId),
))
.get();
}
Future<List<Receipt>> getReceiptsForRetransmission() async {
final markedRetriesTime = clock.now().subtract(
const Duration(
// give the server time to transmit all messages to the client
seconds: 20,
),
);
return (select(receipts)..where(
(t) =>
(t.ackByServerAt.isNull() |
t.markForRetry.isSmallerThanValue(markedRetriesTime) |
t.markForRetryAfterAccepted.isSmallerThanValue(
markedRetriesTime,
)) &
t.willBeRetriedByMediaUpload.equals(false),
))
.get();
}
Future<List<Receipt>> getReceiptsForMediaRetransmissions() async {
final markedRetriesTime = clock.now().subtract( final markedRetriesTime = clock.now().subtract(
const Duration( const Duration(
// give the server time to transmit all messages to the client // give the server time to transmit all messages to the client
@ -171,18 +90,7 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
Stream<List<Receipt>> watchAll() { Stream<List<Receipt>> watchAll() {
return select(receipts).watch(); return select(receipts).watch();
} }
Future<void> updateReceipt(
Future<int> getReceiptCountForContact(int contactId) {
final countExp = countAll();
final query = selectOnly(receipts)
..addColumns([countExp])
..where(receipts.contactId.equals(contactId));
return query.map((row) => row.read(countExp)!).getSingle();
}
Future<void> updateReceipt(
String receiptId, String receiptId,
ReceiptsCompanion updates, ReceiptsCompanion updates,
) async { ) async {
@ -190,25 +98,7 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
receipts, receipts,
)..where((c) => c.receiptId.equals(receiptId))).write(updates); )..where((c) => c.receiptId.equals(receiptId))).write(updates);
} }
Future<void> updateReceiptByContactAndMessageId(
Future<Receipt?> rotateReceiptId(String oldReceiptId) async {
final newReceiptId = uuid.v4();
await updateReceipt(
oldReceiptId,
ReceiptsCompanion(
receiptId: Value(newReceiptId),
),
);
final updatedReceipt = await getReceiptById(newReceiptId);
if (updatedReceipt == null) {
Log.warn(
'[$oldReceiptId] Tried to change the receipt ID to $newReceiptId, but could not get the updated receipt...',
);
}
return updatedReceipt;
}
Future<void> updateReceiptByContactAndMessageId(
int contactId, int contactId,
String messageId, String messageId,
ReceiptsCompanion updates, ReceiptsCompanion updates,
@ -220,61 +110,8 @@ class ReceiptsDao extends DatabaseAccessor<TwonlyDB> with _$ReceiptsDaoMixin {
)) ))
.write(updates); .write(updates);
} }
/// Claims a new delivery-receipt attempt after [cooldown] has elapsed.
Future<void> updateReceiptWidthUserId(
int fromUserId,
String receiptId,
ReceiptsCompanion updates,
) async {
await (update(receipts)..where(
(c) => c.receiptId.equals(receiptId) & c.contactId.equals(fromUserId),
))
.write(updates);
}
Future<void> markMessagesForRetry(int contactId) async {
await (update(receipts)..where(
(c) => c.contactId.equals(contactId) & c.markForRetry.isNull(),
))
.write(
ReceiptsCompanion(
markForRetry: Value(clock.now()),
),
);
}
Future<bool> isDuplicated(String receiptId) async {
return await (select(
receivedReceipts,
)..where((t) => t.receiptId.equals(receiptId))).getSingleOrNull() !=
null;
}
/// Claims a new delivery-receipt attempt after [cooldown] has elapsed.
/// ///
/// Updating the timestamp before sending prevents repeated server batches from /// Updating the timestamp before sending prevents repeated server batches from
/// starting multiple delivery-receipt attempts during the same cooldown. /// starting multiple delivery-receipt attempts during the same cooldown.
Future<bool> claimDuplicateReceiptResend(
String receiptId,
Duration cooldown,
) async {
final now = clock.now();
final updated =
await (update(receivedReceipts)..where(
(t) =>
t.receiptId.equals(receiptId) &
t.createdAt.isSmallerOrEqualValue(now.subtract(cooldown)),
))
.write(ReceivedReceiptsCompanion(createdAt: Value(now)));
return updated > 0;
}
Future<void> gotReceipt(String receiptId) async {
await into(
receivedReceipts,
).insert(
ReceivedReceiptsCompanion(receiptId: Value(receiptId)),
mode: InsertMode.insertOrIgnore,
);
}
} }

View file

@ -53,48 +53,7 @@ class UserDiscoveryDao extends DatabaseAccessor<TwonlyDB>
.map((row) => row.readTable(userDiscoveryAnnouncedUsers)) .map((row) => row.readTable(userDiscoveryAnnouncedUsers))
.toList(); .toList();
} }
Stream<AnnouncedUsersWithRelations> watchAllAnnouncedUsersWithRelations() {
Future<AnnouncedUsersWithRelations>
getAllAnnouncedUsersWithRelations() async {
final query = select(userDiscoveryAnnouncedUsers).join([
innerJoin(
userDiscoveryUserRelations,
userDiscoveryUserRelations.announcedUserId.equalsExp(
userDiscoveryAnnouncedUsers.announcedUserId,
),
),
innerJoin(
contacts,
contacts.userId.equalsExp(
userDiscoveryUserRelations.fromContactId,
),
),
])..where(userDiscoveryAnnouncedUsers.username.isNotNull());
final rows = await query.get();
// ignore: omit_local_variable_types
final AnnouncedUsersWithRelations results = {};
for (final row in rows) {
final user = row.readTable(userDiscoveryAnnouncedUsers);
final relation = row.readTable(userDiscoveryUserRelations);
final contact = row.readTable(contacts);
final relationData = (
contact,
relation.publicKeyVerifiedTimestamp,
);
if (!results.containsKey(user)) {
results[user] = [];
}
results[user]!.add(relationData);
}
return results;
}
Stream<AnnouncedUsersWithRelations> watchAllAnnouncedUsersWithRelations() {
final query = select(userDiscoveryAnnouncedUsers).join([ final query = select(userDiscoveryAnnouncedUsers).join([
innerJoin( innerJoin(
userDiscoveryUserRelations, userDiscoveryUserRelations,