New Cwtch Library Integration #258
|
@ -184,6 +184,7 @@ class FlwtchWorker(context: Context, parameters: WorkerParameters) :
|
|||
val profile = (a.get("ProfileOnion") as? String) ?: ""
|
||||
val conversation = a.getInt("conversation").toLong()
|
||||
val indexI = a.getInt("index").toLong()
|
||||
Log.i("FlwtchWorker", "Cwtch GetMessage " + profile + " " + conversation.toString() + " " + indexI.toString())
|
||||
sarah marked this conversation as resolved
Outdated
|
||||
return Result.success(Data.Builder().putString("result", Cwtch.getMessage(profile, conversation, indexI)).build())
|
||||
}
|
||||
"GetMessageByID" -> {
|
||||
|
|
|
@ -30,6 +30,7 @@ import android.os.Build
|
|||
import android.os.Environment
|
||||
import android.database.Cursor
|
||||
import android.provider.MediaStore
|
||||
import cwtch.Cwtch
|
||||
|
||||
class MainActivity: FlutterActivity() {
|
||||
override fun provideSplashScreen(): SplashScreen? = SplashView()
|
||||
|
|
|
@ -130,6 +130,10 @@ class CwtchNotifier {
|
|||
case "NewMessageFromPeer":
|
||||
notificationManager.notify("New Message From Peer!");
|
||||
var identifier = int.parse(data["ConversationID"]);
|
||||
var messageID = int.parse(data["Index"]);
|
||||
var timestamp = DateTime.tryParse(data['TimestampReceived'])!;
|
||||
var senderHandle = data['RemotePeer'];
|
||||
var senderImage = data['Picture'];
|
||||
|
||||
// We might not have received a contact created for this contact yet...
|
||||
// In that case the **next** event we receive will actually update these values...
|
||||
|
@ -140,6 +144,7 @@ class CwtchNotifier {
|
|||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++;
|
||||
}
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.updateLastMessageTime(identifier, DateTime.now());
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.updateMessageCache(identifier, messageID, timestamp, senderHandle, senderImage, data["Data"], "");
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++;
|
||||
|
||||
// We only ever see messages from authenticated peers.
|
||||
|
@ -156,11 +161,12 @@ class CwtchNotifier {
|
|||
break;
|
||||
case "IndexedAcknowledgement":
|
||||
var conversation = int.parse(data["ConversationID"]);
|
||||
var message_index = int.parse(data["Index"]);
|
||||
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 (message_index == -1) break;
|
||||
var key = contact!.getMessageKeyOrFail(conversation, message_index, contact.lastMessageTime);
|
||||
if (messageID == -1) break;
|
||||
var key = contact!.getMessageKeyOrFail(conversation, messageID, contact.lastMessageTime);
|
||||
if (key == null) break;
|
||||
try {
|
||||
var message = Provider.of<MessageMetadata>(key.currentContext!, listen: false);
|
||||
|
@ -181,11 +187,19 @@ class CwtchNotifier {
|
|||
var identifier = int.parse(data["ConversationID"]);
|
||||
if (data["ProfileOnion"] != data["RemotePeer"]) {
|
||||
var idx = int.parse(data["Index"]);
|
||||
var senderHandle = data['RemotePeer'];
|
||||
var senderImage = data['Picture'];
|
||||
var timestampSent = DateTime.tryParse(data['TimestampSent'])!;
|
||||
var currentTotal = profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages;
|
||||
|
||||
// Only bother to do anything if we know about the group and the provided index is greater than our current total...
|
||||
if (currentTotal != null && idx >= currentTotal) {
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages = idx + 1;
|
||||
profileCN
|
||||
.getProfile(data["ProfileOnion"])
|
||||
?.contactList
|
||||
.getContact(identifier)!
|
||||
.updateMessageCache(identifier, idx, timestampSent, senderHandle, senderImage, data["Data"], data["Signature"]);
|
||||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.totalMessages++;
|
||||
|
||||
//if not currently open
|
||||
if (appState.selectedProfile != data["ProfileOnion"] || appState.selectedConversation != identifier) {
|
||||
|
@ -194,7 +208,6 @@ class CwtchNotifier {
|
|||
profileCN.getProfile(data["ProfileOnion"])?.contactList.getContact(identifier)!.newMarker++;
|
||||
}
|
||||
|
||||
var timestampSent = DateTime.tryParse(data['TimestampSent'])!;
|
||||
// TODO: There are 2 timestamps associated with a new group message - time sent and time received.
|
||||
// Sent refers to the time a profile alleges they sent a message
|
||||
// Received refers to the time we actually saw the message from the server
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/widgets/messagerow.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:cwtch/models/profileservers.dart';
|
||||
|
@ -501,6 +502,12 @@ ContactAuthorization stringToContactAuthorization(String authStr) {
|
|||
}
|
||||
}
|
||||
|
||||
class MessageCache {
|
||||
final MessageMetadata metadata;
|
||||
final String wrapper;
|
||||
MessageCache(this.metadata, this.wrapper);
|
||||
}
|
||||
|
||||
class ContactInfoState extends ChangeNotifier {
|
||||
final String profileOnion;
|
||||
final int identifier;
|
||||
|
@ -515,6 +522,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
late int _totalMessages = 0;
|
||||
late DateTime _lastMessageTime;
|
||||
late Map<String, GlobalKey<MessageRowState>> keys;
|
||||
late List<MessageCache?> messageCache;
|
||||
int _newMarker = 0;
|
||||
DateTime _newMarkerClearAt = DateTime.now();
|
||||
|
||||
|
@ -546,6 +554,7 @@ class ContactInfoState extends ChangeNotifier {
|
|||
this._lastMessageTime = lastMessageTime == null ? DateTime.fromMillisecondsSinceEpoch(0) : lastMessageTime;
|
||||
this._server = server;
|
||||
this._archived = archived;
|
||||
this.messageCache = List.empty(growable: true);
|
||||
keys = Map<String, GlobalKey<MessageRowState>>();
|
||||
}
|
||||
|
||||
|
@ -677,4 +686,12 @@ class ContactInfoState extends ChangeNotifier {
|
|||
GlobalKey<MessageRowState> ret = keys[index]!;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void updateMessageCache(int conversation, int messageID, DateTime timestamp, String senderHandle, String senderImage, String data, String signature) {
|
||||
this.messageCache.insert(0, MessageCache(MessageMetadata(profileOnion, conversation, messageID, timestamp, senderHandle, senderImage, signature, {}, false, false), data));
|
||||
}
|
||||
|
||||
void bumpMessageCache() {
|
||||
sarah marked this conversation as resolved
dan
commented
ideally internal. the public setter for totalMessages can call, and updateMessageCaches should internally inc totalMessages ideally internal. the public setter for totalMessages can call, and updateMessageCaches should internally inc totalMessages
|
||||
this.messageCache.insert(0, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,11 +28,43 @@ const GroupConversationHandleLength = 32;
|
|||
|
||||
abstract class Message {
|
||||
MessageMetadata getMetadata();
|
||||
Widget getWidget(BuildContext context);
|
||||
Widget getWidget(BuildContext context, Key key);
|
||||
Widget getPreviewWidget(BuildContext context);
|
||||
}
|
||||
|
||||
Message compileOverlay(MessageMetadata metadata, String messageData) {
|
||||
try {
|
||||
dynamic message = jsonDecode(messageData);
|
||||
var content = message['d'] as dynamic;
|
||||
var overlay = int.parse(message['o'].toString());
|
||||
|
||||
switch (overlay) {
|
||||
case TextMessageOverlay:
|
||||
return TextMessage(metadata, content);
|
||||
case SuggestContactOverlay:
|
||||
case InviteGroupOverlay:
|
||||
return InviteMessage(overlay, metadata, content);
|
||||
case QuotedMessageOverlay:
|
||||
return QuotedMessage(metadata, content);
|
||||
case FileShareOverlay:
|
||||
return FileMessage(metadata, content);
|
||||
default:
|
||||
// Metadata is valid, content is not..
|
||||
return MalformedMessage(metadata);
|
||||
}
|
||||
} catch (e) {
|
||||
return MalformedMessage(metadata);
|
||||
}
|
||||
}
|
||||
|
||||
Future<Message> messageHandler(BuildContext context, String profileOnion, int conversationIdentifier, int index, {bool byID = false}) {
|
||||
var cache = Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(conversationIdentifier)!.messageCache;
|
||||
if (cache.length > index) {
|
||||
if (cache[index] != null) {
|
||||
return Future.value(compileOverlay(cache[index]!.metadata, cache[index]!.wrapper));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Future<dynamic> rawMessageEnvelopeFuture;
|
||||
|
||||
|
@ -43,7 +75,7 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
|
|||
}
|
||||
|
||||
return rawMessageEnvelopeFuture.then((dynamic rawMessageEnvelope) {
|
||||
var metadata = MessageMetadata(profileOnion, conversationIdentifier, index, -1, DateTime.now(), "", "", "", <String, String>{}, false, true);
|
||||
var metadata = MessageMetadata(profileOnion, conversationIdentifier, index, DateTime.now(), "", "", "", <String, String>{}, false, true);
|
||||
try {
|
||||
dynamic messageWrapper = jsonDecode(rawMessageEnvelope);
|
||||
// There are 2 conditions in which this error condition can be met:
|
||||
|
@ -58,7 +90,7 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
|
|||
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 messageHandler(context, profileOnion, conversationIdentifier, index, byID: byID).then((value) => value);
|
||||
return messageHandler(context, profileOnion, conversationIdentifier, -1, byID: byID).then((value) => value);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -71,33 +103,16 @@ Future<Message> messageHandler(BuildContext context, String profileOnion, int co
|
|||
var ackd = messageWrapper['Acknowledged'];
|
||||
var error = messageWrapper['Error'] != null;
|
||||
var signature = messageWrapper['Signature'];
|
||||
metadata = MessageMetadata(profileOnion, conversationIdentifier, index, messageID, timestamp, senderHandle, senderImage, signature, attributes, ackd, error);
|
||||
metadata = MessageMetadata(profileOnion, conversationIdentifier, messageID, timestamp, senderHandle, senderImage, signature, attributes, ackd, error);
|
||||
|
||||
dynamic message = jsonDecode(messageWrapper['Message']);
|
||||
var content = message['d'] as dynamic;
|
||||
var overlay = int.parse(message['o'].toString());
|
||||
|
||||
switch (overlay) {
|
||||
case TextMessageOverlay:
|
||||
return TextMessage(metadata, content);
|
||||
case SuggestContactOverlay:
|
||||
case InviteGroupOverlay:
|
||||
return InviteMessage(overlay, metadata, content);
|
||||
case QuotedMessageOverlay:
|
||||
return QuotedMessage(metadata, content);
|
||||
case FileShareOverlay:
|
||||
return FileMessage(metadata, content);
|
||||
default:
|
||||
// Metadata is valid, content is not..
|
||||
return MalformedMessage(metadata);
|
||||
}
|
||||
return compileOverlay(metadata, messageWrapper['Message']);
|
||||
} catch (e) {
|
||||
EnvironmentConfig.debugLog("an error! " + e.toString());
|
||||
return MalformedMessage(metadata);
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
return Future.value(MalformedMessage(MessageMetadata(profileOnion, conversationIdentifier, index, -1, DateTime.now(), "", "", "", <String, String>{}, false, true)));
|
||||
return Future.value(MalformedMessage(MessageMetadata(profileOnion, conversationIdentifier, -1, DateTime.now(), "", "", "", <String, String>{}, false, true)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +120,6 @@ class MessageMetadata extends ChangeNotifier {
|
|||
// meta-metadata
|
||||
final String profileOnion;
|
||||
final int conversationIdentifier;
|
||||
final int messageIndex;
|
||||
final int messageID;
|
||||
|
||||
final DateTime timestamp;
|
||||
|
@ -131,6 +145,5 @@ class MessageMetadata extends ChangeNotifier {
|
|||
notifyListeners();
|
||||
}
|
||||
|
||||
MessageMetadata(this.profileOnion, this.conversationIdentifier, this.messageIndex, this.messageID, this.timestamp, this.senderHandle, this.senderImage, this.signature, this._attributes, this._ackd,
|
||||
this._error);
|
||||
MessageMetadata(this.profileOnion, this.conversationIdentifier, this.messageID, this.timestamp, this.senderHandle, this.senderImage, this.signature, this._attributes, this._ackd, this._error);
|
||||
}
|
||||
|
|
|
@ -17,8 +17,9 @@ class FileMessage extends Message {
|
|||
FileMessage(this.metadata, this.content);
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context) {
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
return ChangeNotifierProvider.value(
|
||||
key: key,
|
||||
value: this.metadata,
|
||||
builder: (bcontext, child) {
|
||||
dynamic shareObj = jsonDecode(this.content);
|
||||
|
@ -34,9 +35,7 @@ class FileMessage extends Message {
|
|||
return MessageRow(MalformedBubble());
|
||||
}
|
||||
|
||||
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
|
||||
return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize),
|
||||
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
|
||||
return MessageRow(FileBubble(nameSuggestion, rootHash, nonce, fileSize));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@ class InviteMessage extends Message {
|
|||
InviteMessage(this.overlay, this.metadata, this.content);
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context) {
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
return ChangeNotifierProvider.value(
|
||||
key: key,
|
||||
value: this.metadata,
|
||||
builder: (bcontext, child) {
|
||||
String inviteTarget;
|
||||
|
@ -40,8 +41,7 @@ class InviteMessage extends Message {
|
|||
}
|
||||
}
|
||||
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
|
||||
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite),
|
||||
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
|
||||
return MessageRow(InvitationBubble(overlay, inviteTarget, inviteNick, invite));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,9 @@ class MalformedMessage extends Message {
|
|||
MalformedMessage(this.metadata);
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context) {
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
return ChangeNotifierProvider.value(
|
||||
key: key,
|
||||
value: this.metadata,
|
||||
builder: (context, child) {
|
||||
return MessageRow(MalformedBubble());
|
||||
|
|
|
@ -51,7 +51,7 @@ class QuotedMessage extends Message {
|
|||
dynamic message = jsonDecode(this.content);
|
||||
return Text(message["body"]);
|
||||
} catch (e) {
|
||||
return MalformedMessage(this.metadata).getWidget(context);
|
||||
return MalformedMessage(this.metadata).getWidget(context, Key("malformed"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -62,16 +62,15 @@ class QuotedMessage extends Message {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context) {
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
try {
|
||||
dynamic message = jsonDecode(this.content);
|
||||
|
||||
if (message["body"] == null || message["quotedHash"] == null) {
|
||||
return MalformedMessage(this.metadata).getWidget(context);
|
||||
return MalformedMessage(this.metadata).getWidget(context, key);
|
||||
}
|
||||
|
||||
var quotedMessagePotentials = Provider.of<FlwtchState>(context).cwtch.GetMessageByContentHash(metadata.profileOnion, metadata.conversationIdentifier, message["quotedHash"]);
|
||||
int messageIndex = metadata.messageIndex;
|
||||
Future<LocallyIndexedMessage?> quotedMessage = quotedMessagePotentials.then((matchingMessages) {
|
||||
if (matchingMessages == "[]") {
|
||||
return null;
|
||||
|
@ -81,9 +80,7 @@ class QuotedMessage extends Message {
|
|||
// message
|
||||
try {
|
||||
var list = (jsonDecode(matchingMessages) as List<dynamic>).map((data) => LocallyIndexedMessage.fromJson(data)).toList();
|
||||
LocallyIndexedMessage candidate = list.reversed.firstWhere((element) => messageIndex < element.index, orElse: () {
|
||||
return list.firstWhere((element) => messageIndex > element.index);
|
||||
});
|
||||
LocallyIndexedMessage candidate = list.reversed.first;
|
||||
return candidate;
|
||||
} catch (e) {
|
||||
// Malformed Message will be returned...
|
||||
|
@ -92,20 +89,18 @@ class QuotedMessage extends Message {
|
|||
});
|
||||
|
||||
return ChangeNotifierProvider.value(
|
||||
key: key,
|
||||
value: this.metadata,
|
||||
builder: (bcontext, child) {
|
||||
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
|
||||
return MessageRow(
|
||||
QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) {
|
||||
if (localIndex != null) {
|
||||
return messageHandler(context, metadata.profileOnion, metadata.conversationIdentifier, localIndex.index);
|
||||
}
|
||||
return MalformedMessage(this.metadata);
|
||||
})),
|
||||
key: Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt));
|
||||
return MessageRow(QuotedMessageBubble(message["body"], quotedMessage.then((LocallyIndexedMessage? localIndex) {
|
||||
if (localIndex != null) {
|
||||
return messageHandler(context, metadata.profileOnion, metadata.conversationIdentifier, localIndex.index);
|
||||
}
|
||||
return MalformedMessage(this.metadata);
|
||||
})));
|
||||
});
|
||||
} catch (e) {
|
||||
return MalformedMessage(this.metadata).getWidget(context);
|
||||
return MalformedMessage(this.metadata).getWidget(context, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,14 +31,15 @@ class TextMessage extends Message {
|
|||
}
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context) {
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
return ChangeNotifierProvider.value(
|
||||
key: key,
|
||||
value: this.metadata,
|
||||
builder: (bcontext, child) {
|
||||
var lrt = Provider.of<ContactInfoState>(bcontext).lastMessageTime;
|
||||
var key = Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt);
|
||||
// var key = Provider.of<ContactInfoState>(bcontext).getMessageKey(this.metadata.conversationIdentifier, this.metadata.messageID, lrt);
|
||||
|
||||
return MessageRow(MessageBubble(this.content), key: key);
|
||||
return MessageRow(MessageBubble(this.content));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'package:crypto/crypto.dart';
|
||||
import 'package:cwtch/config.dart';
|
||||
import 'package:cwtch/cwtch_icons_icons.dart';
|
||||
import 'package:cwtch/models/message.dart';
|
||||
import 'package:cwtch/models/messages/quotedmessage.dart';
|
||||
|
@ -213,6 +214,7 @@ class _MessageViewState extends State<MessageView> {
|
|||
ctrlrCompose.clear();
|
||||
focusNode.requestFocus();
|
||||
Future.delayed(const Duration(milliseconds: 80), () {
|
||||
Provider.of<ProfileInfoState>(context, listen: false).contactList.getContact(Provider.of<ContactInfoState>(context, listen: false).identifier)?.bumpMessageCache();
|
||||
Provider.of<ContactInfoState>(context, listen: false).totalMessages++;
|
||||
Provider.of<ContactInfoState>(context, listen: false).newMarker++;
|
||||
// Resort the contact list...
|
||||
|
|
|
@ -79,13 +79,15 @@ class _MessageListState extends State<MessageList> {
|
|||
var contactHandle = Provider.of<ContactInfoState>(outerContext, listen: false).identifier;
|
||||
var messageIndex = index;
|
||||
|
||||
// var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, Provider.of<ContactInfoState>(outerContext).totalMessages - index, DateTime.now());
|
||||
return FutureBuilder(
|
||||
//key: Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, Provider.of<ContactInfoState>(outerContext).totalMessages - index, DateTime.now()),
|
||||
future: messageHandler(outerContext, profileOnion, contactHandle, messageIndex),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.hasData) {
|
||||
var message = snapshot.data as Message;
|
||||
// Already includes MessageRow,,
|
||||
return message.getWidget(context);
|
||||
var key = Provider.of<ContactInfoState>(outerContext, listen: false).getMessageKey(contactHandle, message.getMetadata().messageID, DateTime.now());
|
||||
return message.getWidget(context, key);
|
||||
} else {
|
||||
return MessageLoadingBubble();
|
||||
}
|
||||
|
@ -97,3 +99,23 @@ class _MessageListState extends State<MessageList> {
|
|||
])));
|
||||
}
|
||||
}
|
||||
|
||||
class CachedMessage extends Message {
|
||||
sarah marked this conversation as resolved
Outdated
dan
commented
delete class? delete class?
|
||||
@override
|
||||
MessageMetadata getMetadata() {
|
||||
// TODO: implement getMetadata
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget getPreviewWidget(BuildContext context) {
|
||||
// TODO: implement getPreviewWidget
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget getWidget(BuildContext context, Key key) {
|
||||
// TODO: implement getWidget
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
index = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
||||
index = Provider.of<MessageMetadata>(context, listen: false).messageID;
|
||||
_controller = AnimationController(vsync: this);
|
||||
_controller.addListener(() {
|
||||
setState(() {
|
||||
|
@ -75,7 +75,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
}
|
||||
|
||||
Widget wdgIcons = Visibility(
|
||||
visible: Provider.of<AppState>(context).hoveredIndex == Provider.of<MessageMetadata>(context).messageIndex,
|
||||
visible: Provider.of<AppState>(context).hoveredIndex == Provider.of<MessageMetadata>(context).messageID,
|
||||
maintainSize: true,
|
||||
maintainAnimation: true,
|
||||
maintainState: true,
|
||||
|
@ -169,7 +169,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
// For desktop...
|
||||
onHover: (event) {
|
||||
setState(() {
|
||||
Provider.of<AppState>(context, listen: false).hoveredIndex = Provider.of<MessageMetadata>(context, listen: false).messageIndex;
|
||||
Provider.of<AppState>(context, listen: false).hoveredIndex = Provider.of<MessageMetadata>(context, listen: false).messageID;
|
||||
});
|
||||
},
|
||||
onExit: (event) {
|
||||
|
@ -204,7 +204,7 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
children: widgetRow,
|
||||
)))));
|
||||
var mark = Provider.of<ContactInfoState>(context).newMarker;
|
||||
if (mark > 0 && mark == Provider.of<MessageMetadata>(context).messageIndex + 1) {
|
||||
if (mark > 0 && Provider.of<ContactInfoState>(context).messageCache[mark]?.metadata.messageID == Provider.of<MessageMetadata>(context).messageID) {
|
||||
return Column(crossAxisAlignment: fromMe ? CrossAxisAlignment.end : CrossAxisAlignment.start, children: [Align(alignment: Alignment.center, child: _bubbleNew()), mr]);
|
||||
} else {
|
||||
return mr;
|
||||
|
@ -251,12 +251,17 @@ class MessageRowState extends State<MessageRow> with SingleTickerProviderStateMi
|
|||
}
|
||||
|
||||
void _btnGoto() {
|
||||
selectConversation(context, Provider.of<MessageMetadata>(context, listen: false).conversationIdentifier);
|
||||
var id = Provider.of<ProfileInfoState>(context, listen: false).contactList.findContact(Provider.of<MessageMetadata>(context, listen: false).senderHandle)?.identifier;
|
||||
if (id == null) {
|
||||
// Can't happen
|
||||
} else {
|
||||
selectConversation(context, id);
|
||||
}
|
||||
}
|
||||
|
||||
void _btnAdd() {
|
||||
var sender = Provider.of<MessageMetadata>(context, listen: false).senderHandle;
|
||||
if (sender == null || sender == "") {
|
||||
if (sender == "") {
|
||||
print("sender not yet loaded");
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
remove or debug