mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-09-01 07:24:07 +00:00
removed unused functions
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
bd65268dd2
commit
b09d79f5d6
9 changed files with 27 additions and 578 deletions
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)]))
|
||||||
|
|
|
||||||
|
|
@ -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(
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue