Stop using key-based lookups for messages, use the message cache instead.

Always update alignment to allow for message row objects to be reused
This commit is contained in:
Sarah Jamie Lewis 2022-03-04 11:30:19 -08:00
parent 7457246a01
commit 1fea540f9d
26 changed files with 60 additions and 66 deletions

View File

@ -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<MessageMetadata>(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<MessageMetadata>(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");

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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": "Διακομιστής",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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",

View File

@ -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": "Пароли не совпадают",

View File

@ -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":

View File

@ -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);
}

View File

@ -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<int, MessageInfo> cache;
late List<int?> cacheByIndex;
late Map<String, int> 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();
}
}

View File

@ -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));
});
}

View File

@ -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));
});
}

View File

@ -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());
});
}

View File

@ -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();

View File

@ -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,
);
});
}

View File

@ -30,9 +30,7 @@ class MessageBubbleState extends State<MessageBubble> {
@override
Widget build(BuildContext context) {
var fromMe = Provider.of<MessageMetadata>(context).senderHandle == Provider.of<ProfileInfoState>(context).onion;
var prettyDate = "";
var borderRadiousEh = 15.0;
// var myKey = Provider.of<MessageState>(context).profileOnion + "::" + Provider.of<MessageState>(context).contactHandle + "::" + Provider.of<MessageState>(context).messageIndex.toString();
var showClickableLinks = Provider.of<Settings>(context).isExperimentEnabled(ClickableLinksExperiment);
DateTime messageDate = Provider.of<MessageMetadata>(context).timestamp;

View File

@ -87,8 +87,7 @@ class _MessageListState extends State<MessageList> {
builder: (context, snapshot) {
if (snapshot.hasData) {
var message = snapshot.data as Message;
var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, message.getMetadata().messageID);
return message.getWidget(context, key);
return message.getWidget(context);
} else {
return MessageLoadingBubble();
}

View File

@ -63,10 +63,7 @@ class MessageRowState extends State<MessageRow> 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) {