* Converge on UserSessionFlowCoordinator logout confirmation * Add logout confirmation screen strings to untranslated. * Fix chat backup learn more URl fragment. * Implement logout flows that check recovery and key backup for the last session * Move logout confirmation screen strings to localazy * Change encrypted timeline item copy to "Waiting for decryption key" * Use different encrypted history banner based on key backup states * Introduce a SettingsFlowCoordinator and implement navigation directly to the secure backup screen from the logout flows. * Fix **mocked** secure backup controller flows * Simplify encrypted history banner logic * Address PR comments
127 lines
4.0 KiB
Swift
127 lines
4.0 KiB
Swift
//
|
|
// Copyright 2023 New Vector Ltd
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
enum AppRoute: Equatable {
|
|
case oidcCallback(url: URL)
|
|
case roomList
|
|
case room(roomID: String)
|
|
case roomDetails(roomID: String)
|
|
case roomMemberDetails(userID: String)
|
|
case invites
|
|
case genericCallLink(url: URL)
|
|
case settings
|
|
case chatBackupSettings
|
|
}
|
|
|
|
struct AppRouteURLParser {
|
|
let urlParsers: [URLParser]
|
|
|
|
init(appSettings: AppSettings) {
|
|
urlParsers = [
|
|
MatrixPermalinkParser(appSettings: appSettings),
|
|
OIDCCallbackURLParser(appSettings: appSettings),
|
|
ElementCallURLParser()
|
|
]
|
|
}
|
|
|
|
func route(from url: URL) -> AppRoute? {
|
|
for parser in urlParsers {
|
|
if let appRoute = parser.route(from: url) {
|
|
return appRoute
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
/// Represents a type that can parse a `URL` into an `AppRoute`.
|
|
///
|
|
/// The following Universal Links are missing parsers.
|
|
/// - app.element.io
|
|
/// - staging.element.io
|
|
/// - develop.element.io
|
|
/// - mobile.element.io
|
|
protocol URLParser {
|
|
func route(from url: URL) -> AppRoute?
|
|
}
|
|
|
|
/// The parser for the OIDC callback URL. This always returns a `.oidcCallback`.
|
|
struct OIDCCallbackURLParser: URLParser {
|
|
let appSettings: AppSettings
|
|
|
|
func route(from url: URL) -> AppRoute? {
|
|
guard url.absoluteString.starts(with: appSettings.oidcRedirectURL.absoluteString) else { return nil }
|
|
return .oidcCallback(url: url)
|
|
}
|
|
}
|
|
|
|
/// The parser for Element Call links. This always returns a `.genericCallLink`.
|
|
struct ElementCallURLParser: URLParser {
|
|
private let knownHosts = ["call.element.io"]
|
|
private let customSchemeURLQueryParameterName = "url"
|
|
|
|
func route(from url: URL) -> AppRoute? {
|
|
// Element Call not supported, WebRTC not available
|
|
// https://github.com/vector-im/element-x-ios/issues/1794
|
|
if ProcessInfo.processInfo.isiOSAppOnMac {
|
|
return nil
|
|
}
|
|
|
|
// First try processing URLs with custom schemes
|
|
if let scheme = url.scheme,
|
|
scheme == InfoPlistReader.app.elementCallScheme {
|
|
guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
|
|
return nil
|
|
}
|
|
|
|
guard let encodedURLString = components.queryItems?.first(where: { $0.name == customSchemeURLQueryParameterName })?.value,
|
|
let callURL = URL(string: encodedURLString),
|
|
callURL.scheme == "https" // Don't allow URLs from potentially unsafe domains
|
|
else {
|
|
MXLog.error("Invalid custom scheme call parameters: \(url)")
|
|
return nil
|
|
}
|
|
|
|
return .genericCallLink(url: callURL)
|
|
}
|
|
|
|
// Otherwise try to interpret it as an universal link
|
|
guard let host = url.host, knownHosts.contains(host) else {
|
|
return nil
|
|
}
|
|
|
|
return .genericCallLink(url: url)
|
|
}
|
|
}
|
|
|
|
struct MatrixPermalinkParser: URLParser {
|
|
let appSettings: AppSettings
|
|
|
|
func route(from url: URL) -> AppRoute? {
|
|
switch PermalinkBuilder.detectPermalink(in: url, baseURL: appSettings.permalinkBaseURL) {
|
|
case .userIdentifier(let userID):
|
|
return .roomMemberDetails(userID: userID)
|
|
case .roomIdentifier(let roomID):
|
|
return .room(roomID: roomID)
|
|
default:
|
|
return nil
|
|
}
|
|
}
|
|
}
|