fix: code review notes

This commit is contained in:
Nikita Semenov 2022-12-27 00:36:31 +03:00
parent 7add7c46ab
commit 9d3bbc9c71
18 changed files with 130 additions and 193 deletions

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -22,9 +22,9 @@
import TILogging
open class BaseWebViewErrorHandler: WebViewErrorHandlerProtocol {
open class BaseWebViewErrorHandler {
let logger: TILogger?
public var logger: TILogger?
public init(logger: TILogger? = nil) {
self.logger = logger

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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

View File

@ -1,25 +0,0 @@
//
// Copyright (c) 2020 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 WebViewErrorHandlerProtocol {
func didRecievedError(_ error: WebViewErrorModel)
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -23,7 +23,7 @@
import Foundation
import enum WebKit.WKNavigationActionPolicy
open class BaseWebViewNavigator: WebViewNavigatorProtocol {
open class BaseWebViewNavigator {
public typealias WebViewNavigationMap = [WebViewUrlComparator: NavigationResult]

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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

View File

@ -1,49 +0,0 @@
//
// Copyright (c) 2020 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 WebKit
public protocol WebViewNavigationDelegate {
func navigationProgress(_ progress: Double, isLoading: Bool)
func didCommit(_ navigation: WKNavigation, forWebView webView: WKWebView)
func didFinish(_ navigation: WKNavigation!, forWebView webView: WKWebView)
func didFailProvisionalNavigation(_ navigation: WKNavigation!, withError error: Error, forWebView webView: WKWebView)
func didFail(_ navigation: WKNavigation!, withError error: Error, forWebView webView: WKWebView)
}
public extension WebViewNavigationDelegate {
func navigationProgress(_ progress: Double, isLoading: Bool) {
// empty implementation
}
func didCommit(_ navigation: WKNavigation, forWebView webView: WKWebView) {
// empty implementation
}
func didFinish(_ navigation: WKNavigation!, forWebView webView: WKWebView) {
// empty implementation
}
func didFail(_ navigation: WKNavigation!, withError error: Error, forWebView webView: WKWebView) {
// empty implementation
}
}

View File

@ -0,0 +1,68 @@
//
// 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 WebKit
open class BaseWebViewStateHandler: NSObject, WebViewStateHandler {
public weak var viewModel: WebViewModelProtocol?
// MARK: - WebViewStateHandler
open func navigationProgress(_ progress: Double, isLoading: Bool) {
// Override in subclass
}
// MARK: - WKNavigationDelegate
open func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
return decisionHandler(.cancel)
}
let decision = viewModel?.shouldNavigate(toUrl: url) ?? .cancel
decisionHandler(decision)
}
open func webView(_ webView: WKWebView, didCommit navigation: WKNavigation?) {
}
open func webView(_ webView: WKWebView, didFinish navigation: WKNavigation?) {
viewModel?.makeUrlInjection(forWebView: webView)
}
open func webView(_ webView: WKWebView,
didFailProvisionalNavigation navigation: WKNavigation?,
withError error: Error) {
viewModel?.handleError(error, url: webView.url)
}
open func webView(_ webView: WKWebView,
didFail navigation: WKNavigation?,
withError error: Error) {
viewModel?.handleError(error, url: webView.url)
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -20,9 +20,10 @@
// THE SOFTWARE.
//
import Foundation
import enum WebKit.WKNavigationActionPolicy
import protocol WebKit.WKNavigationDelegate
public protocol WebViewNavigatorProtocol {
func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy
public protocol WebViewStateHandler: WKNavigationDelegate {
var viewModel: WebViewModelProtocol? { get set }
func navigationProgress(_ progress: Double, isLoading: Bool)
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -23,7 +23,7 @@
import Foundation
import class WebKit.WKWebView
open class BaseWebViewUrlInjector: WebViewUrlInjectorProtocol {
open class BaseWebViewUrlInjector {
public typealias URLInjection = [WebViewUrlComparator: [WebViewUrlInjection]]
@ -37,7 +37,9 @@ open class BaseWebViewUrlInjector: WebViewUrlInjectorProtocol {
self.init(injection: [:])
}
open func inject(onWebView webView: WKWebView) {
// MARK: - Open methods
open func inject(on webView: WKWebView) {
guard !injection.isEmpty, let url = webView.url else {
return
}
@ -51,6 +53,8 @@ open class BaseWebViewUrlInjector: WebViewUrlInjectorProtocol {
}
}
// MARK: - Private methods
private func evaluteInjection(onWebView webView: WKWebView, injection: WebViewUrlInjection) {
let jsScript = makeJsScript(fromInjection: injection)
@ -66,12 +70,8 @@ open class BaseWebViewUrlInjector: WebViewUrlInjectorProtocol {
case let .css(css):
return cssJsScript(css: css)
case let .cssForFile(file):
guard let path = Bundle.main.path(forResource: file, ofType: "css") else {
return ""
}
let css = try? String(contentsOfFile: path)
case let .cssForFile(url):
let css = try? String(contentsOf: url)
.components(separatedBy: .newlines)
.joined()

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -20,8 +20,10 @@
// THE SOFTWARE.
//
import Foundation
public enum WebViewUrlInjection {
case css(String)
case cssForFile(String)
case cssForFile(URL)
case javaScript(String)
}

View File

@ -1,27 +0,0 @@
//
// Copyright (c) 2020 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 class WebKit.WKWebView
public protocol WebViewUrlInjectorProtocol {
func inject(onWebView webView: WKWebView)
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -25,17 +25,25 @@ import WebKit
open class BaseInitializableWebView: WKWebView,
InitializableViewProtocol,
ConfigurableView,
WKNavigationDelegate {
ConfigurableView {
public var viewModel: WebViewModelProtocol?
public var delegate: WebViewNavigationDelegate?
public var viewModel: WebViewModelProtocol? {
didSet {
stateHandler?.viewModel = viewModel
}
}
public var stateHandler: WebViewStateHandler? {
didSet {
navigationDelegate = stateHandler
}
}
// MARK: - Init
public init() {
public init(stateHandler: WebViewStateHandler? = BaseWebViewStateHandler()) {
super.init(frame: .zero, configuration: .init())
self.stateHandler = stateHandler
initializeView()
}
@ -55,9 +63,6 @@ open class BaseInitializableWebView: WKWebView,
}
public func bindViews() {
navigationDelegate = self
configuration.preferences.javaScriptEnabled = true
addObserver(self,
forKeyPath: #keyPath(WKWebView.estimatedProgress),
options: .new,
@ -80,7 +85,7 @@ open class BaseInitializableWebView: WKWebView,
context: UnsafeMutableRawPointer?) {
if keyPath == #keyPath(WKWebView.estimatedProgress) {
delegate?.navigationProgress(estimatedProgress, isLoading: isLoading)
stateHandler?.navigationProgress(estimatedProgress, isLoading: isLoading)
}
}
@ -91,42 +96,4 @@ open class BaseInitializableWebView: WKWebView,
configuration.userContentController.add(viewModel, name: WebViewErrorConstants.errorMessageName)
}
// MARK: - WKNavigationDelegate
open func webView(_ webView: WKWebView,
decidePolicyFor navigationAction: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = navigationAction.request.url else {
return decisionHandler(.cancel)
}
let decision = viewModel?.shouldNavigate(toUrl: url) ?? .cancel
decisionHandler(decision)
}
open func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!) {
delegate?.didCommit(navigation, forWebView: webView)
}
open func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
delegate?.didFinish(navigation, forWebView: webView)
viewModel?.makeUrlInjection(forWebView: webView)
}
open func webView(_ webView: WKWebView,
didFailProvisionalNavigation navigation: WKNavigation!,
withError error: Error) {
viewModel?.handleError(error, url: webView.url)
delegate?.didFailProvisionalNavigation(navigation, withError: error, forWebView: webView)
}
open func webView(_ webView: WKWebView,
didFail navigation: WKNavigation!,
withError error: Error) {
viewModel?.handleError(error, url: webView.url)
delegate?.didFail(navigation, withError: error, forWebView: webView)
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -24,15 +24,15 @@ import WebKit
open class BaseWebViewModel: NSObject, WebViewModelProtocol {
public var injector: WebViewUrlInjectorProtocol
public var navigator: WebViewNavigatorProtocol
public var errorHandler: WebViewErrorHandlerProtocol
public var injector: BaseWebViewUrlInjector
public var navigator: BaseWebViewNavigator
public var errorHandler: BaseWebViewErrorHandler
// MARK: - Init
public init(injector: WebViewUrlInjectorProtocol = BaseWebViewUrlInjector(),
navigator: WebViewNavigatorProtocol = BaseWebViewNavigator(),
errorHandler: WebViewErrorHandlerProtocol = BaseWebViewErrorHandler()) {
public init(injector: BaseWebViewUrlInjector = .init(),
navigator: BaseWebViewNavigator = .init(),
errorHandler: BaseWebViewErrorHandler = .init()) {
self.injector = injector
self.navigator = navigator
@ -44,7 +44,7 @@ open class BaseWebViewModel: NSObject, WebViewModelProtocol {
// MARK: - Open methods
open func makeUrlInjection(forWebView webView: WKWebView) {
injector.inject(onWebView: webView)
injector.inject(on: webView)
}
open func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy {
@ -60,18 +60,17 @@ open class BaseWebViewModel: NSObject, WebViewModelProtocol {
open func userContentController(_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage) {
if message.name == WebViewErrorConstants.errorMessageName,
let error = parseError(message){
let url = message.webView?.url
errorHandler.didRecievedError(.init(url: url, jsErrorMessage: error))
if message.name == WebViewErrorConstants.errorMessageName {
let error = parseError(message)
errorHandler.didRecievedError(error)
}
}
// MARK: - Private methods
private func parseError(_ message: WKScriptMessage) -> String? {
private func parseError(_ message: WKScriptMessage) -> WebViewErrorModel {
let body = message.body as? [String: Any]
let error = body?[WebViewErrorConstants.errorPropertyName] as? String
return error
return .init(jsErrorMessage: error)
}
}

View File

@ -1,5 +1,5 @@
//
// Copyright (c) 2020 Touch Instinct
// 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
@ -23,8 +23,9 @@
import WebKit
public protocol WebViewModelProtocol: WKScriptMessageHandler {
var injector: WebViewUrlInjectorProtocol { get }
var navigator: WebViewNavigatorProtocol { get }
var injector: BaseWebViewUrlInjector { get }
var navigator: BaseWebViewNavigator { get }
var errorHandler: BaseWebViewErrorHandler { get }
func makeUrlInjection(forWebView webView: WKWebView)
func shouldNavigate(toUrl url: URL) -> WKNavigationActionPolicy

View File

@ -8,7 +8,7 @@ Pod::Spec.new do |s|
'castlele' => 'nikita.semenov@touchin.ru' }
s.source = { :git => 'https://github.com/TouchInstinct/LeadKit.git', :tag => s.version.to_s }
s.ios.deployment_target = '13.0'
s.ios.deployment_target = '11.0'
s.swift_versions = ['5.3']
s.source_files = s.name + '/Sources/**/*'