fix onCreateContextMenu and onHideContextMenu events for iOS 16.0+

This commit is contained in:
Lorenzo Pichilli 2023-05-15 19:30:25 +02:00 committed by GitHub
parent 47427044c8
commit 57106e8dc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 86 additions and 50 deletions

View File

@ -224,6 +224,11 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
if !self.responds(to: Selector(targetMethodName)) { if !self.responds(to: Selector(targetMethodName)) {
let customAction: () -> Void = { let customAction: () -> Void = {
self.channelDelegate?.onContextMenuActionItemClicked(id: id, title: title) self.channelDelegate?.onContextMenuActionItemClicked(id: id, title: title)
if #available(iOS 16.0, *) {
if #unavailable(iOS 16.4) {
self.onHideContextMenu()
}
}
} }
let castedCustomAction: AnyObject = unsafeBitCast(customAction as @convention(block) () -> Void, to: AnyObject.self) let castedCustomAction: AnyObject = unsafeBitCast(customAction as @convention(block) () -> Void, to: AnyObject.self)
let swizzledImplementation = imp_implementationWithBlock(castedCustomAction) let swizzledImplementation = imp_implementationWithBlock(castedCustomAction)
@ -239,8 +244,6 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
return super.hitTest(point, with: event) return super.hitTest(point, with: event)
} }
@available(iOS 13.0, *) @available(iOS 13.0, *)
public override func buildMenu(with builder: UIMenuBuilder) { public override func buildMenu(with builder: UIMenuBuilder) {
if #available(iOS 16.0, *) { if #available(iOS 16.0, *) {
@ -248,43 +251,71 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
let contextMenuSettings = ContextMenuSettings() let contextMenuSettings = ContextMenuSettings()
if let contextMenuSettingsMap = menu["settings"] as? [String: Any?] { if let contextMenuSettingsMap = menu["settings"] as? [String: Any?] {
let _ = contextMenuSettings.parse(settings: contextMenuSettingsMap) let _ = contextMenuSettings.parse(settings: contextMenuSettingsMap)
if contextMenuSettings.hideDefaultSystemContextMenuItems { if contextMenuSettings.hideDefaultSystemContextMenuItems {
builder.remove(menu: .lookup) builder.remove(menu: .lookup)
} }
} }
} }
if #unavailable(iOS 16.4), settings?.disableContextMenu == false {
contextMenuIsShowing = false
DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
self.onCreateContextMenu()
}
}
} }
super.buildMenu(with: builder) super.buildMenu(with: builder)
} }
@available(iOS 16.4, *)
public func webView(_ webView: WKWebView, willPresentEditMenuWithAnimator animator: UIEditMenuInteractionAnimating) {
onCreateContextMenu()
}
@available(iOS 16.4, *)
public func webView(_ webView: WKWebView, willDismissEditMenuWithAnimator animator: UIEditMenuInteractionAnimating) {
onHideContextMenu()
}
public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { public override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if self.settings?.disableContextMenu == true { var needCheck = sender is UIMenuController
if !onCreateContextMenuEventTriggeredWhenMenuDisabled { if #available(iOS 13.0, *) {
// workaround to trigger onCreateContextMenu event as the same on Android needCheck = sender is UIMenuElement || sender is UIMenuController
self.onCreateContextMenu()
onCreateContextMenuEventTriggeredWhenMenuDisabled = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onCreateContextMenuEventTriggeredWhenMenuDisabled = false
}
}
return false
} }
if let menu = contextMenu { if needCheck {
let contextMenuSettings = ContextMenuSettings() if settings?.disableContextMenu == true {
if let contextMenuSettingsMap = menu["settings"] as? [String: Any?] { if !onCreateContextMenuEventTriggeredWhenMenuDisabled {
let _ = contextMenuSettings.parse(settings: contextMenuSettingsMap) // workaround to trigger onCreateContextMenu event as the same on Android
if !action.description.starts(with: "onContextMenuActionItemClicked-") && contextMenuSettings.hideDefaultSystemContextMenuItems { onCreateContextMenu()
return false onCreateContextMenuEventTriggeredWhenMenuDisabled = true
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.onCreateContextMenuEventTriggeredWhenMenuDisabled = false
}
}
return false
}
if let menu = contextMenu {
let contextMenuSettings = ContextMenuSettings()
if let contextMenuSettingsMap = menu["settings"] as? [String: Any?] {
let _ = contextMenuSettings.parse(settings: contextMenuSettingsMap)
if !action.description.starts(with: "onContextMenuActionItemClicked-") && contextMenuSettings.hideDefaultSystemContextMenuItems {
return false
}
}
}
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
let id = action.description.compactMap({ $0.asciiValue?.description }).joined()
channelDelegate?.onContextMenuActionItemClicked(id: id, title: action.description)
if #available(iOS 16.0, *) {
if #unavailable(iOS 16.4) {
onHideContextMenu()
}
} }
} }
} }
if contextMenuIsShowing, !action.description.starts(with: "onContextMenuActionItemClicked-") {
let id = action.description.compactMap({ $0.asciiValue?.description }).joined()
self.channelDelegate?.onContextMenuActionItemClicked(id: id, title: action.description)
}
return super.canPerformAction(action, withSender: sender) return super.canPerformAction(action, withSender: sender)
} }
@ -336,17 +367,19 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
context: nil) context: nil)
} }
NotificationCenter.default.addObserver( if #unavailable(iOS 16.0) {
self, NotificationCenter.default.addObserver(
selector: #selector(onCreateContextMenu), self,
name: UIMenuController.willShowMenuNotification, selector: #selector(onCreateContextMenu),
object: nil) name: UIMenuController.willShowMenuNotification,
object: nil)
NotificationCenter.default.addObserver(
self, NotificationCenter.default.addObserver(
selector: #selector(onHideContextMenu), self,
name: UIMenuController.didHideMenuNotification, selector: #selector(onHideContextMenu),
object: nil) name: UIMenuController.didHideMenuNotification,
object: nil)
}
// TODO: Still not working on iOS 16.0! // TODO: Still not working on iOS 16.0!
// if #available(iOS 16.0, *) { // if #available(iOS 16.0, *) {
@ -443,8 +476,9 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
isFindInteractionEnabled = settings.isFindInteractionEnabled isFindInteractionEnabled = settings.isFindInteractionEnabled
} }
// debugging is always enabled for iOS, if #available(iOS 16.4, *) {
// there isn't any option to set about it such as on Android. isInspectable = settings.isInspectable
}
if settings.clearCache { if settings.clearCache {
clearCache() clearCache()
@ -480,14 +514,16 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
configuration.defaultWebpagePreferences.allowsContentJavaScript = settings.javaScriptEnabled configuration.defaultWebpagePreferences.allowsContentJavaScript = settings.javaScriptEnabled
} }
if #available(iOS 14.5, *) { if #available(iOS 15.0, *) {
configuration.preferences.isTextInteractionEnabled = settings.isTextInteractionEnabled configuration.preferences.isTextInteractionEnabled = settings.isTextInteractionEnabled
} }
if #available(iOS 15.4, *) { if #available(iOS 15.4, *) {
configuration.preferences.isSiteSpecificQuirksModeEnabled = settings.isSiteSpecificQuirksModeEnabled configuration.preferences.isSiteSpecificQuirksModeEnabled = settings.isSiteSpecificQuirksModeEnabled
configuration.preferences.isElementFullscreenEnabled = settings.isElementFullscreenEnabled configuration.preferences.isElementFullscreenEnabled = settings.isElementFullscreenEnabled
} }
if #available(iOS 16.4, *) {
configuration.preferences.shouldPrintBackgrounds = settings.shouldPrintBackgrounds
}
} }
} }
@ -628,11 +664,7 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
contextMenuIsShowing = true contextMenuIsShowing = true
let hitTestResult = HitTestResult(type: .unknownType, extra: nil) let hitTestResult = HitTestResult(type: .unknownType, extra: nil)
if let lastLongPressTouhLocation = lastLongPressTouchPoint { if let lastLongPressTouhLocation = lastLongPressTouchPoint {
if configuration.preferences.javaScriptEnabled { if configuration.preferences.javaScriptEnabled {
self.evaluateJavaScript("window.\(JAVASCRIPT_BRIDGE_NAME)._findElementsAtPoint(\(lastLongPressTouhLocation.x),\(lastLongPressTouhLocation.y))", completionHandler: {(value, error) in self.evaluateJavaScript("window.\(JAVASCRIPT_BRIDGE_NAME)._findElementsAtPoint(\(lastLongPressTouhLocation.x),\(lastLongPressTouhLocation.y))", completionHandler: {(value, error) in
@ -1207,16 +1239,13 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
} }
} }
if #available(iOS 14.5, *) { if #available(iOS 15.0, *) {
if newSettingsMap["upgradeKnownHostsToHTTPS"] != nil && settings?.upgradeKnownHostsToHTTPS != newSettings.upgradeKnownHostsToHTTPS { if newSettingsMap["upgradeKnownHostsToHTTPS"] != nil && settings?.upgradeKnownHostsToHTTPS != newSettings.upgradeKnownHostsToHTTPS {
configuration.upgradeKnownHostsToHTTPS = newSettings.upgradeKnownHostsToHTTPS configuration.upgradeKnownHostsToHTTPS = newSettings.upgradeKnownHostsToHTTPS
} }
if newSettingsMap["isTextInteractionEnabled"] != nil && settings?.isTextInteractionEnabled != newSettings.isTextInteractionEnabled { if newSettingsMap["isTextInteractionEnabled"] != nil && settings?.isTextInteractionEnabled != newSettings.isTextInteractionEnabled {
configuration.preferences.isTextInteractionEnabled = newSettings.isTextInteractionEnabled configuration.preferences.isTextInteractionEnabled = newSettings.isTextInteractionEnabled
} }
}
if #available(iOS 15.0, *) {
if newSettingsMap["underPageBackgroundColor"] != nil, settings?.underPageBackgroundColor != newSettings.underPageBackgroundColor, if newSettingsMap["underPageBackgroundColor"] != nil, settings?.underPageBackgroundColor != newSettings.underPageBackgroundColor,
let underPageBackgroundColor = newSettings.underPageBackgroundColor, !underPageBackgroundColor.isEmpty { let underPageBackgroundColor = newSettings.underPageBackgroundColor, !underPageBackgroundColor.isEmpty {
self.underPageBackgroundColor = UIColor(hexString: underPageBackgroundColor) self.underPageBackgroundColor = UIColor(hexString: underPageBackgroundColor)
@ -1234,12 +1263,19 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate,
setMinimumViewportInset(minViewportInset, maximumViewportInset: maxViewportInset) setMinimumViewportInset(minViewportInset, maximumViewportInset: maxViewportInset)
} }
} }
if #available(iOS 16.0, *) { if #available(iOS 16.0, *) {
if newSettingsMap["isFindInteractionEnabled"] != nil, settings?.isFindInteractionEnabled != newSettings.isFindInteractionEnabled { if newSettingsMap["isFindInteractionEnabled"] != nil, settings?.isFindInteractionEnabled != newSettings.isFindInteractionEnabled {
isFindInteractionEnabled = newSettings.isFindInteractionEnabled isFindInteractionEnabled = newSettings.isFindInteractionEnabled
} }
} }
if #available(iOS 16.4, *) {
if newSettingsMap["isInspectable"] != nil, settings?.isInspectable != newSettings.isInspectable {
isInspectable = newSettings.isInspectable
}
if newSettingsMap["shouldPrintBackgrounds"] != nil, settings?.shouldPrintBackgrounds != newSettings.shouldPrintBackgrounds {
configuration.preferences.shouldPrintBackgrounds = newSettings.shouldPrintBackgrounds
}
}
scrollView.isScrollEnabled = !(newSettings.disableVerticalScroll && newSettings.disableHorizontalScroll) scrollView.isScrollEnabled = !(newSettings.disableVerticalScroll && newSettings.disableHorizontalScroll)