mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Add a TracingHook. (#4345)
This commit is contained in:
@@ -39,6 +39,11 @@ class AppHooks: AppHooksProtocol {
|
||||
}
|
||||
#endif
|
||||
|
||||
private(set) var tracingHook: TracingHookProtocol = DefaultTracingHook()
|
||||
func registerTracingHook(_ hook: TracingHookProtocol) {
|
||||
tracingHook = hook
|
||||
}
|
||||
|
||||
private(set) var clientBuilderHook: ClientBuilderHookProtocol = DefaultClientBuilderHook()
|
||||
func registerClientBuilderHook(_ hook: ClientBuilderHookProtocol) {
|
||||
clientBuilderHook = hook
|
||||
|
||||
@@ -18,7 +18,7 @@ protocol RemoteSettingsHookProtocol {
|
||||
func updateCache(using client: ClientProtocol) async
|
||||
func reset(_ appSettings: CommonSettingsProtocol)
|
||||
#endif
|
||||
func loadCache(forHomeserver: String, applyingTo appSettings: CommonSettingsProtocol)
|
||||
func loadCache(forHomeserver homeserver: String, applyingTo appSettings: CommonSettingsProtocol)
|
||||
}
|
||||
|
||||
struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
|
||||
@@ -51,7 +51,7 @@ struct DefaultRemoteSettingsHook: RemoteSettingsHookProtocol {
|
||||
func reset(_ appSettings: any CommonSettingsProtocol) { }
|
||||
#endif
|
||||
|
||||
func loadCache(forHomeserver: String, applyingTo appSettings: CommonSettingsProtocol) { }
|
||||
func loadCache(forHomeserver homeserver: String, applyingTo appSettings: CommonSettingsProtocol) { }
|
||||
}
|
||||
|
||||
private struct ElementWellKnown: Decodable {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd.
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import MatrixRustSDK
|
||||
|
||||
protocol TracingHookProtocol {
|
||||
func update(_ configuration: TracingConfiguration, with rageshakeURL: RemotePreference<RageshakeConfiguration>)
|
||||
}
|
||||
|
||||
struct DefaultTracingHook: TracingHookProtocol {
|
||||
func update(_ configuration: TracingConfiguration, with rageshakeURL: RemotePreference<RageshakeConfiguration>) { }
|
||||
}
|
||||
@@ -18,7 +18,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
private let stateMachine: AppCoordinatorStateMachine
|
||||
private let navigationRootCoordinator: NavigationRootCoordinator
|
||||
private let userSessionStore: UserSessionStoreProtocol
|
||||
private let targetConfiguration: Target.Configuration
|
||||
private let targetConfiguration: Target.ConfigurationResult
|
||||
private let appMediator: AppMediator
|
||||
private let appSettings: AppSettings
|
||||
private let appDelegate: AppDelegate
|
||||
@@ -77,7 +77,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
targetConfiguration = Target.mainApp.configure(logLevel: appSettings.logLevel,
|
||||
traceLogPacks: appSettings.traceLogPacks,
|
||||
sentryURL: appSettings.bugReportSentryRustURL)
|
||||
sentryURL: appSettings.bugReportSentryRustURL,
|
||||
rageshakeURL: appSettings.bugReportRageshakeURL,
|
||||
appHooks: appHooks)
|
||||
|
||||
let appName = InfoPlistReader.main.bundleDisplayName
|
||||
let appVersion = InfoPlistReader.main.bundleShortVersionString
|
||||
|
||||
@@ -12,7 +12,7 @@ import Combine
|
||||
///
|
||||
/// Unlike ``UserPreference``, this type of setting isn't settable by the user, nor is the
|
||||
/// remote value persisted between app launches.
|
||||
struct RemotePreference<T: Equatable> {
|
||||
class RemotePreference<T: Equatable> {
|
||||
private let defaultValue: T
|
||||
private let subject: CurrentValueSubject<T, Never>
|
||||
var publisher: CurrentValuePublisher<T, Never> { subject.asCurrentValuePublisher() }
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
import MatrixRustSDK
|
||||
|
||||
@@ -32,10 +33,14 @@ enum Target: String {
|
||||
|
||||
/// Configures the target with logging and an appropriate runtime.
|
||||
///
|
||||
/// Returns a `Configuration` which should be stored to
|
||||
/// Returns a `ConfigurationResult` which should be stored to
|
||||
/// a) detect whether the platform is already configured.
|
||||
/// b) reconfigure the platform if necessary.
|
||||
func configure(logLevel: LogLevel, traceLogPacks: Set<TraceLogPack>, sentryURL: URL?) -> Configuration {
|
||||
/// b) automatically reconfigure the platform as necessary.
|
||||
func configure(logLevel: LogLevel,
|
||||
traceLogPacks: Set<TraceLogPack>,
|
||||
sentryURL: URL?,
|
||||
rageshakeURL: RemotePreference<RageshakeConfiguration>,
|
||||
appHooks: AppHooks) -> ConfigurationResult {
|
||||
let tracingConfiguration = Tracing.buildConfiguration(logLevel: logLevel,
|
||||
traceLogPacks: traceLogPacks,
|
||||
currentTarget: rawValue,
|
||||
@@ -54,14 +59,21 @@ enum Target: String {
|
||||
|
||||
MXLog.configure(currentTarget: rawValue)
|
||||
|
||||
return Configuration(tracingConfiguration: tracingConfiguration)
|
||||
let hookCancellable = rageshakeURL.publisher
|
||||
.sink { _ in
|
||||
appHooks.tracingHook.update(tracingConfiguration, with: rageshakeURL)
|
||||
}
|
||||
|
||||
return ConfigurationResult(hookCancellable: hookCancellable)
|
||||
}
|
||||
|
||||
/// Represents the configuration that was applied by ``configure(logLevel:traceLogPacks:sentryURL:)``.
|
||||
struct Configuration {
|
||||
/// The configuration applied when calling ``configure(logLevel:traceLogPacks:sentryURL:)``.
|
||||
///
|
||||
/// **Note:** This is immutable and won't be updated to reflect further changes.
|
||||
let tracingConfiguration: TracingConfiguration
|
||||
/// The result of calling ``configure(logLevel:traceLogPacks:sentryURL:)``.
|
||||
/// This must be stored - see the docs on the configure method to learn more.
|
||||
struct ConfigurationResult {
|
||||
private let hookCancellable: AnyCancellable
|
||||
|
||||
init(hookCancellable: AnyCancellable) {
|
||||
self.hookCancellable = hookCancellable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ extension ClientSDKMock {
|
||||
slidingSyncVersionReturnValue = configuration.slidingSyncVersion
|
||||
userIdServerNameThrowableError = MockError.generic
|
||||
serverReturnValue = "https://\(configuration.serverAddress)"
|
||||
homeserverReturnValue = configuration.homeserverURL
|
||||
urlForOidcOidcConfigurationPromptLoginHintDeviceIdReturnValue = OAuthAuthorizationDataSDKMock(configuration: configuration)
|
||||
loginUsernamePasswordInitialDeviceNameDeviceIdClosure = { username, password, _, _ in
|
||||
guard username == configuration.validCredentials.username,
|
||||
|
||||
@@ -7,15 +7,9 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
public init(stringLiteral value: StaticString) {
|
||||
guard let url = URL(string: "\(value)") else {
|
||||
fatalError("The static string used to create this URL is invalid")
|
||||
}
|
||||
|
||||
self = url
|
||||
}
|
||||
// MARK: - Custom URLs
|
||||
|
||||
extension URL {
|
||||
/// The URL of the primary app group container.
|
||||
static var appGroupContainerDirectory: URL {
|
||||
guard let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: InfoPlistReader.main.appGroupIdentifier) else {
|
||||
@@ -104,6 +98,45 @@ extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
return nil
|
||||
}
|
||||
|
||||
// MARK: Mocks
|
||||
|
||||
static var mockMXCAudio: URL { "mxc://matrix.org/1234567890AuDiO" }
|
||||
static var mockMXCFile: URL { "mxc://matrix.org/1234567890FiLe" }
|
||||
static var mockMXCImage: URL { "mxc://matrix.org/1234567890ImAgE" }
|
||||
static var mockMXCVideo: URL { "mxc://matrix.org/1234567890ViDeO" }
|
||||
static var mockMXCAvatar: URL { "mxc://matrix.org/1234567890AvAtAr" }
|
||||
static var mockMXCUserAvatar: URL { "mxc://matrix.org/1234567890AvAtArUsEr" }
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
public init(stringLiteral value: StaticString) {
|
||||
guard let url = URL(string: "\(value)") else {
|
||||
fatalError("The static string used to create this URL is invalid")
|
||||
}
|
||||
|
||||
self = url
|
||||
}
|
||||
|
||||
/// Sanitises the URL for use as the name of a directory.
|
||||
func asDirectoryName() -> String {
|
||||
absoluteString.asURLDirectoryName()
|
||||
}
|
||||
}
|
||||
|
||||
extension String {
|
||||
/// Assumes that the string is a URL and sanitises it for use as the name of a directory.
|
||||
func asURLDirectoryName() -> String {
|
||||
replacingOccurrences(of: "https://", with: "")
|
||||
.trimmingCharacters(in: CharacterSet(charactersIn: "/"))
|
||||
.replacing(/[:\/\p{C}]/, with: "-")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Phishing Confirmation URL
|
||||
|
||||
extension URL {
|
||||
static let confirmationScheme = "confirm"
|
||||
|
||||
var requiresConfirmation: Bool {
|
||||
@@ -117,15 +150,6 @@ extension URL: @retroactive ExpressibleByStringLiteral {
|
||||
}
|
||||
return ConfirmURLParameters(queryItems: queryItems)
|
||||
}
|
||||
|
||||
// MARK: Mocks
|
||||
|
||||
static var mockMXCAudio: URL { "mxc://matrix.org/1234567890AuDiO" }
|
||||
static var mockMXCFile: URL { "mxc://matrix.org/1234567890FiLe" }
|
||||
static var mockMXCImage: URL { "mxc://matrix.org/1234567890ImAgE" }
|
||||
static var mockMXCVideo: URL { "mxc://matrix.org/1234567890ViDeO" }
|
||||
static var mockMXCAvatar: URL { "mxc://matrix.org/1234567890AvAtAr" }
|
||||
static var mockMXCUserAvatar: URL { "mxc://matrix.org/1234567890AvAtArUsEr" }
|
||||
}
|
||||
|
||||
struct ConfirmURLParameters {
|
||||
|
||||
Reference in New Issue
Block a user