I am growing an iOS app that makes use of a WKWebView
to show WhatsApp Internet (https://net.whatsapp.com
). I have to detect when a message is deleted within the WhatsApp Internet interface and deal with the occasion in my app utilizing the WKScriptMessageHandler
. Nonetheless, the messageDeleted
occasion will not be being triggered when a message is deleted within the WhatsApp Internet UI.
Right here is the related code the place I deal with the messages within the WKScriptMessageHandler
:
extension WhatsWebVC: WKScriptMessageHandler {
@objc func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
guard let physique = message.physique as? [String: Any],
let kind = physique["type"] as? String,
let information = physique["data"] as? [String: Any] else { return }
swap kind {
case "messageDeleted":
handleDeletedMessage(information) // This operate will not be being referred to as
case "mediaMessage":
handleMediaMessage(information)
case "wsReceive":
handleWebSocketMessage(information)
case "wsSend":
print("Outgoing WS message:", information)
default:
print("Unknown message kind acquired:", kind)
}
}
}
In my WebView’s JavaScript injection, I monitor when a message is deleted utilizing a MutationObserver
on the WhatsApp Internet chat container. When a message is deleted, I ship the messageDeleted
occasion again to the iOS app utilizing window.webkit.messageHandlers.messageObserver.postMessage()
.
Here is the JavaScript code that I inject into WhatsApp Internet:
(operate() {
let messageCache = new Map();
operate extractMessageContent(ingredient) {
let messageContainer = ingredient.querySelector('[data-pre-plain-text]');
let messageText = ingredient.querySelector('.selectable-text');
let mediaContainer = ingredient.querySelector('.media-container');
let timestampElement = ingredient.querySelector('div[data-pre-plain-text]');
let timestamp = '';
let sender="";
let mediaUrl="";
let mediaName="";
if (timestampElement) {
let preText = timestampElement.getAttribute('data-pre-plain-text');
if (preText) {
let matches = preText.match(/[(.*?)].*?([^:]+):/);
if (matches) {
timestamp = matches[1];
sender = matches[2].trim();
}
}
}
if (mediaContainer) {
let mediaElement = mediaContainer.querySelector('img, video');
if (mediaElement)
}
return {
id: ingredient.getAttribute('data-id'),
textual content: messageText ? messageText.innerText : '',
sender: sender,
timestamp: timestamp,
hasMedia: !!mediaContainer,
mediaUrl: mediaUrl,
mediaName: mediaName
};
}
const messageObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.kind === 'childList') {
mutation.removedNodes.forEach((node) => {
if (node.nodeType === Node.ELEMENT_NODE) {
let messageElement = node.querySelector('[data-id]');
if (messageElement) {
let messageId = messageElement.getAttribute('data-id');
window.webkit.messageHandlers.messageObserver.postMessage({
kind: 'messageDeleted',
information: extractMessageContent(messageElement)
});
}
}
});
}
});
});
operate observeChat() {
const chatContainer = doc.querySelector('#predominant div.copyable-area');
if (chatContainer) {
messageObserver.observe(chatContainer, {
childList: true,
subtree: true
});
} else {
setTimeout(observeChat, 1000);
}
}
operate initObserver() {
if (doc.querySelector('#app')) {
observeChat();
} else {
setTimeout(initObserver, 1000);
}
}
initObserver();
})();
On this JavaScript code:
- A
MutationObserver
listens for adjustments within the chat container and particularly checks when messages are eliminated. - If a message is deleted, I name
window.webkit.messageHandlers.messageObserver.postMessage()
to inform the app with themessageDeleted
kind and the corresponding message information.
What I’ve tried:
-
Make sure the JavaScript is injected: I’ve confirmed that the JavaScript is correctly injected into the
WKWebView
. The observer is firing when parts are faraway from the DOM, however themessageDeleted
message by no means reaches theuserContentController(_:didReceive:)
methodology within the iOS app. -
Message kind and information: I added print statements within the app to log incoming messages, however the “messageDeleted” case doesn’t get triggered, regardless that the WebView is accurately executing the JavaScript.
-
WebView configuration: I make sure that the WebView’s
WKUserContentController
is correctly configured to deal with messages:let userContentController = WKUserContentController() userContentController.add(self, identify: "messageObserver") let config = WKWebViewConfiguration() config.userContentController = userContentController let webView = WKWebView(body: .zero, configuration: config)
-
Injected JavaScript: I double-checked that the JavaScript executes accurately and that the
postMessage
operate is named with the anticipated information.
Query:
Why is the messageDeleted
case not being referred to as? Are there any points with how the JavaScript is speaking with the iOS app, or with how I’ve arrange the message handler in WKWebView
? What might be inflicting this downside, and the way can I repair it? Any ideas can be vastly appreciated!