new message marker moved from id to index and now works on old messages

This commit is contained in:
Dan Ballard 2022-04-29 16:00:52 -07:00
parent 0647a2d98d
commit ffa51e83a1
10 changed files with 40 additions and 46 deletions

View File

@ -42,7 +42,7 @@ class ContactInfoState extends ChangeNotifier {
late int _totalMessages = 0; late int _totalMessages = 0;
late DateTime _lastMessageTime; late DateTime _lastMessageTime;
late Map<String, GlobalKey<MessageRowState>> keys; late Map<String, GlobalKey<MessageRowState>> keys;
int _newMarkerMsgId = -1; int _newMarkerMsgIndex = -1;
late MessageCache messageCache; late MessageCache messageCache;
// todo: a nicer way to model contacts, groups and other "entities" // todo: a nicer way to model contacts, groups and other "entities"
@ -145,11 +145,12 @@ class ContactInfoState extends ChangeNotifier {
} }
void selected() { void selected() {
this._newMarkerMsgIndex = this._unreadMessages-1;
this._unreadMessages = 0; this._unreadMessages = 0;
} }
void unselected() { void unselected() {
this._newMarkerMsgId = -1; this._newMarkerMsgIndex = -1;
} }
int get unreadMessages => this._unreadMessages; int get unreadMessages => this._unreadMessages;
@ -159,8 +160,8 @@ class ContactInfoState extends ChangeNotifier {
notifyListeners(); notifyListeners();
} }
int get newMarkerMsgId { int get newMarkerMsgIndex {
return this._newMarkerMsgId; return this._newMarkerMsgIndex;
} }
int get totalMessages => this._totalMessages; int get totalMessages => this._totalMessages;
@ -240,8 +241,10 @@ class ContactInfoState extends ChangeNotifier {
if (!selectedConversation) { if (!selectedConversation) {
unreadMessages++; unreadMessages++;
} }
if (_newMarkerMsgId == -1) { if (_newMarkerMsgIndex == -1) {
_newMarkerMsgId = messageID; _newMarkerMsgIndex = 0;
} else {
_newMarkerMsgIndex++;
} }
this._lastMessageTime = timestamp; this._lastMessageTime = timestamp;

View File

@ -32,33 +32,34 @@ const GroupConversationHandleLength = 32;
abstract class Message { abstract class Message {
MessageMetadata getMetadata(); MessageMetadata getMetadata();
Widget getWidget(BuildContext context, Key key); Widget getWidget(BuildContext context, Key key, int index);
Widget getPreviewWidget(BuildContext context); Widget getPreviewWidget(BuildContext context);
} }
Message compileOverlay(MessageMetadata metadata, String messageData) { Message compileOverlay(MessageInfo messageInfo) {
try {
dynamic message = jsonDecode(messageData); try {
dynamic message = jsonDecode(messageInfo.wrapper);
var content = message['d'] as dynamic; var content = message['d'] as dynamic;
var overlay = int.parse(message['o'].toString()); var overlay = int.parse(message['o'].toString());
switch (overlay) { switch (overlay) {
case TextMessageOverlay: case TextMessageOverlay:
return TextMessage(metadata, content); return TextMessage(messageInfo.metadata, content);
case SuggestContactOverlay: case SuggestContactOverlay:
case InviteGroupOverlay: case InviteGroupOverlay:
return InviteMessage(overlay, metadata, content); return InviteMessage(overlay, messageInfo.metadata, content);
case QuotedMessageOverlay: case QuotedMessageOverlay:
return QuotedMessage(metadata, content); return QuotedMessage(messageInfo.metadata, content);
case FileShareOverlay: case FileShareOverlay:
return FileMessage(metadata, content); return FileMessage(messageInfo.metadata, content);
default: default:
// Metadata is valid, content is not.. // Metadata is valid, content is not..
return MalformedMessage(metadata); return MalformedMessage(messageInfo.metadata);
} }
} catch (e) { } catch (e) {
return MalformedMessage(metadata); return MalformedMessage(messageInfo.metadata);
} }
} }
@ -222,7 +223,7 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
MessageInfo? messageInfo = await cacheHandler.get(cwtch, profileOnion, conversationIdentifier, cache); MessageInfo? messageInfo = await cacheHandler.get(cwtch, profileOnion, conversationIdentifier, cache);
if (messageInfo != null) { if (messageInfo != null) {
return compileOverlay(messageInfo.metadata, messageInfo.wrapper); return compileOverlay(messageInfo);
} else { } else {
return MalformedMessage(malformedMetadata); return MalformedMessage(malformedMetadata);
} }

View File

@ -105,13 +105,6 @@ class MessageCache extends ChangeNotifier {
int get indexUnsynced => _indexUnsynced; int get indexUnsynced => _indexUnsynced;
// TODO: unused? delete?
void resetIndexCache() {
this._indexUnsynced = 0;
cacheByIndex = List.empty(growable: true);
notifyListeners();
}
MessageInfo? getById(int id) => cache[id]; MessageInfo? getById(int id) => cache[id];
Future<MessageInfo?> getByIndex(int index) async { Future<MessageInfo?> getByIndex(int index) async {

View File

@ -18,13 +18,13 @@ class FileMessage extends Message {
FileMessage(this.metadata, this.content); FileMessage(this.metadata, this.content);
@override @override
Widget getWidget(BuildContext context, Key key) { Widget getWidget(BuildContext context, Key key, int index) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
dynamic shareObj = jsonDecode(this.content); dynamic shareObj = jsonDecode(this.content);
if (shareObj == null) { if (shareObj == null) {
return MessageRow(MalformedBubble()); return MessageRow(MalformedBubble(), index);
} }
String nameSuggestion = shareObj['f'] as String; String nameSuggestion = shareObj['f'] as String;
String rootHash = shareObj['h'] as String; String rootHash = shareObj['h'] as String;
@ -39,10 +39,10 @@ class FileMessage extends Message {
} }
if (!validHash(rootHash, nonce)) { if (!validHash(rootHash, nonce)) {
return MessageRow(MalformedBubble()); return MessageRow(MalformedBubble(), index);
} }
return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize, isAuto: metadata.isAuto), key: key); return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize, isAuto: metadata.isAuto), index, key: key);
}); });
} }
@ -53,14 +53,14 @@ class FileMessage extends Message {
builder: (bcontext, child) { builder: (bcontext, child) {
dynamic shareObj = jsonDecode(this.content); dynamic shareObj = jsonDecode(this.content);
if (shareObj == null) { if (shareObj == null) {
return MessageRow(MalformedBubble()); return MessageRow(MalformedBubble(), 0);
} }
String nameSuggestion = shareObj['n'] as String; String nameSuggestion = shareObj['n'] as String;
String rootHash = shareObj['h'] as String; String rootHash = shareObj['h'] as String;
String nonce = shareObj['n'] as String; String nonce = shareObj['n'] as String;
int fileSize = shareObj['s'] as int; int fileSize = shareObj['s'] as int;
if (!validHash(rootHash, nonce)) { if (!validHash(rootHash, nonce)) {
return MessageRow(MalformedBubble()); return MessageRow(MalformedBubble(), 0);
} }
return Container( return Container(
alignment: Alignment.center, alignment: Alignment.center,

View File

@ -17,7 +17,7 @@ class InviteMessage extends Message {
InviteMessage(this.overlay, this.metadata, this.content); InviteMessage(this.overlay, this.metadata, this.content);
@override @override
Widget getWidget(BuildContext context, Key key) { Widget getWidget(BuildContext context, Key key, int index) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
@ -36,10 +36,10 @@ class InviteMessage extends Message {
inviteTarget = jsonObj['GroupID']; inviteTarget = jsonObj['GroupID'];
inviteNick = jsonObj['GroupName']; inviteNick = jsonObj['GroupName'];
} else { } else {
return MessageRow(MalformedBubble()); return MessageRow(MalformedBubble(), index);
} }
} }
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), key: key); return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite), index, key: key);
}); });
} }

View File

@ -9,11 +9,11 @@ class MalformedMessage extends Message {
MalformedMessage(this.metadata); MalformedMessage(this.metadata);
@override @override
Widget getWidget(BuildContext context, Key key) { Widget getWidget(BuildContext context, Key key, int index) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (context, child) { builder: (context, child) {
return MessageRow(MalformedBubble(), key: key); return MessageRow(MalformedBubble(), index, key: key);
}); });
} }

View File

@ -48,7 +48,7 @@ class QuotedMessage extends Message {
} }
@override @override
Widget getWidget(BuildContext context, Key key) { Widget getWidget(BuildContext context, Key key, int index) {
try { try {
dynamic message = jsonDecode(this.content); dynamic message = jsonDecode(this.content);
@ -59,7 +59,7 @@ class QuotedMessage extends Message {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { 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"]))), index, key: key);
}); });
} catch (e) { } catch (e) {
return MalformedBubble(); return MalformedBubble();

View File

@ -29,12 +29,12 @@ class TextMessage extends Message {
} }
@override @override
Widget getWidget(BuildContext context, Key key) { Widget getWidget(BuildContext context, Key key, int index) {
return ChangeNotifierProvider.value( return ChangeNotifierProvider.value(
value: this.metadata, value: this.metadata,
builder: (bcontext, child) { builder: (bcontext, child) {
return MessageRow( return MessageRow(
MessageBubble(this.content), MessageBubble(this.content), index,
key: key, key: key,
); );
}); });

View File

@ -100,7 +100,7 @@ class _MessageListState extends State<MessageList> {
// reliably use this without running into duplicate keys...it isn't ideal as it means keys need to be re-built // reliably use this without running into duplicate keys...it isn't ideal as it means keys need to be re-built
// when new messages are added...however it is better than the alternative of not having widget keys at all. // when new messages are added...however it is better than the alternative of not having widget keys at all.
var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, messageIndex); var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, messageIndex);
return message.getWidget(context, key); return message.getWidget(context, key, messageIndex);
} else { } else {
return MessageLoadingBubble(); return MessageLoadingBubble();
} }

View File

@ -18,8 +18,9 @@ import '../settings.dart';
class MessageRow extends StatefulWidget { class MessageRow extends StatefulWidget {
final Widget child; final Widget child;
final int index;
MessageRow(this.child, {Key? key}) : super(key: key); MessageRow(this.child, this.index, {Key? key}) : super(key: key);
@override @override
MessageRowState createState() => MessageRowState(); MessageRowState createState() => MessageRowState();
@ -32,12 +33,9 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
late Alignment _dragAlignment = Alignment.center; late Alignment _dragAlignment = Alignment.center;
Alignment _dragAffinity = Alignment.center; Alignment _dragAffinity = Alignment.center;
late int index;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
index = Provider.of<MessageMetadata>(context, listen: false).messageID;
_controller = AnimationController(vsync: this); _controller = AnimationController(vsync: this);
_controller.addListener(() { _controller.addListener(() {
setState(() { setState(() {
@ -224,8 +222,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
children: widgetRow, children: widgetRow,
))))); )))));
var markMsgId = Provider.of<ContactInfoState>(context).newMarkerMsgId; if (Provider.of<ContactInfoState>(context).newMarkerMsgIndex == widget.index) {
if (markMsgId == Provider.of<MessageMetadata>(context).messageID) {
return Column(crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [Align(alignment: Alignment.center, child: _bubbleNew()), mr]); return Column(crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [Align(alignment: Alignment.center, child: _bubbleNew()), mr]);
} else { } else {
return mr; return mr;