From 1fea540f9d5c45cdc1117d161b7d3d1d34d88cdf Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 4 Mar 2022 11:30:19 -0800 Subject: [PATCH] Stop using key-based lookups for messages, use the message cache instead. Always update alignment to allow for message row objects to be reused --- lib/cwtch/cwtchNotifier.dart | 33 +++++++---------------- lib/l10n/intl_cy.arb | 6 ++--- lib/l10n/intl_da.arb | 2 +- lib/l10n/intl_de.arb | 4 +-- lib/l10n/intl_el.arb | 2 +- lib/l10n/intl_en.arb | 2 +- lib/l10n/intl_es.arb | 2 +- lib/l10n/intl_fr.arb | 2 +- lib/l10n/intl_it.arb | 2 +- lib/l10n/intl_lb.arb | 2 +- lib/l10n/intl_no.arb | 2 +- lib/l10n/intl_pl.arb | 4 +-- lib/l10n/intl_pt.arb | 2 +- lib/l10n/intl_ro.arb | 6 ++--- lib/l10n/intl_ru.arb | 6 ++--- lib/models/contact.dart | 5 ++++ lib/models/message.dart | 2 +- lib/models/messagecache.dart | 13 ++++++++- lib/models/messages/filemessage.dart | 4 +-- lib/models/messages/invitemessage.dart | 4 +-- lib/models/messages/malformedmessage.dart | 4 +-- lib/models/messages/quotedmessage.dart | 4 +-- lib/models/messages/textmessage.dart | 3 +-- lib/widgets/messagebubble.dart | 2 -- lib/widgets/messagelist.dart | 3 +-- lib/widgets/messagerow.dart | 5 +--- 26 files changed, 60 insertions(+), 66 deletions(-) diff --git a/lib/cwtch/cwtchNotifier.dart b/lib/cwtch/cwtchNotifier.dart index 1bb5922c..05da5a50 100644 --- a/lib/cwtch/cwtchNotifier.dart +++ b/lib/cwtch/cwtchNotifier.dart @@ -192,25 +192,14 @@ class CwtchNotifier { var conversation = int.parse(data["ConversationID"]); var messageID = int.parse(data["Index"]); - var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation); - // We return -1 for protocol message acks if there is no message - if (messageID == -1) break; - var key = contact!.getMessageKeyOrFail(conversation, messageID); - if (key == null) break; - try { - var message = Provider.of(key.currentContext!, listen: false); - message.ackd = true; - - // We only ever see acks from authenticated peers. - // If the contact is marked as offline then override this - can happen when the contact is removed from the front - // end during syncing. - if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.isOnline() == false) { - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.status = "Authenticated"; - } - profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.ackCache(messageID); - } catch (e) { - // ignore, most likely cause is the key got optimized out... + // We only ever see acks from authenticated peers. + // If the contact is marked as offline then override this - can happen when the contact is removed from the front + // end during syncing. + if (profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.isOnline() == false) { + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.status = "Authenticated"; } + profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(conversation)!.ackCache(messageID); + break; case "NewMessageFromGroup": var identifier = int.parse(data["ConversationID"]); @@ -259,12 +248,8 @@ class CwtchNotifier { case "IndexedFailure": var identifier = int.parse(data["ConversationID"]); var contact = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier); - var idx = int.parse(data["Index"]); - var key = contact?.getMessageKeyOrFail(contact.identifier, idx); - if (key != null) { - var message = Provider.of(key.currentContext!, listen: false); - message.error = true; - } + var messageID = int.parse(data["Index"]); + contact!.errCache(messageID); break; case "AppError": EnvironmentConfig.debugLog("New App Error: $data"); diff --git a/lib/l10n/intl_cy.arb b/lib/l10n/intl_cy.arb index 7f154c83..1fc9e5d5 100644 --- a/lib/l10n/intl_cy.arb +++ b/lib/l10n/intl_cy.arb @@ -1,6 +1,8 @@ { "@@locale": "cy", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", + "deleteConfirmLabel": "Teipiwch DILEU i gadarnhau", + "deleteConfirmText": "DILEU", "localeDa": "Daneg", "successfullAddedContact": "Wedi llwyddo i ychwanegu: ", "serverMetricsLabel": "Metrigau Gweinydd", @@ -281,9 +283,7 @@ "settingLanguage": "Laith", "password": "Cyfrinair", "addNewProfileBtn": "Ychwanegu proffil newydd", - "deleteConfirmText": "DELETE", "deleteProfileConfirmBtn": "Dileu Proffil yn Wirioneddol", - "deleteConfirmLabel": "Teipiwch DELETE i gadarnhau", "deleteProfileBtn": "Dileu Proffil", "passwordErrorMatch": "Nid yw cyfrineiriau'n cyfateb", "saveProfileBtn": "Cadw Proffil", diff --git a/lib/l10n/intl_da.arb b/lib/l10n/intl_da.arb index c1b21027..592b6852 100644 --- a/lib/l10n/intl_da.arb +++ b/lib/l10n/intl_da.arb @@ -1,6 +1,6 @@ { "@@locale": "da", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "serverLabel": "Server", "profileOnionLabel": "Send denne adresse til personer du ønsker forbindelse med", "saveBtn": "Gem", diff --git a/lib/l10n/intl_de.arb b/lib/l10n/intl_de.arb index de252622..0ada706f 100644 --- a/lib/l10n/intl_de.arb +++ b/lib/l10n/intl_de.arb @@ -1,6 +1,7 @@ { "@@locale": "de", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", + "deleteConfirmLabel": "Gib LÖSCHEN ein, um zu bestätigen", "localeDa": "Dänisch", "localeCy": "Walisisch", "pasteAddressToAddContact": "Cwtch Adresse, Einladung oder Schlüssel hier hinzufügen, um eine neue Konversation hinzuzufügen", @@ -176,7 +177,6 @@ "yourServers": "Deine Server", "yourProfiles": "Deine Profile", "enterProfilePassword": "Gib ein Passwort ein, um deine Profile anzuzeigen", - "deleteConfirmLabel": "Gib LÖSCHEN ein um zu bestätigen", "notificationNewMessageFromGroup": "Neue Nachricht in einer Gruppe!", "notificationNewMessageFromPeer": "Neue Nachricht von einem Kontakt!", "tooltipHidePassword": "Password verstecken", diff --git a/lib/l10n/intl_el.arb b/lib/l10n/intl_el.arb index 06b31d77..82d2e6eb 100644 --- a/lib/l10n/intl_el.arb +++ b/lib/l10n/intl_el.arb @@ -1,6 +1,6 @@ { "@@locale": "el", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeCy": "Ουαλικά", "localeDa": "Δανικά", "server": "Διακομιστής", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index deef114e..9b2e7140 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,6 +1,6 @@ { "@@locale": "en", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danish", "localeCy": "Welsh", "localeEl": "Greek", diff --git a/lib/l10n/intl_es.arb b/lib/l10n/intl_es.arb index 3b1273ff..fcc2a99e 100644 --- a/lib/l10n/intl_es.arb +++ b/lib/l10n/intl_es.arb @@ -1,6 +1,6 @@ { "@@locale": "es", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danés", "groupInviteSettingsWarning": "¡Has recibido una invitación para unirte a un grupo! Por favor habilita el experimento de chat grupal en Configuración para ver esta invitación", "plainServerDescription": "Te recomendamos que protejas tus servidores de Cwtch con una contraseña. Si no estableces una contraseña en este servidor, cualquiera que tenga acceso a este dispositivo podrá acceder a la información sobre este servidor incluyendo claves criptográficas confidenciales", diff --git a/lib/l10n/intl_fr.arb b/lib/l10n/intl_fr.arb index 45623427..3dbc8730 100644 --- a/lib/l10n/intl_fr.arb +++ b/lib/l10n/intl_fr.arb @@ -1,6 +1,6 @@ { "@@locale": "fr", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danois", "localeCy": "Gallois", "conversationNotificationPolicySettingDescription": "Contrôler le comportement de notification de cette conversation", diff --git a/lib/l10n/intl_it.arb b/lib/l10n/intl_it.arb index c9ccc6b9..c398c300 100644 --- a/lib/l10n/intl_it.arb +++ b/lib/l10n/intl_it.arb @@ -1,6 +1,6 @@ { "@@locale": "it", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danese", "localeCy": "Gallese", "settingTheme": "Usa Temi Leggeri", diff --git a/lib/l10n/intl_lb.arb b/lib/l10n/intl_lb.arb index 37ad66e3..0094b855 100644 --- a/lib/l10n/intl_lb.arb +++ b/lib/l10n/intl_lb.arb @@ -1,6 +1,6 @@ { "@@locale": "lb", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danish", "localeCy": "Welsh", "serverSynced": "Synchroniséiert", diff --git a/lib/l10n/intl_no.arb b/lib/l10n/intl_no.arb index e7c2251f..4d9aa52e 100644 --- a/lib/l10n/intl_no.arb +++ b/lib/l10n/intl_no.arb @@ -1,6 +1,6 @@ { "@@locale": "no", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Dansk", "localeCy": "Walisisk", "serverLabel": "Tjener", diff --git a/lib/l10n/intl_pl.arb b/lib/l10n/intl_pl.arb index a39224a6..cf53d4ff 100644 --- a/lib/l10n/intl_pl.arb +++ b/lib/l10n/intl_pl.arb @@ -1,6 +1,7 @@ { "@@locale": "pl", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", + "deleteConfirmLabel": "Wpisz USUŃ aby potwierdzić", "localeLb": "Luksemburski", "localeNo": "Norweski", "localeEl": "Grecki", @@ -63,7 +64,6 @@ "addNewProfileBtn": "Dodaj", "deleteConfirmText": "USUŃ", "deleteProfileConfirmBtn": "Usuń", - "deleteConfirmLabel": "Wpisz USUŃ aby potwierdzić", "deleteProfileBtn": "Usuń profil", "passwordChangeError": "Zmiana hasła nie powiodła się: hasło niepoprawne", "passwordErrorMatch": "Hasła nie są identyczne", diff --git a/lib/l10n/intl_pt.arb b/lib/l10n/intl_pt.arb index 6add354e..4528d5a1 100644 --- a/lib/l10n/intl_pt.arb +++ b/lib/l10n/intl_pt.arb @@ -1,6 +1,6 @@ { "@@locale": "pt", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", "localeDa": "Danish", "localeCy": "Welsh", "localeEl": "Greek", diff --git a/lib/l10n/intl_ro.arb b/lib/l10n/intl_ro.arb index 761bcebc..cd8f5760 100644 --- a/lib/l10n/intl_ro.arb +++ b/lib/l10n/intl_ro.arb @@ -1,6 +1,8 @@ { "@@locale": "ro", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", + "deleteProfileConfirmBtn": "Sigur ștergeti profilul", + "deleteConfirmLabel": "Tastați ȘTERGE pentru a confirma", "localeDa": "Daneză", "localeCy": "Velşă", "conversationNotificationPolicySettingDescription": "Controlați comportamentul de notificare al acestei conversații", @@ -89,8 +91,6 @@ "passwordErrorMatch": "Parolele nu se potrivesc", "passwordChangeError": "Eroare la schimbarea parolei: Parola furnizată a fost respinsă", "deleteProfileBtn": "Ștergeți profilul", - "deleteConfirmLabel": "Tastați DELETE pentru a confirma", - "deleteProfileConfirmBtn": "Sigur ștergeti profilul", "deleteConfirmText": "ȘTERGE", "addNewProfileBtn": "Adăugați un profil nou", "enterProfilePassword": "Introduceți o parolă pentru a vă vizualiza profilurile", diff --git a/lib/l10n/intl_ru.arb b/lib/l10n/intl_ru.arb index 91b455f2..b37ae80d 100644 --- a/lib/l10n/intl_ru.arb +++ b/lib/l10n/intl_ru.arb @@ -1,6 +1,8 @@ { "@@locale": "ru", - "@@last_modified": "2022-03-03T19:10:17+01:00", + "@@last_modified": "2022-03-04T17:33:01+01:00", + "deleteConfirmLabel": "Введите УДАЛИТЬ, чтобы продолжить", + "deleteConfirmText": "УДАЛИТЬ", "localeCy": "Валлийский", "localeDa": "Датский", "localeEl": "Греческий", @@ -241,9 +243,7 @@ "password": "Пароль", "enterProfilePassword": "Введите пароль для просмотра ваших профилей", "addNewProfileBtn": "Добавить новый профиль", - "deleteConfirmText": "УДАЛИТЬ", "deleteProfileConfirmBtn": "Действительно удалить профиль?", - "deleteConfirmLabel": "Введите DELETE чтобы продолжить", "deleteProfileBtn": "Удалить профиль", "passwordChangeError": "Ошибка при смене пароля: Введенный пароль отклонен", "passwordErrorMatch": "Пароли не совпадают", diff --git a/lib/models/contact.dart b/lib/models/contact.dart index 81669a8c..87976811 100644 --- a/lib/models/contact.dart +++ b/lib/models/contact.dart @@ -276,6 +276,11 @@ class ContactInfoState extends ChangeNotifier { notifyListeners(); } + void errCache(int messageID) { + this.messageCache.errCache(messageID); + notifyListeners(); + } + static ConversationNotificationPolicy notificationPolicyFromString(String val) { switch (val) { case "ConversationNotificationPolicy.Default": diff --git a/lib/models/message.dart b/lib/models/message.dart index 4c6956d3..866306b0 100644 --- a/lib/models/message.dart +++ b/lib/models/message.dart @@ -32,7 +32,7 @@ const GroupConversationHandleLength = 32; abstract class Message { MessageMetadata getMetadata(); - Widget getWidget(BuildContext context, Key key); + Widget getWidget(BuildContext context); Widget getPreviewWidget(BuildContext context); } diff --git a/lib/models/messagecache.dart b/lib/models/messagecache.dart index a2deae4e..b357ad52 100644 --- a/lib/models/messagecache.dart +++ b/lib/models/messagecache.dart @@ -1,3 +1,5 @@ +import 'package:flutter/foundation.dart'; + import 'message.dart'; class MessageInfo { @@ -6,7 +8,7 @@ class MessageInfo { MessageInfo(this.metadata, this.wrapper); } -class MessageCache { +class MessageCache extends ChangeNotifier { late Map cache; late List cacheByIndex; late Map cacheByHash; @@ -35,6 +37,7 @@ class MessageCache { if (contenthash != null && contenthash != "") { this.cacheByHash[contenthash] = messageID; } + notifyListeners(); } void add(MessageInfo messageInfo, int index, String? contenthash) { @@ -43,6 +46,7 @@ class MessageCache { if (contenthash != null && contenthash != "") { this.cacheByHash[contenthash] = messageInfo.metadata.messageID; } + notifyListeners(); } void addUnindexed(MessageInfo messageInfo, String? contenthash) { @@ -50,9 +54,16 @@ class MessageCache { if (contenthash != null && contenthash != "") { this.cacheByHash[contenthash] = messageInfo.metadata.messageID; } + notifyListeners(); } void ackCache(int messageID) { cache[messageID]?.metadata.ackd = true; + notifyListeners(); + } + + void errCache(int messageID) { + cache[messageID]?.metadata.error = true; + notifyListeners(); } } diff --git a/lib/models/messages/filemessage.dart b/lib/models/messages/filemessage.dart index c68b24e5..e4d0bc7b 100644 --- a/lib/models/messages/filemessage.dart +++ b/lib/models/messages/filemessage.dart @@ -18,7 +18,7 @@ class FileMessage extends Message { FileMessage(this.metadata, this.content); @override - Widget getWidget(BuildContext context, Key key) { + Widget getWidget(BuildContext context) { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { @@ -42,7 +42,7 @@ class FileMessage extends Message { return MessageRow(MalformedBubble()); } - return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize, isAuto: metadata.isAuto), key: key); + return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize, isAuto: metadata.isAuto)); }); } diff --git a/lib/models/messages/invitemessage.dart b/lib/models/messages/invitemessage.dart index 50a28806..f1d1d18b 100644 --- a/lib/models/messages/invitemessage.dart +++ b/lib/models/messages/invitemessage.dart @@ -17,7 +17,7 @@ class InviteMessage extends Message { InviteMessage(this.overlay, this.metadata, this.content); @override - Widget getWidget(BuildContext context, Key key) { + Widget getWidget(BuildContext context) { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { @@ -39,7 +39,7 @@ class InviteMessage extends Message { return MessageRow(MalformedBubble()); } } - return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), key: key); + return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite)); }); } diff --git a/lib/models/messages/malformedmessage.dart b/lib/models/messages/malformedmessage.dart index 0ebf2281..dc943fe1 100644 --- a/lib/models/messages/malformedmessage.dart +++ b/lib/models/messages/malformedmessage.dart @@ -9,11 +9,11 @@ class MalformedMessage extends Message { MalformedMessage(this.metadata); @override - Widget getWidget(BuildContext context, Key key) { + Widget getWidget(BuildContext context) { return ChangeNotifierProvider.value( value: this.metadata, builder: (context, child) { - return MessageRow(MalformedBubble(), key: key); + return MessageRow(MalformedBubble()); }); } diff --git a/lib/models/messages/quotedmessage.dart b/lib/models/messages/quotedmessage.dart index c43ac12c..774c0c41 100644 --- a/lib/models/messages/quotedmessage.dart +++ b/lib/models/messages/quotedmessage.dart @@ -48,7 +48,7 @@ class QuotedMessage extends Message { } @override - Widget getWidget(BuildContext context, Key key) { + Widget getWidget(BuildContext context) { try { dynamic message = jsonDecode(this.content); @@ -59,7 +59,7 @@ class QuotedMessage extends Message { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { - return MessageRow(QuotedMessageBubble(message["body"], messageHandler(bcontext, metadata.profileOnion, metadata.conversationIdentifier, ByContentHash(message["quotedHash"]))), key: key); + return MessageRow(QuotedMessageBubble(message["body"], messageHandler(bcontext, metadata.profileOnion, metadata.conversationIdentifier, ByContentHash(message["quotedHash"])))); }); } catch (e) { return MalformedBubble(); diff --git a/lib/models/messages/textmessage.dart b/lib/models/messages/textmessage.dart index 44f99510..00cd14f7 100644 --- a/lib/models/messages/textmessage.dart +++ b/lib/models/messages/textmessage.dart @@ -29,13 +29,12 @@ class TextMessage extends Message { } @override - Widget getWidget(BuildContext context, Key key) { + Widget getWidget(BuildContext context) { return ChangeNotifierProvider.value( value: this.metadata, builder: (bcontext, child) { return MessageRow( MessageBubble(this.content), - key: key, ); }); } diff --git a/lib/widgets/messagebubble.dart b/lib/widgets/messagebubble.dart index 00314443..3860e6a4 100644 --- a/lib/widgets/messagebubble.dart +++ b/lib/widgets/messagebubble.dart @@ -30,9 +30,7 @@ class MessageBubbleState extends State { @override Widget build(BuildContext context) { var fromMe = Provider.of(context).senderHandle == Provider.of(context).onion; - var prettyDate = ""; var borderRadiousEh = 15.0; - // var myKey = Provider.of(context).profileOnion + "::" + Provider.of(context).contactHandle + "::" + Provider.of(context).messageIndex.toString(); var showClickableLinks = Provider.of(context).isExperimentEnabled(ClickableLinksExperiment); DateTime messageDate = Provider.of(context).timestamp; diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index da8b3ea5..e6f642b2 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -87,8 +87,7 @@ class _MessageListState extends State { builder: (context, snapshot) { if (snapshot.hasData) { var message = snapshot.data as Message; - var key = Provider.of(outerContext, listen: false).getMessageKey(contactHandle, message.getMetadata().messageID); - return message.getWidget(context, key); + return message.getWidget(context); } else { return MessageLoadingBubble(); } diff --git a/lib/widgets/messagerow.dart b/lib/widgets/messagerow.dart index ad92f840..84efcf1c 100644 --- a/lib/widgets/messagerow.dart +++ b/lib/widgets/messagerow.dart @@ -63,10 +63,7 @@ class MessageRowState extends State with SingleTickerProviderStateMi var actualMessage = Flexible(flex: Platform.isAndroid ? 10 : 3, fit: FlexFit.loose, child: widget.child); _dragAffinity = fromMe ? Alignment.centerRight : Alignment.centerLeft; - - if (_dragAlignment == Alignment.center) { - _dragAlignment = fromMe ? Alignment.centerRight : Alignment.centerLeft; - } + _dragAlignment = fromMe ? Alignment.centerRight : Alignment.centerLeft; var senderDisplayStr = ""; if (!fromMe) {