smserver
smserver copied to clipboard
[Feature Request] Support for iOS 14 In-Line replies
Even if it starts off as view only, this would be a cool feature to have on the web client
@iandwelker in case you want to implement this:
-
To render replies, you'd want to pull the
thread_originator_guid
column fromchat.db
. You can kinda see in here (the line renderer), here (the message bubble itself that decides whether the line should get rendered), and here (code that does some of the processing of whether the message is a reply, whether it should show the reply line, how that reply line is gonna look, etc) -
To send replies, refer to the following objc code:
// get the chat
IMChat *chat = [BlueBubblesHelper getChat: data[@"chatGuid"]];
// get the message text
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString: data[@"message"]];
// get the subject line, if any
NSMutableAttributedString *subjectAttributedString = nil;
if ([data objectForKey:(@"subject")] != [NSNull null]) {
subjectAttributedString = [[NSMutableAttributedString alloc] initWithString: data[@"subject"]];
}
// get the effect ID, if any
NSString *effectId = nil;
if ([data objectForKey:(@"effectId")] != [NSNull null]) {
effectId = data[@"effectId"];
}
// helper function to create a message
void (^createMessage)(NSAttributedString*, NSAttributedString*, NSString*, NSString*) = ^(NSAttributedString *message, NSAttributedString *subject, NSString *effectId, NSString *threadIdentifier) {
// init an IMMessage with the text, subject, and effect ID
IMMessage *messageToSend = [[IMMessage alloc] init];
messageToSend = [messageToSend initWithSender:(nil) time:(nil) text:(message) messageSubject:(subject) fileTransferGUIDs:(nil) flags:(100005) error:(nil) guid:(nil) subject:(nil) balloonBundleID:(nil) payloadData:(nil) expressiveSendStyleID:(effectId)];
// add the thread ID for the reply
messageToSend.threadIdentifier = threadIdentifier;
// send it
[chat sendMessage:(messageToSend)];
};
if ([data objectForKey:(@"selectedMessageGuid")] != [NSNull null]) {
// get the message being replied to
[BlueBubblesHelper getMessageItem:(chat) :(data[@"selectedMessageGuid"]) completionBlock:^(IMMessage *message) {
// get the specific IMMessagePartChatItem out of the message
IMMessageItem *messageItem = (IMMessageItem *)message._imMessageItem;
NSObject *items = messageItem._newChatItems;
IMMessagePartChatItem *item;
// sometimes items is an array so we need to account for that
if ([items isKindOfClass:[NSArray class]]) {
for(IMMessagePartChatItem* imci in (NSArray *)items) {
if([imci._item.guid isEqualToString:(data[@"selectedMessageGuid"])]) {
DLog(@"BLUEBUBBLESHELPER: %@", data[@"selectedMessageGuid"]);
item = imci;
}
}
} else {
item = (IMMessagePartChatItem *)items;
}
NSString *identifier = @"";
// either reply to an existing thread or create a new thread
if (message.threadIdentifier != nil) {
identifier = message.threadIdentifier;
} else {
identifier = IMCreateThreadIdentifierForMessagePartChatItem(item);
}
createMessage(attributedString, subjectAttributedString, effectId, identifier);
}];
}
If you got more questions lmk!
@tneotia, your third link is now dead (the one that comes before "code that does some of the processing of whether the message is a reply, whether it should show the reply line, how that reply line is gonna look, etc"). Is this link a correct/updated one, or no?
https://github.com/BlueBubblesApp/bluebubbles-app/blob/development/lib/repository/models/io/message.dart#L909-L964