From 1fe7d270aa2115b7ba74c9f372d27dd4301a28e6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 19 Sep 2023 15:56:14 +0300 Subject: [PATCH] Use a different scheme for Element Call in the form of `io.element.call:/?url=some_url` --- ElementX.xcodeproj/project.pbxproj | 2 -- .../Application/Navigation/AppRoutes.swift | 6 ++-- ElementX/Sources/Other/InfoPlistReader.swift | 28 +++++++++++++------ ElementX/SupportingFiles/Info.plist | 14 ++++++++-- ElementX/SupportingFiles/target.yml | 11 ++++++-- .../Sources/AppRouteURLParserTests.swift | 2 +- project.yml | 1 - 7 files changed, 43 insertions(+), 21 deletions(-) diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 55178c6da..6a4f4d98b 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -5308,7 +5308,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - APP_CUSTOM_SCHEME = element; APP_DISPLAY_NAME = "Element X"; APP_GROUP_IDENTIFIER = "group.$(BASE_APP_GROUP_IDENTIFIER)"; APP_NAME = ElementX; @@ -5378,7 +5377,6 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - APP_CUSTOM_SCHEME = element; APP_DISPLAY_NAME = "Element X"; APP_GROUP_IDENTIFIER = "group.$(BASE_APP_GROUP_IDENTIFIER)"; APP_NAME = ElementX; diff --git a/ElementX/Sources/Application/Navigation/AppRoutes.swift b/ElementX/Sources/Application/Navigation/AppRoutes.swift index 4595a13e1..2b4473c3b 100644 --- a/ElementX/Sources/Application/Navigation/AppRoutes.swift +++ b/ElementX/Sources/Application/Navigation/AppRoutes.swift @@ -80,15 +80,13 @@ struct ElementAppURLParser: URLParser { /// The parser for Element Call links. This always returns a `.genericCallLink` struct ElementCallURLParser: URLParser { private let knownHosts = ["call.element.io"] - private let customSchemeHost = "call" private let customSchemeURLQueryParameterName = "url" func route(from url: URL) -> AppRoute? { // First try processing URLs with custom schemes if let scheme = url.scheme, - scheme == InfoPlistReader.app.appScheme { - guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false), - components.host == customSchemeHost else { + scheme == InfoPlistReader.app.elementCallScheme { + guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return nil } diff --git a/ElementX/Sources/Other/InfoPlistReader.swift b/ElementX/Sources/Other/InfoPlistReader.swift index a16a2b467..7fb50e620 100644 --- a/ElementX/Sources/Other/InfoPlistReader.swift +++ b/ElementX/Sources/Other/InfoPlistReader.swift @@ -33,6 +33,7 @@ struct InfoPlistReader { static let otlpTracingPassword = "otlpTracingPassword" static let bundleURLTypes = "CFBundleURLTypes" + static let bundleURLName = "CFBundleURLName" static let bundleURLSchemes = "CFBundleURLSchemes" } @@ -117,14 +118,11 @@ struct InfoPlistReader { // MARK: - Custom App Scheme var appScheme: String { - let urlTypes: [[String: Any]] = infoPlistValue(forKey: Keys.bundleURLTypes) - - guard let urlSchemes = urlTypes.first?[Keys.bundleURLSchemes] as? [String], - let scheme = urlSchemes.first else { - fatalError("Invalid custon application scheme configuration") - } - - return scheme + customSchemeForName("Application") + } + + var elementCallScheme: String { + customSchemeForName("Element Call") } // MARK: - Mention Pills @@ -140,11 +138,23 @@ struct InfoPlistReader { } // MARK: - Private - + private func infoPlistValue(forKey key: String) -> T { guard let result = bundle.object(forInfoDictionaryKey: key) as? T else { fatalError("Add \(key) into your target's Info.plst") } return result } + + private func customSchemeForName(_ name: String) -> String { + let urlTypes: [[String: Any]] = infoPlistValue(forKey: Keys.bundleURLTypes) + + guard let urlType = urlTypes.first(where: { $0[Keys.bundleURLName] as? String == name }), + let urlSchemes = urlType[Keys.bundleURLSchemes] as? [String], + let scheme = urlSchemes.first else { + fatalError("Invalid custom application scheme configuration") + } + + return scheme + } } diff --git a/ElementX/SupportingFiles/Info.plist b/ElementX/SupportingFiles/Info.plist index 50eefe27d..f757b0165 100644 --- a/ElementX/SupportingFiles/Info.plist +++ b/ElementX/SupportingFiles/Info.plist @@ -41,10 +41,20 @@ CFBundleTypeRole Editor CFBundleURLName - $(BASE_BUNDLE_IDENTIFIER) + Element Call CFBundleURLSchemes - $(APP_CUSTOM_SCHEME) + io.element.call + + + + CFBundleTypeRole + Editor + CFBundleURLName + Application + CFBundleURLSchemes + + io.element diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index 03f405308..f9f4d8182 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -57,9 +57,16 @@ targets: CFBundleURLTypes: [ { CFBundleTypeRole: Editor, - CFBundleURLName: $(BASE_BUNDLE_IDENTIFIER), + CFBundleURLName: "Element Call", CFBundleURLSchemes: [ - $(APP_CUSTOM_SCHEME) + io.element.call + ] + }, + { + CFBundleTypeRole: Editor, + CFBundleURLName: "Application", + CFBundleURLSchemes: [ + io.element ] } ] diff --git a/UnitTests/Sources/AppRouteURLParserTests.swift b/UnitTests/Sources/AppRouteURLParserTests.swift index eebaed024..f8dd886e9 100644 --- a/UnitTests/Sources/AppRouteURLParserTests.swift +++ b/UnitTests/Sources/AppRouteURLParserTests.swift @@ -27,7 +27,7 @@ class AppRouteURLParserTests: XCTestCase { XCTAssertEqual(AppRouteURLParser(appSettings: ServiceLocator.shared.settings).route(from: url), AppRoute.genericCallLink(url: url)) - guard let customSchemeURL = URL(string: "element://call?url=https%3A%2F%2Fcall.element.io%2Ftest") else { + guard let customSchemeURL = URL(string: "io.element.call:/?url=https%3A%2F%2Fcall.element.io%2Ftest") else { XCTFail("URL invalid") return } diff --git a/project.yml b/project.yml index ea50240a9..0cd1e24ad 100644 --- a/project.yml +++ b/project.yml @@ -28,7 +28,6 @@ settings: BASE_BUNDLE_IDENTIFIER: io.element.elementx APP_NAME: ElementX APP_DISPLAY_NAME: Element X - APP_CUSTOM_SCHEME: element KEYCHAIN_ACCESS_GROUP_IDENTIFIER: $(AppIdentifierPrefix)$(BASE_BUNDLE_IDENTIFIER) MARKETING_VERSION: 1.3.0 CURRENT_PROJECT_VERSION: 1