fix issue with contact request

This commit is contained in:
otsmr 2026-03-12 22:45:09 +01:00
parent 074211a815
commit 90f5424aae
8 changed files with 49 additions and 53 deletions

View file

@ -131,10 +131,6 @@ PODS:
- google_mlkit_commons (0.11.1):
- Flutter
- MLKitVision (~> 10.0.0)
- google_mlkit_face_detection (0.13.2):
- Flutter
- google_mlkit_commons
- GoogleMLKit/FaceDetection (~> 9.0.0)
- GoogleAdsOnDeviceConversion (3.2.0):
- GoogleUtilities/Environment (~> 8.1)
- GoogleUtilities/Logger (~> 8.1)
@ -168,9 +164,6 @@ PODS:
- GoogleMLKit/BarcodeScanning (9.0.0):
- GoogleMLKit/MLKitCore
- MLKitBarcodeScanning (~> 8.0.0)
- GoogleMLKit/FaceDetection (9.0.0):
- GoogleMLKit/MLKitCore
- MLKitFaceDetection (~> 8.0.0)
- GoogleMLKit/MLKitCore (9.0.0):
- MLKitCommon (~> 14.0.0)
- GoogleToolboxForMac/Defines (4.2.1)
@ -253,9 +246,6 @@ PODS:
- GoogleUtilities/Logger (~> 8.0)
- GoogleUtilities/UserDefaults (~> 8.0)
- GTMSessionFetcher/Core (< 4.0, >= 3.3.2)
- MLKitFaceDetection (8.0.0):
- MLKitCommon (~> 14.0)
- MLKitVision (~> 10.0)
- MLKitVision (10.0.0):
- GoogleToolboxForMac/Logger (< 5.0, >= 4.2.1)
- "GoogleToolboxForMac/NSData+zlib (< 5.0, >= 4.2.1)"
@ -360,7 +350,6 @@ DEPENDENCIES:
- gal (from `.symlinks/plugins/gal/darwin`)
- google_mlkit_barcode_scanning (from `.symlinks/plugins/google_mlkit_barcode_scanning/ios`)
- google_mlkit_commons (from `.symlinks/plugins/google_mlkit_commons/ios`)
- google_mlkit_face_detection (from `.symlinks/plugins/google_mlkit_face_detection/ios`)
- GoogleUtilities
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- in_app_purchase_storekit (from `.symlinks/plugins/in_app_purchase_storekit/darwin`)
@ -403,7 +392,6 @@ SPEC REPOS:
- MLImage
- MLKitBarcodeScanning
- MLKitCommon
- MLKitFaceDetection
- MLKitVision
- nanopb
- PromisesObjC
@ -457,8 +445,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/google_mlkit_barcode_scanning/ios"
google_mlkit_commons:
:path: ".symlinks/plugins/google_mlkit_commons/ios"
google_mlkit_face_detection:
:path: ".symlinks/plugins/google_mlkit_face_detection/ios"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
in_app_purchase_storekit:
@ -524,7 +510,6 @@ SPEC CHECKSUMS:
gal: baecd024ebfd13c441269ca7404792a7152fde89
google_mlkit_barcode_scanning: 12d8422d8f7b00726dedf9cac00188a2b98750c2
google_mlkit_commons: a5e4ffae5bc59ea4c7b9025dc72cb6cb79dc1166
google_mlkit_face_detection: ee4b72cfae062b4c972204be955d83055a4bfd36
GoogleAdsOnDeviceConversion: d68c69dd9581a0f5da02617b6f377e5be483970f
GoogleAppMeasurement: fce7c1c90640d2f9f5c56771f71deacb2ba3f98c
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
@ -540,7 +525,6 @@ SPEC CHECKSUMS:
MLImage: 0de5c6c2bf9e93b80ef752e2797f0836f03b58c0
MLKitBarcodeScanning: 39de223e7b1b8a8fbf10816a536dd292d8a39343
MLKitCommon: 47d47b50a031d00db62f1b0efe5a1d8b09a3b2e6
MLKitFaceDetection: 32549f1e70e6e7731261bf9cea2b74095e2531cb
MLKitVision: 39a5a812db83c4a0794445088e567f3631c11961
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
no_screenshot: 5e345998c43ffcad5d6834f249590483fcc037bd

View file

@ -110,7 +110,7 @@ class ContactsDao extends DatabaseAccessor<TwonlyDB> with _$ContactsDaoMixin {
return query.map((row) => row.read(count)).watchSingle();
}
Stream<int?> watchContactsRequested() {
Stream<int?> watchContactsRequestedCount() {
final count = contacts.requested.count(distinct: true);
final query = selectOnly(contacts)
..where(

View file

@ -18,7 +18,15 @@ Future<bool> handleNewContactRequest(int fromUserId) async {
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
if (contact.accepted) {
// Either the contact has accepted the fromUserId already: Then just blindly accept the request.
// Or the user has also requested fromUserId. This means that both user have requested each other (while been
// offline for example): In this case the contact can also be accepted blindly.
if (contact.accepted || (!contact.requested && !contact.deletedByUser)) {
if (!contact.accepted) {
// User has also requested the fromUserId, so mark the user as accepted.
await handleContactAccept(fromUserId);
}
// contact was already accepted, so just accept the request in the background.
await sendCipherText(
contact.userId,
@ -50,6 +58,28 @@ Future<bool> handleNewContactRequest(int fromUserId) async {
return true;
}
Future<void> handleContactAccept(int fromUserId) async {
await twonlyDB.contactsDao.updateContact(
fromUserId,
const ContactsCompanion(
requested: Value(false),
accepted: Value(true),
deletedByUser: Value(false),
),
);
final contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
await twonlyDB.groupsDao.createNewDirectChat(
fromUserId,
GroupsCompanion(
groupName: Value(getContactDisplayName(contact)),
),
);
}
}
Future<bool> handleContactRequest(
int fromUserId,
EncryptedContent_ContactRequest contactRequest,
@ -60,25 +90,7 @@ Future<bool> handleContactRequest(
return handleNewContactRequest(fromUserId);
case EncryptedContent_ContactRequest_Type.ACCEPT:
Log.info('Got a contact accept from $fromUserId');
await twonlyDB.contactsDao.updateContact(
fromUserId,
const ContactsCompanion(
requested: Value(false),
accepted: Value(true),
deletedByUser: Value(false),
),
);
final contact = await twonlyDB.contactsDao
.getContactByUserId(fromUserId)
.getSingleOrNull();
if (contact != null) {
await twonlyDB.groupsDao.createNewDirectChat(
fromUserId,
GroupsCompanion(
groupName: Value(getContactDisplayName(contact)),
),
);
}
await handleContactAccept(fromUserId);
case EncryptedContent_ContactRequest_Type.REJECT:
Log.info('Got a contact reject from $fromUserId');
await twonlyDB.contactsDao.updateContact(

View file

@ -26,6 +26,7 @@ import 'package:twonly/src/services/api/client2client/text_message.c2c.dart';
import 'package:twonly/src/services/api/messages.dart';
import 'package:twonly/src/services/group.services.dart';
import 'package:twonly/src/services/signal/encryption.signal.dart';
import 'package:twonly/src/services/signal/session.signal.dart';
import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
@ -94,6 +95,11 @@ Future<void> handleClient2ClientMessage(NewMessage newMessage) async {
var retry = false;
if (message.hasPlaintextContent()) {
if (message.plaintextContent.hasDecryptionErrorMessage()) {
if (message.plaintextContent.decryptionErrorMessage.type ==
PlaintextContent_DecryptionErrorMessage_Type.PREKEY_UNKNOWN) {
// Get a new prekey from the server, and establish a new signal session.
await handleSessionResync(fromUserId);
}
Log.info(
'Got decryption error: ${message.plaintextContent.decryptionErrorMessage.type} for $receiptId',
);

View file

@ -138,7 +138,7 @@ class _ChatListViewState extends State<ChatListView> {
actions: [
const FeedbackIconButton(),
StreamBuilder(
stream: twonlyDB.contactsDao.watchContactsRequested(),
stream: twonlyDB.contactsDao.watchContactsRequestedCount(),
builder: (context, snapshot) {
var count = 0;
if (snapshot.hasData && snapshot.data != null) {

View file

@ -93,7 +93,9 @@ class GroupMemberContextMenu extends StatelessWidget {
await twonlyDB.contactsDao.updateContact(
member.contactId,
const ContactsCompanion(
requested: Value(true),
accepted: Value(false),
requested: Value(false),
deletedByUser: Value(false),
),
);
await sendCipherText(

View file

@ -341,18 +341,18 @@ packages:
dependency: "direct main"
description:
name: cryptography_flutter_plus
sha256: "35a8c270aae0abaac7125a6b6b33c2b3daa0ea90d85320aa7d588b6dd6c2edc9"
sha256: "65bc0a78c2104cdb02f4b69e3a03abef093e660d9d9208bc81942b058b49deb2"
url: "https://pub.dev"
source: hosted
version: "2.3.4"
version: "3.0.0"
cryptography_plus:
dependency: "direct main"
description:
name: cryptography_plus
sha256: "34db787df4f4740a39474b6fb0a610aa6dc13a5b5b68754b4787a79939ac0454"
sha256: edf96fc96518368b11bb1ba33b515f59aa5a55b0aa7533c0e1813399cf81130e
url: "https://pub.dev"
source: hosted
version: "2.7.1"
version: "3.0.0"
csslib:
dependency: transitive
description:
@ -1080,14 +1080,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.14.2"
js:
dependency: transitive
description:
name: js
sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc"
url: "https://pub.dev"
source: hosted
version: "0.7.2"
json_annotation:
dependency: "direct main"
description:

View file

@ -98,8 +98,8 @@ dependencies:
avatar_maker: ^0.4.0
background_downloader: ^9.4.0
cached_network_image: ^3.4.1
cryptography_flutter_plus: ^2.3.4
cryptography_plus: ^2.7.0
cryptography_flutter_plus: ^3.0.0
cryptography_plus: ^3.0.0
flutter_android_volume_keydown: ^1.0.1
flutter_image_compress: ^2.4.0
flutter_volume_controller: ^1.3.4