diff --git a/lib/models/message.dart b/lib/models/message.dart index 52070666..6ada0469 100644 --- a/lib/models/message.dart +++ b/lib/models/message.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:cwtch/config.dart'; +import 'package:cwtch/cwtch/cwtch.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:provider/provider.dart'; @@ -61,26 +62,76 @@ Message compileOverlay(MessageMetadata metadata, String messageData) { } } -Future messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, - {bool byIndex = false, int? index, bool byID = false, int? id, bool byHash = false, String? hash}) { - var malformedMetadata = MessageMetadata(profileOnion, conversationIdentifier, 0, DateTime.now(), "", "", "", {}, false, true, false); - if (!byIndex && !byID && !byHash) { - EnvironmentConfig.debugLog("Error calling messageHandler: one of byIndex, byID, byHash must be set"); - return Future.value(MalformedMessage(malformedMetadata)); - } - if ((byID && id == null) || (byIndex && index == null) || (byHash && hash == null)) { - EnvironmentConfig.debugLog("Error calling messageHandler: byType needs corresponding value and it was not set"); - return Future.value(MalformedMessage(malformedMetadata)); +abstract class CacheHandler { + MessageInfo? lookup(MessageCache cache); + Future fetch(Cwtch cwtch, String profileOnion, int conversationIdentifier); + void add(MessageCache cache, MessageInfo messageInfo, String contenthash); +} + +class ByIndex implements CacheHandler { + int index; + + ByIndex(this.index); + + MessageInfo? lookup(MessageCache cache) { + return cache.getByIndex(index); } + Future fetch(Cwtch cwtch, String profileOnion, int conversationIdentifier) { + return cwtch.GetMessage(profileOnion, conversationIdentifier, index); + } + + void add(MessageCache cache, MessageInfo messageInfo, String contenthash) { + cache.add(messageInfo, index, contenthash); + } +} + +class ById implements CacheHandler { + int id; + + ById(this.id); + + MessageInfo? lookup(MessageCache cache) { + return cache.getById(id); + } + + Future fetch(Cwtch cwtch, String profileOnion, int conversationIdentifier) { + return cwtch.GetMessageByID(profileOnion, conversationIdentifier, id); + } + + void add(MessageCache cache, MessageInfo messageInfo, String contenthash) { + cache.addUnindexed(messageInfo, contenthash); + } +} + +class ByContentHash implements CacheHandler { + String hash; + + ByContentHash(this.hash); + + MessageInfo? lookup(MessageCache cache) { + return cache.getByContentHash(hash); + } + + Future fetch(Cwtch cwtch, String profileOnion, int conversationIdentifier) { + return cwtch.GetMessageByContentHash(profileOnion, conversationIdentifier, hash); + } + + void add(MessageCache cache, MessageInfo messageInfo, String contenthash) { + cache.addUnindexed(messageInfo, contenthash); + } +} + +Future messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, CacheHandler cacheHandler) { + var malformedMetadata = MessageMetadata(profileOnion, conversationIdentifier, 0, DateTime.now(), "", "", "", {}, false, true, false); // Hit cache - MessageInfo? messageInfo = getMessageInfoFromCache(context, profileOnion, conversationIdentifier, byIndex: byIndex, index: index, byID: byID, id: id, byHash: byHash, hash: hash); + MessageInfo? messageInfo = getMessageInfoFromCache(context, profileOnion, conversationIdentifier, cacheHandler); if (messageInfo != null) { return Future.value(compileOverlay(messageInfo.metadata, messageInfo.wrapper)); } // Fetch and Cache - var messageInfoFuture = fetchAndCacheMessageInfo(context, profileOnion, conversationIdentifier, byIndex: byIndex, index: index, byID: byID, id: id, byHash: byHash, hash: hash); + var messageInfoFuture = fetchAndCacheMessageInfo(context, profileOnion, conversationIdentifier, cacheHandler); return messageInfoFuture.then((MessageInfo? messageInfo) { if (messageInfo != null) { return compileOverlay(messageInfo.metadata, messageInfo.wrapper); @@ -90,20 +141,12 @@ Future messageHandler(BuildContext context, String profileOnion, int co }); } -MessageInfo? getMessageInfoFromCache(BuildContext context, String profileOnion, int conversationIdentifier, - {bool byIndex = false, int? index, bool byID = false, int? id, bool byHash = false, String? hash}) { +MessageInfo? getMessageInfoFromCache(BuildContext context, String profileOnion, int conversationIdentifier, CacheHandler cacheHandler) { // Hit cache try { var cache = Provider.of(context, listen: false).contactList.getContact(conversationIdentifier)?.messageCache; if (cache != null) { - MessageInfo? messageInfo = null; - if (byID) { - messageInfo = cache.getById(id!); - } else if (byHash) { - messageInfo = cache.getByContentHash(hash!); - } else { - messageInfo = cache.getByIndex(index!); - } + MessageInfo? messageInfo = cacheHandler.lookup(cache); if (messageInfo != null) { return messageInfo; } @@ -115,19 +158,12 @@ MessageInfo? getMessageInfoFromCache(BuildContext context, String profileOnion, return null; } -Future fetchAndCacheMessageInfo(BuildContext context, String profileOnion, int conversationIdentifier, - {bool byIndex = false, int? index, bool byID = false, int? id, bool byHash = false, String? hash}) { +Future fetchAndCacheMessageInfo(BuildContext context, String profileOnion, int conversationIdentifier, CacheHandler cacheHandler) { // Load and cache try { Future rawMessageEnvelopeFuture; - if (byID) { - rawMessageEnvelopeFuture = Provider.of(context, listen: false).cwtch.GetMessageByID(profileOnion, conversationIdentifier, id!); - } else if (byHash) { - rawMessageEnvelopeFuture = Provider.of(context, listen: false).cwtch.GetMessageByContentHash(profileOnion, conversationIdentifier, hash!); - } else { - rawMessageEnvelopeFuture = Provider.of(context, listen: false).cwtch.GetMessage(profileOnion, conversationIdentifier, index!); - } + rawMessageEnvelopeFuture = cacheHandler.fetch(Provider.of(context, listen: false).cwtch, profileOnion, conversationIdentifier); return rawMessageEnvelopeFuture.then((dynamic rawMessageEnvelope) { try { @@ -144,11 +180,11 @@ Future fetchAndCacheMessageInfo(BuildContext context, String profi if (messageWrapper['Message'] == null || messageWrapper['Message'] == '' || messageWrapper['Message'] == '{}') { return Future.delayed(Duration(seconds: 2), () { print("Tail recursive call to messageHandler called. This should be a rare event. If you see multiples of this log over a short period of time please log it as a bug."); - return fetchAndCacheMessageInfo(context, profileOnion, conversationIdentifier, byIndex: byIndex, index: index, byID: byID, id: id, byHash: byHash, hash: hash).then((value) => value); + return fetchAndCacheMessageInfo(context, profileOnion, conversationIdentifier, cacheHandler); }); } -// Construct the initial metadata + // Construct the initial metadata var messageID = messageWrapper['ID']; var timestamp = DateTime.tryParse(messageWrapper['Timestamp'])!; var senderHandle = messageWrapper['PeerID']; @@ -163,15 +199,8 @@ Future fetchAndCacheMessageInfo(BuildContext context, String profi var messageInfo = new MessageInfo(metadata, messageWrapper['Message']); var cache = Provider.of(context, listen: false).contactList.getContact(conversationIdentifier)?.messageCache; - if (cache != null) { - if (byID) { - cache.addUnindexed(messageInfo, contenthash); - } else if (byHash) { - cache.addUnindexed(messageInfo, contenthash); - } else { - cache.add(messageInfo, index!, contenthash); - } + cacheHandler.add(cache, messageInfo, contenthash); } return messageInfo; diff --git a/lib/models/messages/quotedmessage.dart b/lib/models/messages/quotedmessage.dart index 7f5053d9..c43ac12c 100644 --- a/lib/models/messages/quotedmessage.dart +++ b/lib/models/messages/quotedmessage.dart @@ -59,8 +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, byHash: true, hash: message["quotedHash"])), - key: key); + return MessageRow(QuotedMessageBubble(message["body"], messageHandler(bcontext, metadata.profileOnion, metadata.conversationIdentifier, ByContentHash(message["quotedHash"]))), key: key); }); } catch (e) { return MalformedBubble(); diff --git a/lib/views/messageview.dart b/lib/views/messageview.dart index bc811f67..dd81c1c2 100644 --- a/lib/views/messageview.dart +++ b/lib/views/messageview.dart @@ -227,7 +227,7 @@ class _MessageViewState extends State { Future.delayed(const Duration(milliseconds: 80), () { var profile = Provider.of(context, listen: false).profileOnion; var identifier = Provider.of(context, listen: false).identifier; - fetchAndCacheMessageInfo(context, profile, identifier, byIndex: true, index: 0); + fetchAndCacheMessageInfo(context, profile, identifier, ByIndex(0)); Provider.of(context, listen: false).newMarker++; Provider.of(context, listen: false).totalMessages += 1; // Resort the contact list... @@ -284,8 +284,7 @@ class _MessageViewState extends State { var children; if (Provider.of(context).selectedConversation != null && Provider.of(context).selectedIndex != null) { var quoted = FutureBuilder( - future: messageHandler(context, Provider.of(context).selectedProfile!, Provider.of(context).selectedConversation!, - id: Provider.of(context).selectedIndex!, byID: true), + future: messageHandler(context, Provider.of(context).selectedProfile!, Provider.of(context).selectedConversation!, ById(Provider.of(context).selectedIndex!)), builder: (context, snapshot) { if (snapshot.hasData) { var message = snapshot.data! as Message; diff --git a/lib/widgets/messagelist.dart b/lib/widgets/messagelist.dart index 4756381d..da8b3ea5 100644 --- a/lib/widgets/messagelist.dart +++ b/lib/widgets/messagelist.dart @@ -83,7 +83,7 @@ class _MessageListState extends State { var messageIndex = index; return FutureBuilder( - future: messageHandler(outerContext, profileOnion, contactHandle, byIndex: true, index: messageIndex), + future: messageHandler(outerContext, profileOnion, contactHandle, ByIndex(messageIndex)), builder: (context, snapshot) { if (snapshot.hasData) { var message = snapshot.data as Message;