From eade1d87e669adf4dee9905bbc2d9b11caabbea2 Mon Sep 17 00:00:00 2001 From: otsmr Date: Thu, 6 Aug 2026 10:16:27 +0200 Subject: [PATCH] some smaller bug fixes --- lib/src/database/tables/messages.table.dart | 1 + lib/src/database/tables/receipts.table.dart | 1 + lib/src/database/twonly.db.g.dart | 10 ++++++++++ lib/src/services/signal/encryption.signal.dart | 3 +++ lib/src/visual/views/chats/chat_messages.view.dart | 1 + .../visual/views/onboarding/recover_password.view.dart | 7 +++++++ .../visual/views/settings/data_and_storage.view.dart | 10 +++++++++- pubspec.yaml | 2 +- 8 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/src/database/tables/messages.table.dart b/lib/src/database/tables/messages.table.dart index c364b9e6..32cb4ea2 100644 --- a/lib/src/database/tables/messages.table.dart +++ b/lib/src/database/tables/messages.table.dart @@ -6,6 +6,7 @@ import 'package:twonly/src/database/tables/mediafiles.table.dart'; enum MessageType { media, text, contacts, restoreFlameCounter, askAboutUser } @DataClassName('Message') +@TableIndex(name: 'idx_messages_group_id_created_at', columns: {#groupId, #createdAt}) class Messages extends Table { TextColumn get groupId => text().references(Groups, #groupId, onDelete: KeyAction.cascade)(); diff --git a/lib/src/database/tables/receipts.table.dart b/lib/src/database/tables/receipts.table.dart index 691cc322..982bd86c 100644 --- a/lib/src/database/tables/receipts.table.dart +++ b/lib/src/database/tables/receipts.table.dart @@ -3,6 +3,7 @@ import 'package:twonly/src/database/tables/contacts.table.dart'; import 'package:twonly/src/database/tables/messages.table.dart'; @DataClassName('Receipt') +@TableIndex(name: 'idx_receipts_message_id', columns: {#messageId}) class Receipts extends Table { TextColumn get receiptId => text()(); diff --git a/lib/src/database/twonly.db.g.dart b/lib/src/database/twonly.db.g.dart index 3d84320a..fca40dc8 100644 --- a/lib/src/database/twonly.db.g.dart +++ b/lib/src/database/twonly.db.g.dart @@ -13843,6 +13843,14 @@ abstract class _$TwonlyDB extends GeneratedDatabase { ); late final $LabelsTable labels = $LabelsTable(this); late final $ContactLabelsTable contactLabels = $ContactLabelsTable(this); + late final Index idxMessagesGroupIdCreatedAt = Index( + 'idx_messages_group_id_created_at', + 'CREATE INDEX idx_messages_group_id_created_at ON messages (group_id, created_at)', + ); + late final Index idxReceiptsMessageId = Index( + 'idx_receipts_message_id', + 'CREATE INDEX idx_receipts_message_id ON receipts (message_id)', + ); late final MessagesDao messagesDao = MessagesDao(this as TwonlyDB); late final ContactsDao contactsDao = ContactsDao(this as TwonlyDB); late final ReceiptsDao receiptsDao = ReceiptsDao(this as TwonlyDB); @@ -13889,6 +13897,8 @@ abstract class _$TwonlyDB extends GeneratedDatabase { shortcutMembers, labels, contactLabels, + idxMessagesGroupIdCreatedAt, + idxReceiptsMessageId, ]; @override StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules([ diff --git a/lib/src/services/signal/encryption.signal.dart b/lib/src/services/signal/encryption.signal.dart index 2cd65a36..4810048f 100644 --- a/lib/src/services/signal/encryption.signal.dart +++ b/lib/src/services/signal/encryption.signal.dart @@ -140,6 +140,9 @@ signalDecryptMessageV1( ) = await lockingSignalProtocol.protect(() async { Log.info('Lock acquired for $fromUserId (V1)'); try { + // Yield execution to the event loop to prevent UI freezing during bulk decryption + await Future.delayed(Duration.zero); + final session = SessionCipher.fromStore( (await getSignalStore())!, getSignalAddress(fromUserId), diff --git a/lib/src/visual/views/chats/chat_messages.view.dart b/lib/src/visual/views/chats/chat_messages.view.dart index d4b953ed..e0cb543f 100644 --- a/lib/src/visual/views/chats/chat_messages.view.dart +++ b/lib/src/visual/views/chats/chat_messages.view.dart @@ -84,6 +84,7 @@ class _ChatMessagesViewState extends State contactSub?.cancel(); groupActionsSub?.cancel(); _nextTypingIndicator?.cancel(); + textFieldFocus?.dispose(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } diff --git a/lib/src/visual/views/onboarding/recover_password.view.dart b/lib/src/visual/views/onboarding/recover_password.view.dart index 205949f5..84acc7ff 100644 --- a/lib/src/visual/views/onboarding/recover_password.view.dart +++ b/lib/src/visual/views/onboarding/recover_password.view.dart @@ -27,6 +27,13 @@ class _BackupRecoveryViewState extends State { final TextEditingController usernameCtrl = TextEditingController(); final TextEditingController passwordCtrl = TextEditingController(); + @override + void dispose() { + usernameCtrl.dispose(); + passwordCtrl.dispose(); + super.dispose(); + } + Future _recoverTwonlySafe() async { setState(() { isLoading = true; diff --git a/lib/src/visual/views/settings/data_and_storage.view.dart b/lib/src/visual/views/settings/data_and_storage.view.dart index 161adfe2..9b3a38e4 100644 --- a/lib/src/visual/views/settings/data_and_storage.view.dart +++ b/lib/src/visual/views/settings/data_and_storage.view.dart @@ -17,6 +17,14 @@ class DataAndStorageView extends StatefulWidget { } class _DataAndStorageViewState extends State { + late Future> _storageStatsFuture; + + @override + void initState() { + super.initState(); + _storageStatsFuture = twonlyDB.mediaFilesDao.getStorageStats(); + } + Future showAutoDownloadOptions( BuildContext context, ConnectivityResult connectionMode, @@ -93,7 +101,7 @@ class _DataAndStorageViewState extends State { return ListView( children: [ FutureBuilder>( - future: twonlyDB.mediaFilesDao.getStorageStats(), + future: _storageStatsFuture, builder: (context, snapshot) { final stats = snapshot.data ?? {}; final totalBytes = stats.values.fold(0, (a, b) => a + b); diff --git a/pubspec.yaml b/pubspec.yaml index 2f295d77..b58ed5ef 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -3,7 +3,7 @@ description: "twonly, a privacy-friendly way to connect with friends through sec publish_to: 'none' -version: 0.5.0+168 +version: 0.5.0+169 environment: sdk: ^3.11.0