diff --git a/Sources/App/Resources/WebSocketBridge.js b/Sources/App/Resources/WebSocketBridge.js index 6ae4dcb20d..7f583206f5 100644 --- a/Sources/App/Resources/WebSocketBridge.js +++ b/Sources/App/Resources/WebSocketBridge.js @@ -2,7 +2,7 @@ const notifyThemeColors = () => { function doWait() { var colors = {}; - let element = document.createElement('div'); + const element = document.createElement('div'); document.body.appendChild(element); element.style.display = 'none'; @@ -48,6 +48,31 @@ const checkForMissingHassConnectionAndReload = () => { }); }; +const setOverrideZoomEnabled = (shouldZoom) => { + // we know that the HA frontend creates this meta tag, so we can be lazy + const element = document.querySelector('meta[name="viewport"]'); + if (element === null) { + return; + } + + const ignoredBits = ['user-scalable', 'minimum-scale', 'maximum-scale']; + const elements = element['content'] + .split(',') + .filter(contentItem => { + return ignoredBits.every(ignoredBit => !contentItem.includes(ignoredBit)); + }); + + if (shouldZoom) { + elements.push('user-scalable=yes'); + } else { + // setting minimum/maximum scale resets existing zoom if there is one + elements.push('user-scalable=no', 'minimum-scale=1.0', 'maximum-scale=1.0'); + } + + element['content'] = elements.join(','); + console.log(`adjusted viewport to ${element['content']}`); +}; + waitForHassConnection().then(({ conn }) => { conn.sendMessagePromise({type: 'auth/current_user'}).then((user) => { window.webkit.messageHandlers.currentUser.postMessage(user); diff --git a/Sources/App/Resources/en.lproj/Localizable.strings b/Sources/App/Resources/en.lproj/Localizable.strings index 613a6b3c79..4174f8ff26 100644 --- a/Sources/App/Resources/en.lproj/Localizable.strings +++ b/Sources/App/Resources/en.lproj/Localizable.strings @@ -374,6 +374,7 @@ Your actions and local configuration will still be available after logging in."; "settings_details.general.open_in_browser.title" = "Open Links In"; "settings_details.general.page_zoom.default" = "%@ (Default)"; "settings_details.general.page_zoom.title" = "Page Zoom"; +"settings_details.general.pinch_to_zoom.title" = "Pinch to Zoom"; "settings_details.general.restoration.title" = "Remember Last Page"; "settings_details.general.title" = "General"; "settings_details.general.visibility.options.dock" = "Dock"; diff --git a/Sources/App/Settings/SettingsDetailViewController.swift b/Sources/App/Settings/SettingsDetailViewController.swift index e1d512bc42..17d060b83d 100644 --- a/Sources/App/Settings/SettingsDetailViewController.swift +++ b/Sources/App/Settings/SettingsDetailViewController.swift @@ -191,6 +191,15 @@ class SettingsDetailViewController: FormViewController, TypedRowControllerType { } } + <<< SwitchRow { + $0.title = L10n.SettingsDetails.General.PinchToZoom.title + $0.hidden = .isCatalyst + $0.value = Current.settingsStore.pinchToZoom + $0.onChange { row in + Current.settingsStore.pinchToZoom = row.value ?? false + } + } + case "location": title = L10n.SettingsDetails.Location.title form diff --git a/Sources/App/WebView/WebViewController.swift b/Sources/App/WebView/WebViewController.swift index 2fc804c51f..297a7717f6 100644 --- a/Sources/App/WebView/WebViewController.swift +++ b/Sources/App/WebView/WebViewController.swift @@ -223,11 +223,11 @@ class WebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, U NotificationCenter.default.addObserver( self, - selector: #selector(updateWebViewSettings), + selector: #selector(updateWebViewSettingsForNotification), name: SettingsStore.webViewRelatedSettingDidChange, object: nil ) - updateWebViewSettings() + updateWebViewSettings(reason: .initial) styleUI() } @@ -384,6 +384,8 @@ class WebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, U // in case the view appears again, don't reload initialURL = nil + + updateWebViewSettings(reason: .load) } func webView( @@ -691,7 +693,19 @@ class WebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, U underlyingPreferredStatusBarStyle } - @objc private func updateWebViewSettings() { + @objc private func updateWebViewSettingsForNotification() { + updateWebViewSettings(reason: .settingChange) + } + + private enum WebViewSettingsUpdateReason { + case initial + case settingChange + case load + } + + private func updateWebViewSettings(reason: WebViewSettingsUpdateReason) { + Current.Log.info("updating web view settings for \(reason)") + // iOS 14's `pageZoom` property is almost this, but not quite - it breaks the layout as well // This is quasi-private API that has existed since pre-iOS 10, but the implementation // changed in iOS 12 to be like the +/- zoom buttons in Safari, which scale content without @@ -699,6 +713,11 @@ class WebViewController: UIViewController, WKNavigationDelegate, WKUIDelegate, U let viewScale = Current.settingsStore.pageZoom.viewScaleValue Current.Log.info("setting view scale to \(viewScale)") webView.setValue(viewScale, forKey: "viewScale") + + if !Current.isCatalyst { + let zoomValue = Current.settingsStore.pinchToZoom ? "true" : "false" + webView.evaluateJavaScript("setOverrideZoomEnabled(\(zoomValue))", completionHandler: nil) + } } } diff --git a/Sources/Shared/Resources/Swiftgen/Strings.swift b/Sources/Shared/Resources/Swiftgen/Strings.swift index 83e56fa42b..83f5172917 100644 --- a/Sources/Shared/Resources/Swiftgen/Strings.swift +++ b/Sources/Shared/Resources/Swiftgen/Strings.swift @@ -1656,6 +1656,10 @@ public enum L10n { /// Page Zoom public static var title: String { return L10n.tr("Localizable", "settings_details.general.page_zoom.title") } } + public enum PinchToZoom { + /// Pinch to Zoom + public static var title: String { return L10n.tr("Localizable", "settings_details.general.pinch_to_zoom.title") } + } public enum Restoration { /// Remember Last Page public static var title: String { return L10n.tr("Localizable", "settings_details.general.restoration.title") } diff --git a/Sources/Shared/Settings/SettingsStore.swift b/Sources/Shared/Settings/SettingsStore.swift index c0f8c469e1..263f457488 100644 --- a/Sources/Shared/Settings/SettingsStore.swift +++ b/Sources/Shared/Settings/SettingsStore.swift @@ -293,6 +293,16 @@ public class SettingsStore { } } + public var pinchToZoom: Bool { + get { + prefs.bool(forKey: "pinchToZoom") + } + set { + prefs.set(newValue, forKey: "pinchToZoom") + NotificationCenter.default.post(name: Self.webViewRelatedSettingDidChange, object: nil) + } + } + public var restoreLastURL: Bool { get { if let value = prefs.object(forKey: "restoreLastURL") as? NSNumber {