From 6c8d0e40e23ac3369a45f4a94de621626c7300d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pantale=C3=A3o=20Gon=C3=A7alves?= <5808343+bgoncal@users.noreply.github.com> Date: Thu, 13 Nov 2025 22:50:25 +0100 Subject: [PATCH] Hack copy-paste logic on mac catalyst (#3975) Copy/Paste WKWebView on Mac Catalyst apps is known to be buggy and unreliable, while Apple does not fix this, this PR adds a hack alternative which links shift + command + c/v to custom copy paste methods, same used by the new mac top bar copy/paste icons ## Summary ## Screenshots ## Link to pull request in Documentation repository Documentation: home-assistant/companion.home-assistant# ## Any other notes --- Sources/App/WebView/WebViewController.swift | 26 ++++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Sources/App/WebView/WebViewController.swift b/Sources/App/WebView/WebViewController.swift index e7da4251f..f4256d603 100644 --- a/Sources/App/WebView/WebViewController.swift +++ b/Sources/App/WebView/WebViewController.swift @@ -79,6 +79,23 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg underlyingPreferredStatusBarStyle } + #if targetEnvironment(macCatalyst) + override var keyCommands: [UIKeyCommand]? { + [ + UIKeyCommand( + input: "c", + modifierFlags: [.shift, .command], + action: #selector(copyCurrentSelectedContent) + ), + UIKeyCommand( + input: "v", + modifierFlags: [.shift, .command], + action: #selector(pasteContent) + ), + ] + } + #endif + init(server: Server, shouldLoadImmediately: Bool = false) { self.server = server self.leftEdgePanGestureRecognizer = with(UIScreenEdgePanGestureRecognizer()) { @@ -844,15 +861,6 @@ final class WebViewController: UIViewController, WKNavigationDelegate, WKUIDeleg } } - @objc override func paste(_ sender: Any?) { - // Forward to webView if it can handle it - if webView.responds(to: #selector(paste(_:))) { - webView.perform(#selector(paste(_:)), with: sender) - } else { - super.paste(sender) - } - } - @objc private func scheduleReconnectBackgroundTimer() { precondition(Thread.isMainThread)