ios: implement window.confirm()/alert() in the Mac app's webview (#104)
WKUIDelegate silently no-ops window.confirm()/alert() unless the host app implements runJavaScriptConfirmPanelWithMessage/AlertPanelWithMessage. Without them, chat.js's "Cancel invite" (and every other confirm(): delete message, remove from group, leave group, sign out) as well as error alert()s did nothing on Mac. Add both, backed by a non-blocking NSAlert sheet rather than runModal(), since confirm()/alert() block the page's JS thread until completionHandler fires.
Co-authored-by: Claude <noreply@anthropic.com>
1 file changed,
+39
−0
ios/LChatMac/ChatFeedWebView.swift+39 −0
diff --git a/ios/LChatMac/ChatFeedWebView.swift b/ios/LChatMac/ChatFeedWebView.swift| index dac421a..461dc9d 100644 |
| --- a/ios/LChatMac/ChatFeedWebView.swift |
| +++ b/ios/LChatMac/ChatFeedWebView.swift |
| @@ -365,6 +365,45 @@ struct ChatFeedWebView: NSViewRepresentable { |
| } |
| } |
| + // WKUIDelegate shows nothing for window.confirm()/alert() unless we implement |
| + // these — chat.js's "Cancel invite", "Remove from group", "Leave group", "Sign |
| + // out", and delete-message confirms all silently no-op without them. Use a |
| + // sheet, not NSAlert.runModal(): confirm()/alert() block the page's JS thread |
| + // until completionHandler fires, and a nested runModal loop risks the same |
| + // webview freeze the notifyError() comment in chat.js warns about. |
| + func webView(_ webView: WKWebView, |
| + runJavaScriptConfirmPanelWithMessage message: String, |
| + initiatedByFrame frame: WKFrameInfo, |
| + completionHandler: @escaping (Bool) -> Void) { |
| + let alert = NSAlert() |
| + alert.messageText = message |
| + alert.addButton(withTitle: "OK") |
| + alert.addButton(withTitle: "Cancel") |
| + if let window = webView.window { |
| + alert.beginSheetModal(for: window) { completionHandler($0 == .alertFirstButtonReturn) } |
| + } else { |
| + completionHandler(alert.runModal() == .alertFirstButtonReturn) |
| + } |
| + } |
| + |
| + // Same gap as runJavaScriptConfirmPanelWithMessage above, for window.alert() — |
| + // on Mac chat.js's `embed` is always nil, so notifyError() and upload-error |
| + // messages call plain alert() rather than posting to the native shell. |
| + func webView(_ webView: WKWebView, |
| + runJavaScriptAlertPanelWithMessage message: String, |
| + initiatedByFrame frame: WKFrameInfo, |
| + completionHandler: @escaping () -> Void) { |
| + let alert = NSAlert() |
| + alert.messageText = message |
| + alert.addButton(withTitle: "OK") |
| + if let window = webView.window { |
| + alert.beginSheetModal(for: window) { _ in completionHandler() } |
| + } else { |
| + alert.runModal() |
| + completionHandler() |
| + } |
| + } |
| + |
| // Message links and link-preview cards render as target="_blank" anchors |
| // (chat.js), which WebKit routes here as a new-window request rather than a |
| // normal navigation. With no WKUIDelegate handling it, the click did nothing. |