fix: code review notes
This commit is contained in:
parent
b98678b235
commit
c75ff4c1d0
|
|
@ -56,7 +56,7 @@ let package = Package(
|
|||
// MARK: - UIKit
|
||||
.target(name: "TIUIKitCore", dependencies: ["TISwiftUtils"], path: "TIUIKitCore/Sources"),
|
||||
.target(name: "TIUIElements", dependencies: ["TIUIKitCore", "TISwiftUtils"], path: "TIUIElements/Sources"),
|
||||
.target(name: "TIWebView", dependencies: ["TIUIKitCore", "TISwiftUtils", "TILogging"], path: "TIWebView/Sources"),
|
||||
.target(name: "TIWebView", dependencies: ["TIUIKitCore", "TISwiftUtils"], path: "TIWebView/Sources"),
|
||||
|
||||
// MARK: - SwiftUI
|
||||
.target(name: "TISwiftUICore", dependencies: ["TIUIKitCore", "TISwiftUtils"], path: "TISwiftUICore/Sources"),
|
||||
|
|
|
|||
|
|
@ -20,15 +20,9 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import TILogging
|
||||
|
||||
open class BaseWebViewErrorHandler {
|
||||
open class BaseWebViewErrorHandler: WebViewErrorHandler {
|
||||
|
||||
public init() {
|
||||
|
||||
}
|
||||
|
||||
open func didRecievedError(_ error: WebViewError) {
|
||||
// override in subviews
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
public enum WebViewError: Error {
|
||||
case standardError(URL?, Error)
|
||||
case jsError(URL?, String)
|
||||
public protocol WebViewError: Error {
|
||||
var contentURL: URL? { get }
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct WebViewJSError: WebViewError, Codable {
|
||||
public let contentURL: URL?
|
||||
public let name: String?
|
||||
public let message: String?
|
||||
public let stackTrace: String?
|
||||
|
||||
public init(contentURL: URL?,
|
||||
name: String?,
|
||||
message: String?,
|
||||
stackTrace: String?) {
|
||||
|
||||
self.contentURL = contentURL
|
||||
self.name = name
|
||||
self.message = message
|
||||
self.stackTrace = stackTrace
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct WebViewLoadingError: WebViewError {
|
||||
public let contentURL: URL?
|
||||
public let innerError: Error
|
||||
|
||||
public init(contentURL: URL?, innerError: Error) {
|
||||
self.contentURL = contentURL
|
||||
self.innerError = innerError
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,19 @@ public enum WebViewErrorConstants {
|
|||
"error"
|
||||
}
|
||||
|
||||
static var errorPropertyName: String {
|
||||
static var errorMessage: String {
|
||||
"message"
|
||||
}
|
||||
|
||||
static var errorName: String {
|
||||
"name"
|
||||
}
|
||||
|
||||
static var errorUrl: String {
|
||||
"url"
|
||||
}
|
||||
|
||||
static var errorStack: String {
|
||||
"stack"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
public protocol WebViewErrorHandler {
|
||||
func didRecievedError(_ error: WebViewError)
|
||||
}
|
||||
|
||||
public extension WebViewErrorHandler {
|
||||
func didRecievedError(_ error: WebViewError) {
|
||||
// override in subclasses
|
||||
}
|
||||
}
|
||||
|
|
@ -20,12 +20,9 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import enum WebKit.WKNavigationActionPolicy
|
||||
open class BaseWebViewNavigator: WebViewNavigator {
|
||||
|
||||
open class BaseWebViewNavigator {
|
||||
|
||||
public let navigationMap: [NavigationPolicy]
|
||||
public var navigationMap: [NavigationPolicy]
|
||||
|
||||
public init(navigationMap: [NavigationPolicy]) {
|
||||
self.navigationMap = navigationMap
|
||||
|
|
@ -34,13 +31,4 @@ open class BaseWebViewNavigator {
|
|||
public convenience init() {
|
||||
self.init(navigationMap: [])
|
||||
}
|
||||
|
||||
open func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy {
|
||||
guard !navigationMap.isEmpty else {
|
||||
return .cancel
|
||||
}
|
||||
|
||||
let allowPolicy = navigationMap.filter { $0.policy(for: url) == .allow }
|
||||
return allowPolicy.isEmpty ? .cancel : .allow
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@
|
|||
import Foundation
|
||||
|
||||
extension URL {
|
||||
func validate(with regex: NSRegularExpression) -> Bool {
|
||||
func matches(_ regex: NSRegularExpression) -> Bool {
|
||||
let range = NSRange(location: 0, length: absoluteString.utf16.count)
|
||||
|
||||
return regex.firstMatch(in: absoluteString, range: range) != nil
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +37,10 @@ extension URL {
|
|||
return absoluteString == path
|
||||
|
||||
case let .query(query):
|
||||
return (self.query ?? "").contains(query)
|
||||
if let urlQuery = self.query {
|
||||
return urlQuery.contains(query)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
import Foundation
|
||||
import enum WebKit.WKNavigationActionPolicy
|
||||
|
||||
open class AnyNavigationPolicy: NavigationPolicy {
|
||||
open class AlwaysAllowNavigationPolicy: NavigationPolicy {
|
||||
|
||||
public init() {
|
||||
|
||||
|
|
@ -23,7 +23,7 @@
|
|||
import Foundation
|
||||
import enum WebKit.WKNavigationActionPolicy
|
||||
|
||||
open class RegexNavigationPolicy: AnyNavigationPolicy {
|
||||
open class RegexNavigationPolicy: AlwaysAllowNavigationPolicy {
|
||||
|
||||
public var regex: NSRegularExpression
|
||||
|
||||
|
|
@ -46,6 +46,6 @@ open class RegexNavigationPolicy: AnyNavigationPolicy {
|
|||
// MARK: - NavigationPolicy
|
||||
|
||||
open override func policy(for url: URL) -> WKNavigationActionPolicy {
|
||||
url.validate(with: regex) ? .allow : .cancel
|
||||
url.matches(regex) ? .allow : .cancel
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import Foundation
|
|||
import enum WebKit.WKNavigationActionPolicy
|
||||
|
||||
/// Compares URL with combination of URL components.
|
||||
open class URLComponentsNavigationPolicy: AnyNavigationPolicy {
|
||||
open class URLComponentsNavigationPolicy: AlwaysAllowNavigationPolicy {
|
||||
|
||||
public var components: [URLComponent]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import enum WebKit.WKNavigationActionPolicy
|
||||
|
||||
public protocol WebViewNavigator {
|
||||
var navigationMap: [NavigationPolicy] { get set }
|
||||
|
||||
func shouldNavigate(to url: URL) -> WKNavigationActionPolicy
|
||||
}
|
||||
|
||||
public extension WebViewNavigator {
|
||||
func shouldNavigate(to url: URL) -> WKNavigationActionPolicy {
|
||||
guard !navigationMap.isEmpty else {
|
||||
return .cancel
|
||||
}
|
||||
|
||||
let allowPolicy = navigationMap.filter { $0.policy(for: url) == .allow }
|
||||
return allowPolicy.isEmpty ? .cancel : .allow
|
||||
}
|
||||
}
|
||||
|
|
@ -36,16 +36,16 @@ open class BaseWebViewStateHandler: NSObject, WebViewStateHandler {
|
|||
return decisionHandler(.cancel)
|
||||
}
|
||||
|
||||
let decision = viewModel?.shouldNavigate(toUrl: url) ?? .cancel
|
||||
let decision = viewModel?.shouldNavigate(to: url) ?? .cancel
|
||||
decisionHandler(decision)
|
||||
}
|
||||
|
||||
open func webView(_ webView: WKWebView, didCommit navigation: WKNavigation?) {
|
||||
// override in subviews
|
||||
// override in subclasses
|
||||
}
|
||||
|
||||
open func webView(_ webView: WKWebView, didFinish navigation: WKNavigation?) {
|
||||
viewModel?.makeUrlInjection(forWebView: webView)
|
||||
viewModel?.makeUrlInjection(into: webView)
|
||||
}
|
||||
|
||||
open func webView(_ webView: WKWebView,
|
||||
|
|
|
|||
|
|
@ -23,9 +23,7 @@
|
|||
import Foundation
|
||||
import class WebKit.WKWebView
|
||||
|
||||
open class BaseWebViewUrlInjector {
|
||||
|
||||
public typealias URLInjection = [WebViewUrlComparator: [WebViewUrlInjection]]
|
||||
open class BaseWebViewUrlInjector: WebViewUrlInjector {
|
||||
|
||||
public var injection: URLInjection
|
||||
|
||||
|
|
@ -36,57 +34,4 @@ open class BaseWebViewUrlInjector {
|
|||
public convenience init() {
|
||||
self.init(injection: [:])
|
||||
}
|
||||
|
||||
// MARK: - Open methods
|
||||
|
||||
open func inject(on webView: WKWebView) {
|
||||
guard !injection.isEmpty, let url = webView.url else {
|
||||
return
|
||||
}
|
||||
|
||||
injection.forEach { (comparator, injections) in
|
||||
guard url.compare(by: comparator) else {
|
||||
return
|
||||
}
|
||||
|
||||
injections.forEach { evaluteInjection(onWebView: webView, injection: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Private methods
|
||||
|
||||
private func evaluteInjection(onWebView webView: WKWebView, injection: WebViewUrlInjection) {
|
||||
let jsScript = makeJsScript(fromInjection: injection)
|
||||
|
||||
guard !jsScript.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
webView.evaluateJavaScript(jsScript, completionHandler: nil)
|
||||
}
|
||||
|
||||
private func makeJsScript(fromInjection injection: WebViewUrlInjection) -> String {
|
||||
switch injection {
|
||||
case let .css(css):
|
||||
return cssJsScript(css: css)
|
||||
|
||||
case let .cssForFile(url):
|
||||
let css = try? String(contentsOf: url)
|
||||
.components(separatedBy: .newlines)
|
||||
.joined()
|
||||
|
||||
return cssJsScript(css: css ?? "")
|
||||
|
||||
case let .javaScript(script):
|
||||
return script
|
||||
}
|
||||
}
|
||||
|
||||
private func cssJsScript(css: String) -> String {
|
||||
"""
|
||||
var style = document.createElement('style');
|
||||
style.innerHTML = '\(css)';
|
||||
document.head.appendChild(style);
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,11 +37,8 @@ public extension URL {
|
|||
case let .query(query):
|
||||
return compare(by: .query(query))
|
||||
|
||||
case let .regex(stringRegex):
|
||||
guard let regex = try? NSRegularExpression(pattern: stringRegex) else {
|
||||
return false
|
||||
}
|
||||
return validate(with: regex)
|
||||
case let .regex(nsRegex):
|
||||
return matches(nsRegex)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public enum WebViewUrlComparator: Hashable {
|
||||
case any
|
||||
case absolutePath(String)
|
||||
case host(String)
|
||||
case query(String)
|
||||
case regex(String)
|
||||
case regex(NSRegularExpression)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,86 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import class WebKit.WKWebView
|
||||
|
||||
public typealias URLInjection = [WebViewUrlComparator: [WebViewUrlInjection]]
|
||||
|
||||
public protocol WebViewUrlInjector {
|
||||
var injection: URLInjection { get set }
|
||||
|
||||
func inject(into webView: WKWebView)
|
||||
}
|
||||
|
||||
public extension WebViewUrlInjector {
|
||||
|
||||
func inject(into webView: WKWebView) {
|
||||
guard !injection.isEmpty, let url = webView.url else {
|
||||
return
|
||||
}
|
||||
|
||||
injection.forEach { (comparator, injections) in
|
||||
guard url.compare(by: comparator) else {
|
||||
return
|
||||
}
|
||||
|
||||
injections.forEach { evaluteInjection(onWebView: webView, injection: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Helper methods
|
||||
|
||||
private func evaluteInjection(onWebView webView: WKWebView, injection: WebViewUrlInjection) {
|
||||
let jsScript = makeJsScript(fromInjection: injection)
|
||||
|
||||
guard !jsScript.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
webView.evaluateJavaScript(jsScript, completionHandler: nil)
|
||||
}
|
||||
|
||||
private func makeJsScript(fromInjection injection: WebViewUrlInjection) -> String {
|
||||
switch injection {
|
||||
case let .css(css):
|
||||
return cssJsScript(css: css)
|
||||
|
||||
case let .cssForFile(url):
|
||||
let css = try? String(contentsOf: url)
|
||||
.components(separatedBy: .newlines)
|
||||
.joined()
|
||||
|
||||
return cssJsScript(css: css ?? "")
|
||||
|
||||
case let .javaScript(script):
|
||||
return script
|
||||
}
|
||||
}
|
||||
|
||||
private func cssJsScript(css: String) -> String {
|
||||
"""
|
||||
var style = document.createElement('style');
|
||||
style.innerHTML = '\(css)';
|
||||
document.head.appendChild(style);
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
|
@ -24,15 +24,15 @@ import WebKit
|
|||
|
||||
open class DefaultWebViewModel: NSObject, WebViewModel {
|
||||
|
||||
public var injector: BaseWebViewUrlInjector
|
||||
public var navigator: BaseWebViewNavigator
|
||||
public var errorHandler: BaseWebViewErrorHandler
|
||||
public var injector: WebViewUrlInjector
|
||||
public var navigator: WebViewNavigator
|
||||
public var errorHandler: WebViewErrorHandler
|
||||
|
||||
// MARK: - Init
|
||||
|
||||
public init(injector: BaseWebViewUrlInjector = .init(),
|
||||
navigator: BaseWebViewNavigator = .init(),
|
||||
errorHandler: BaseWebViewErrorHandler = .init()) {
|
||||
public init(injector: WebViewUrlInjector = BaseWebViewUrlInjector(),
|
||||
navigator: WebViewNavigator = BaseWebViewNavigator(),
|
||||
errorHandler: WebViewErrorHandler = BaseWebViewErrorHandler()) {
|
||||
|
||||
self.injector = injector
|
||||
self.navigator = navigator
|
||||
|
|
@ -56,7 +56,9 @@ open class DefaultWebViewModel: NSObject, WebViewModel {
|
|||
|
||||
private func parseError(_ message: WKScriptMessage) -> WebViewError {
|
||||
let body = message.body as? [String: Any]
|
||||
let error = body?[WebViewErrorConstants.errorPropertyName] as? String
|
||||
return .jsError(message.webView?.url, error ?? "")
|
||||
return WebViewJSError(contentURL: body?[WebViewErrorConstants.errorUrl] as? URL,
|
||||
name: body?[WebViewErrorConstants.errorName] as? String,
|
||||
message: body?[WebViewErrorConstants.errorMessage] as? String,
|
||||
stackTrace: body?[WebViewErrorConstants.errorStack] as? String)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,26 +23,27 @@
|
|||
import WebKit
|
||||
|
||||
public protocol WebViewModel: WKScriptMessageHandler {
|
||||
var injector: BaseWebViewUrlInjector { get }
|
||||
var navigator: BaseWebViewNavigator { get }
|
||||
var errorHandler: BaseWebViewErrorHandler { get }
|
||||
var injector: WebViewUrlInjector { get }
|
||||
var navigator: WebViewNavigator { get }
|
||||
var errorHandler: WebViewErrorHandler { get }
|
||||
|
||||
func makeUrlInjection(forWebView webView: WKWebView)
|
||||
func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy
|
||||
func makeUrlInjection(into webView: WKWebView)
|
||||
func shouldNavigate(to url: URL) -> WKNavigationActionPolicy
|
||||
func handleError(_ error: Error, url: URL?)
|
||||
}
|
||||
|
||||
public extension WebViewModel {
|
||||
|
||||
func makeUrlInjection(forWebView webView: WKWebView) {
|
||||
injector.inject(on: webView)
|
||||
func makeUrlInjection(into webView: WKWebView) {
|
||||
injector.inject(into: webView)
|
||||
}
|
||||
|
||||
func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy {
|
||||
navigator.shouldNavigate(toUrl: url)
|
||||
func shouldNavigate(to url: URL) -> WKNavigationActionPolicy {
|
||||
navigator.shouldNavigate(to: url)
|
||||
}
|
||||
|
||||
func handleError(_ error: Error, url: URL?) {
|
||||
errorHandler.didRecievedError(.standardError(url, error))
|
||||
let errorModel = WebViewLoadingError(contentURL: url, innerError: error)
|
||||
errorHandler.didRecievedError(errorModel)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue