-
Notifications
You must be signed in to change notification settings - Fork 8
Feature/deeplink api #338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Feature/deeplink api #338
Changes from 5 commits
a7e44a3
aff5485
f885183
3d5aa7a
caeded9
63777fe
407995d
7765c01
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| // | ||
| // Copyright (c) 2023 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 UIKit | ||
|
|
||
| open class BaseNavigationStackDeeplinkHandler: DeeplinkHandler { | ||
|
|
||
| // MARK: - DeeplinkHandler | ||
|
|
||
| open func canHandle(deeplink: DeeplinkType) -> Bool { | ||
| findHandler(for: deeplink) != nil | ||
| } | ||
|
|
||
| open func handle(deeplink: DeeplinkType) -> Operation? { | ||
| let handler = findHandler(for: deeplink) | ||
| return handler?.handle(deeplink: deeplink) | ||
| } | ||
|
|
||
| // MARK: - Open methods | ||
|
|
||
| open func findHandler(for deeplink: DeeplinkType) -> DeeplinkHandler? { | ||
| guard let rootController = UIApplication.shared.keyWindow?.rootViewController else { | ||
| return nil | ||
| } | ||
|
|
||
| return rootController.findHandler(for: deeplink) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // | ||
| // Copyright (c) 2023 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 protocol DeeplinkHandler { | ||
| func canHandle(deeplink: DeeplinkType) -> Bool | ||
| func handle(deeplink: DeeplinkType) -> Operation? | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. я думаю, что нам хватит второго метода т.к. он возвращает optional |
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| // | ||
| // Copyright (c) 2023 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 UIKit | ||
|
|
||
| public typealias DeeplinkHandlerViewController = DeeplinkHandler & UIViewController | ||
|
|
||
| public extension UIViewController { | ||
|
|
||
| func findHandler(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? { | ||
| if let deeplinksHandler = self as? DeeplinkHandlerViewController, | ||
| deeplinksHandler.canHandle(deeplink: deeplink) { | ||
| return deeplinksHandler | ||
| } | ||
|
|
||
| if let deeplinksHandler = presentedViewController?.findHandler(for: deeplink) { | ||
| return deeplinksHandler | ||
| } | ||
|
|
||
| return findHandlerInViewHierarchy(for: deeplink) | ||
| } | ||
|
|
||
| private func findHandlerInViewHierarchy(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? { | ||
| switch self { | ||
| case let navController as UINavigationController: | ||
| return navController.viewControllers.reversed().findHadler(for: deeplink) | ||
|
|
||
| case let tabController as UITabBarController: | ||
| if let deeplinksHandler = tabController.selectedViewController?.findHandler(for: deeplink) { | ||
| return deeplinksHandler | ||
| } else if var tabControllers = tabController.viewControllers { | ||
| if tabController.selectedIndex != NSNotFound { | ||
| tabControllers.remove(at: tabController.selectedIndex) | ||
| } | ||
|
|
||
| if let deeplinksHandler = tabControllers.findHadler(for: deeplink) { | ||
| return deeplinksHandler | ||
| } | ||
| } | ||
|
|
||
| default: | ||
| return nil | ||
| } | ||
|
|
||
| return nil | ||
|
petropavel13 marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
| private extension Sequence where Element: UIViewController { | ||
| func findHadler(for deeplink: DeeplinkType) -> DeeplinkHandlerViewController? { | ||
| for controller in self { | ||
| if let deeplinksHandler = controller.findHandler(for: deeplink) { | ||
| return deeplinksHandler | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // | ||
| // Copyright (c) 2023 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 protocol DeeplinkMapper { | ||
| func map(url: URL) -> DeeplinkType? | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| // | ||
| // Copyright (c) 2023 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 DeeplinkType { | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. а можем обойтись associatedType или generic вместо пустого протокола? |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| // | ||
| // Copyright (c) 2023 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 TIFoundationUtils | ||
|
|
||
| public final class TIDeeplinksService { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. сервис надо создавать самостоятельно с generic аргументом deeplink type |
||
|
|
||
| public static let shared = TIDeeplinksService() | ||
|
|
||
| // MARK: - Private properties | ||
|
|
||
| private let operationQueue = OperationQueue.main | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. параметром в init |
||
|
|
||
| private var pendingDeeplink: DeeplinkType? | ||
|
|
||
| private(set) var isProcessingDeeplink = false | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. уже есть реализация актуальней |
||
|
|
||
| // MARK: - Public properties | ||
|
|
||
| public var deeplinkMapper: DeeplinkMapper? | ||
| public var deeplinkHandler: DeeplinkHandler? | ||
|
|
||
| // MARK: - Init | ||
|
|
||
| private init() { | ||
|
|
||
| } | ||
|
|
||
| // MARK: - Public methods | ||
|
|
||
| public func configure(mapper: DeeplinkMapper, handler: DeeplinkHandler) { | ||
| deeplinkMapper = mapper | ||
| deeplinkHandler = handler | ||
| } | ||
|
|
||
| @discardableResult | ||
| public func deferredHandle(url: URL) -> Bool { | ||
| pendingDeeplink = deeplinkMapper?.map(url: url) | ||
| return pendingDeeplink != nil | ||
| } | ||
|
|
||
| public func reset() { | ||
| operationQueue.cancelAllOperations() | ||
| pendingDeeplink = nil | ||
| isProcessingDeeplink = false | ||
| } | ||
|
|
||
| public func tryHandle() { | ||
| guard let deeplink = pendingDeeplink, | ||
| deeplinkHandler?.canHandle(deeplink: deeplink) ?? false else { | ||
| return | ||
| } | ||
|
|
||
| handle() | ||
| } | ||
|
|
||
| public func handle() { | ||
| guard let deeplink = pendingDeeplink, | ||
| let lastOperation = deeplinkHandler?.handle(deeplink: deeplink) else { | ||
| return | ||
| } | ||
|
|
||
| operationQueue.addOperation { [weak self] in | ||
| self?.isProcessingDeeplink = true | ||
| self?.pendingDeeplink = nil | ||
| } | ||
| operationQueue.addOperations(lastOperation.flattenDependencies + [lastOperation], | ||
| waitUntilFinished: false) | ||
| operationQueue.addOperation { [weak self] in | ||
| self?.isProcessingDeeplink = false | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| Pod::Spec.new do |s| | ||
| s.name = 'TIDeeplink' | ||
| s.version = '1.33.0' | ||
| s.summary = 'Deeplink service API' | ||
| s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name | ||
| s.license = { :type => 'MIT', :file => 'LICENSE' } | ||
| s.author = { 'petropavel13' => 'ivan.smolin@touchin.ru', | ||
| 'castlele' => 'nikita.semenov@touchin.ru' } | ||
| s.source = { :git => 'https://github.com/TouchInstinct/LeadKit.git', :tag => s.version.to_s } | ||
|
|
||
| s.ios.deployment_target = '11.0' | ||
| s.swift_versions = ['5.3'] | ||
|
|
||
| s.source_files = s.name + '/Sources/**/*' | ||
|
|
||
| s.dependency 'TIFoundationUtils', s.version.to_s | ||
|
|
||
| end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
давай лучше протоколом закроем, который будет предоставлять rootDeeplinkHandlerController (UIViewController)