sgtaziz / WebMessage

A client for communicating with the WebMessage tweak on iOS. Send and receive messages from the comfort of your computer
73 stars 12 forks source link

Support for Inline Replies #168

Open wonkieinc opened 3 years ago

wonkieinc commented 3 years ago

iOS 14 has inline replies, is there a way to integrate support for this?

sabogalc commented 3 years ago

29

sabogalc commented 3 years ago

Here is some info from @tneotia at https://github.com/iandwelker/smserver/issues/135#issuecomment-953390109

@iandwelker in case you want to implement this:

  1. To render replies, you'd want to pull the thread_originator_guid column from chat.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)
  2. 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!