mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Run SwiftFormat.
This commit is contained in:
@@ -29,7 +29,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
private let appHooks: AppHooks
|
||||
private let bugReportService: BugReportServiceProtocol
|
||||
private let elementCallService: ElementCallServiceProtocol
|
||||
|
||||
|
||||
/// Common background task to continue long-running tasks in the background.
|
||||
private var backgroundTask: UIBackgroundTaskIdentifier?
|
||||
|
||||
@@ -60,13 +60,13 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
let windowManager: SecureWindowManagerProtocol
|
||||
let notificationManager: NotificationManagerProtocol
|
||||
|
||||
|
||||
private let appRouteURLParser: AppRouteURLParser
|
||||
|
||||
private var storedAppRoute: AppRoute?
|
||||
@Consumable private var storedInlineReply: (roomID: String, message: String)?
|
||||
@Consumable private var storedRoomsToAwait: Set<String>?
|
||||
|
||||
|
||||
init(appDelegate: AppDelegate) {
|
||||
let appHooks = AppHooks()
|
||||
appHooks.setUp()
|
||||
@@ -115,9 +115,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
navigationRootCoordinator = NavigationRootCoordinator()
|
||||
|
||||
stateMachine = AppCoordinatorStateMachine()
|
||||
|
||||
|
||||
navigationRootCoordinator.setRootCoordinator(SplashScreenCoordinator())
|
||||
|
||||
|
||||
let keychainController = KeychainController(service: .sessions,
|
||||
accessGroup: InfoPlistReader.main.keychainAccessGroupIdentifier)
|
||||
userSessionStore = UserSessionStore(keychainController: keychainController,
|
||||
@@ -160,9 +160,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
wipeUserData(includingSettings: true)
|
||||
}
|
||||
appSettings.lastVersionLaunched = currentVersion.description
|
||||
|
||||
|
||||
setupStateMachine()
|
||||
|
||||
|
||||
observeApplicationState()
|
||||
observeAppLockChanges()
|
||||
|
||||
@@ -213,13 +213,13 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
stateMachine.processEvent(.startWithExistingSession)
|
||||
}
|
||||
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(navigationRootCoordinator.toPresentable()
|
||||
.environment(\.analyticsService, analyticsService)
|
||||
.onReceive(appSettings.$appAppearance) { [weak self] appAppearance in
|
||||
guard let self else { return }
|
||||
|
||||
|
||||
windowManager.windows.forEach { window in
|
||||
// Unfortunately .preferredColorScheme doesn't propagate properly throughout the app when changed
|
||||
window.overrideUserInterfaceStyle = appAppearance.interfaceStyle
|
||||
@@ -267,7 +267,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
storedAppRoute = appRoute
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func handleDeepLink(_ url: URL, isExternalURL: Bool, windowType: SecondaryWindowType?) -> Bool {
|
||||
// Parse into an AppRoute to redirect these in a type safe way.
|
||||
|
||||
@@ -382,7 +382,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
func unregisterForRemoteNotifications() {
|
||||
UIApplication.shared.unregisterForRemoteNotifications()
|
||||
}
|
||||
|
||||
|
||||
func shouldDisplayInAppNotification(content: UNNotificationContent) -> Bool {
|
||||
guard let roomID = content.roomID else {
|
||||
return true
|
||||
@@ -542,7 +542,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Clears the keychain, app support directory etc ready for a fresh use.
|
||||
/// - Parameter includingSettings: Whether to additionally wipe the user's app settings too.
|
||||
private func wipeUserData(includingSettings: Bool = false) {
|
||||
@@ -608,7 +608,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
presentSplashScreen()
|
||||
case (.restoringSession, .createdUserSession, .signedIn):
|
||||
setupUserSession(isNewLogin: false)
|
||||
|
||||
|
||||
case (.signingOut, .signOut, .signingOut):
|
||||
// We can ignore signOut when already in the process of signing out,
|
||||
// such as the SDK sending an authError due to token invalidation.
|
||||
@@ -696,7 +696,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
await processInlineReply(roomID: storedInlineReply.roomID, replyText: storedInlineReply.message)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func startAuthenticationSoftLogout() {
|
||||
guard let userSession else {
|
||||
fatalError("User session not setup")
|
||||
@@ -799,7 +799,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
await runPostSessionSetupTasks()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func logout(isSoft: Bool) {
|
||||
guard let userSession else {
|
||||
fatalError("User session not setup")
|
||||
@@ -841,7 +841,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
analyticsService.resetConsentState()
|
||||
|
||||
stateMachine.processEvent(.completedSigningOut)
|
||||
|
||||
|
||||
hideLoadingIndicator()
|
||||
}
|
||||
}
|
||||
@@ -852,7 +852,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
userSession = nil
|
||||
|
||||
userSessionFlowCoordinator = nil
|
||||
|
||||
|
||||
notificationManager.setUserSession(nil)
|
||||
}
|
||||
|
||||
@@ -882,10 +882,10 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
elementCallService.setClientProxy(userSession.clientProxy)
|
||||
}
|
||||
|
||||
|
||||
private func configureNotificationManager() {
|
||||
notificationManager.setUserSession(userSession)
|
||||
|
||||
|
||||
appDelegateObserver = appDelegate.callbacks
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] callback in
|
||||
@@ -940,7 +940,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
|
||||
stopSync(isBackgroundTask: false)
|
||||
userSessionFlowCoordinator?.stop()
|
||||
|
||||
|
||||
// Allow for everything to deallocate properly
|
||||
Task {
|
||||
await userSession.clientProxy.clearCaches()
|
||||
@@ -959,7 +959,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
#else
|
||||
options.enabled = appSettings.analyticsConsentState == .optedIn
|
||||
#endif
|
||||
|
||||
|
||||
options.dsn = bugReportSentryURL.absoluteString
|
||||
|
||||
// Matches android, at least for now.
|
||||
@@ -997,7 +997,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
options.sampleRate = 1.0
|
||||
options.tracesSampleRate = 1.0
|
||||
options.configureProfiling = { $0.sessionSampleRate = 1.0 }
|
||||
|
||||
|
||||
// This callback is only executed once during the entire run of the program to avoid
|
||||
// multiple callbacks if there are multiple crash events to send (see method documentation)
|
||||
options.onLastRunStatusDetermined = { status, event in
|
||||
@@ -1056,9 +1056,9 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
private func showLoginErrorToast() {
|
||||
userIndicatorController.submitIndicator(UserIndicator(title: "Failed logging in"))
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Application State
|
||||
|
||||
|
||||
private func stopSync(isBackgroundTask: Bool, completion: (() -> Void)? = nil) {
|
||||
if isBackgroundTask, UIApplication.shared.applicationState == .active {
|
||||
// Attempt to stop the background task sync loop cleanly, only if the app not already running
|
||||
@@ -1070,7 +1070,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
clientProxyObserver = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func startSync() {
|
||||
guard let userSession else { return }
|
||||
|
||||
@@ -1103,7 +1103,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func observeApplicationState() {
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(applicationWillResignActive),
|
||||
@@ -1123,7 +1123,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
selector: #selector(applicationDidBecomeActive),
|
||||
name: UIApplication.didBecomeActiveNotification,
|
||||
object: nil)
|
||||
|
||||
|
||||
NotificationCenter.default.addObserver(self,
|
||||
selector: #selector(applicationWillTerminate),
|
||||
name: UIApplication.willTerminateNotification,
|
||||
@@ -1133,18 +1133,18 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationFlowCoordinatorDeleg
|
||||
name: UIContentSizeCategory.didChangeNotification,
|
||||
object: nil)
|
||||
}
|
||||
|
||||
|
||||
@objc
|
||||
private func didChangeContentSizeCategory() {
|
||||
AttributedStringBuilder.invalidateCaches()
|
||||
}
|
||||
|
||||
|
||||
@objc
|
||||
private func applicationWillTerminate() {
|
||||
MXLog.info("Application will terminate")
|
||||
stopSync(isBackgroundTask: false)
|
||||
}
|
||||
|
||||
|
||||
@objc
|
||||
private func applicationDidEnterBackground() {
|
||||
MXLog.info("Application did enter background")
|
||||
|
||||
@@ -20,14 +20,14 @@ class AppCoordinatorStateMachine {
|
||||
case softLogout
|
||||
/// Opening an existing session.
|
||||
case restoringSession
|
||||
|
||||
|
||||
/// User session started
|
||||
case signedIn
|
||||
|
||||
|
||||
/// Processing a sign out request
|
||||
case signingOut(isSoft: Bool, disableAppLock: Bool)
|
||||
}
|
||||
|
||||
|
||||
/// Events that can be triggered on the AppCoordinator state machine
|
||||
enum Event: EventType {
|
||||
/// Start the `AppCoordinator` by showing authentication.
|
||||
@@ -41,7 +41,7 @@ class AppCoordinatorStateMachine {
|
||||
|
||||
/// A session has been created.
|
||||
case createdUserSession
|
||||
|
||||
|
||||
/// Request sign out.
|
||||
case signOut(isSoft: Bool, disableAppLock: Bool)
|
||||
/// Request the soft logout screen.
|
||||
@@ -63,7 +63,7 @@ class AppCoordinatorStateMachine {
|
||||
stateMachine = StateMachine(state: .initial)
|
||||
configure()
|
||||
}
|
||||
|
||||
|
||||
private func configure() {
|
||||
stateMachine.addRoutes(event: .startWithAuthentication, transitions: [.initial => .signedOut])
|
||||
stateMachine.addRoutes(event: .createdUserSession, transitions: [.signedOut => .signedIn,
|
||||
@@ -71,13 +71,13 @@ class AppCoordinatorStateMachine {
|
||||
stateMachine.addRoutes(event: .startWithExistingSession, transitions: [.initial => .restoringSession])
|
||||
stateMachine.addRoutes(event: .createdUserSession, transitions: [.restoringSession => .signedIn])
|
||||
stateMachine.addRoutes(event: .failedRestoringSession, transitions: [.restoringSession => .signedOut])
|
||||
|
||||
|
||||
stateMachine.addRoutes(event: .completedSigningOut, transitions: [.signingOut(isSoft: false, disableAppLock: false) => .signedOut,
|
||||
.signingOut(isSoft: false, disableAppLock: true) => .signedOut])
|
||||
stateMachine.addRoutes(event: .showSoftLogout, transitions: [.signingOut(isSoft: true, disableAppLock: false) => .softLogout])
|
||||
|
||||
stateMachine.addRoutes(event: .clearCache, transitions: [.signedIn => .initial])
|
||||
|
||||
|
||||
// Transitions with associated values need to be handled through `addRouteMapping`
|
||||
stateMachine.addRouteMapping { event, fromState, _ in
|
||||
switch (fromState, event) {
|
||||
@@ -87,7 +87,7 @@ class AppCoordinatorStateMachine {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addTransitionHandler { context in
|
||||
if let event = context.event {
|
||||
MXLog.info("Transitioning from `\(context.fromState)` to `\(context.toState)` with event `\(event)`")
|
||||
|
||||
@@ -24,7 +24,7 @@ final class AppDelegate: NSObject, UIApplicationDelegate {
|
||||
configuration.delegateClass = SceneDelegate.self
|
||||
return configuration
|
||||
}
|
||||
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
|
||||
NSTextAttachment.registerViewProviderClass(PillAttachmentViewProvider.self, forFileType: InfoPlistReader.main.pillsUTType)
|
||||
return true
|
||||
|
||||
@@ -17,12 +17,12 @@ class AppMediator: AppMediatorProtocol {
|
||||
self.windowManager = windowManager
|
||||
self.networkMonitor = networkMonitor
|
||||
}
|
||||
|
||||
|
||||
/// UIApplication.State won't update if we store this e.g. in the constructor
|
||||
private var application: UIApplication {
|
||||
UIApplication.shared
|
||||
}
|
||||
|
||||
|
||||
var appState: UIApplication.State {
|
||||
switch application.applicationState {
|
||||
case .active:
|
||||
@@ -39,7 +39,7 @@ class AppMediator: AppMediatorProtocol {
|
||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier {
|
||||
application.beginBackgroundTask(expirationHandler: handler)
|
||||
}
|
||||
|
||||
|
||||
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier) {
|
||||
application.endBackgroundTask(identifier)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ protocol AppMediatorProtocol {
|
||||
var appState: UIApplication.State { get }
|
||||
|
||||
func beginBackgroundTask(expirationHandler handler: (() -> Void)?) -> UIBackgroundTaskIdentifier
|
||||
|
||||
|
||||
func endBackgroundTask(_ identifier: UIBackgroundTaskIdentifier)
|
||||
|
||||
func open(_ url: URL)
|
||||
|
||||
@@ -16,7 +16,7 @@ struct Application: App {
|
||||
@Environment(\.dismissWindow) private var dismissWindow
|
||||
|
||||
private var appCoordinator: AppCoordinatorProtocol!
|
||||
|
||||
|
||||
init() {
|
||||
if ProcessInfo.isRunningUITests {
|
||||
appCoordinator = UITestsAppCoordinator(appDelegate: appDelegate)
|
||||
@@ -30,7 +30,7 @@ struct Application: App {
|
||||
|
||||
SceneDelegate.windowManager = appCoordinator.windowManager
|
||||
}
|
||||
|
||||
|
||||
var body: some Scene {
|
||||
WindowGroup(id: SceneDelegate.mainSceneID) {
|
||||
appCoordinator.toPresentable()
|
||||
@@ -114,7 +114,7 @@ struct Application: App {
|
||||
openURLInSystemBrowser(url)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Hide the status bar so it doesn't interfere with the screenshot tests
|
||||
private var shouldHideStatusBar: Bool {
|
||||
ProcessInfo.isRunningUITests
|
||||
|
||||
@@ -17,9 +17,9 @@ protocol CoordinatorProtocol: AnyObject {
|
||||
|
||||
extension CoordinatorProtocol {
|
||||
func start() { }
|
||||
|
||||
|
||||
func stop() { }
|
||||
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(Text("View not configured"))
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ struct CommonFlowParameters {
|
||||
var windowManager: WindowManagerProtocol {
|
||||
appMediator.windowManager
|
||||
}
|
||||
|
||||
|
||||
var ongoingCallRoomIDPublisher: CurrentValuePublisher<String?, Never> {
|
||||
elementCallService.ongoingCallRoomIDPublisher
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import SwiftUI
|
||||
/// into a single navigation stack on compact layouts
|
||||
@Observable class NavigationSplitCoordinator: CoordinatorProtocol, CustomStringConvertible {
|
||||
fileprivate let placeholderModule: NavigationModule
|
||||
|
||||
|
||||
fileprivate var sidebarModule: NavigationModule? {
|
||||
didSet {
|
||||
if let oldValue {
|
||||
@@ -105,7 +105,7 @@ import SwiftUI
|
||||
var compactLayoutRootCoordinator: (any CoordinatorProtocol)? {
|
||||
compactLayoutRootModule?.coordinator
|
||||
}
|
||||
|
||||
|
||||
var compactLayoutStackModules: [NavigationModule] {
|
||||
get {
|
||||
getCompactStackModules()
|
||||
@@ -114,7 +114,7 @@ import SwiftUI
|
||||
setCompactStackModules(newValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func getCompactStackModules() -> [NavigationModule] {
|
||||
// Start building the new compact layout navigation stack
|
||||
var stackModules: [NavigationModule] = []
|
||||
@@ -123,23 +123,23 @@ import SwiftUI
|
||||
if let sidebarNavigationStackCoordinator = sidebarModule?.coordinator as? NavigationStackCoordinator {
|
||||
stackModules.append(contentsOf: sidebarNavigationStackCoordinator.stackModules)
|
||||
}
|
||||
|
||||
|
||||
// If the detail is a stackCoordinator then push its root and children to the compact layout stack
|
||||
if let detailNavigationStackCoordinator = detailModule?.coordinator as? NavigationStackCoordinator {
|
||||
if let detailRootCoordinator = detailNavigationStackCoordinator.rootModule {
|
||||
stackModules.append(detailRootCoordinator)
|
||||
}
|
||||
|
||||
|
||||
stackModules.append(contentsOf: detailNavigationStackCoordinator.stackModules)
|
||||
} else if let detailModule { // Otherwise just push it entirely
|
||||
stackModules.append(detailModule)
|
||||
}
|
||||
return stackModules
|
||||
}
|
||||
|
||||
|
||||
private func setCompactStackModules(_ modules: [NavigationModule]) {
|
||||
guard compactLayoutStackModules != modules else { return }
|
||||
|
||||
|
||||
let diffs = modules.difference(from: compactLayoutStackModules)
|
||||
diffs.forEach { change in
|
||||
switch change {
|
||||
@@ -150,7 +150,7 @@ import SwiftUI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var compactLayoutStackCoordinators: [any CoordinatorProtocol] {
|
||||
compactLayoutStackModules.compactMap(\.coordinator)
|
||||
}
|
||||
@@ -175,10 +175,10 @@ import SwiftUI
|
||||
if sidebarModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
sidebarModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -198,10 +198,10 @@ import SwiftUI
|
||||
if detailModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
detailModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -221,10 +221,10 @@ import SwiftUI
|
||||
if sheetModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -244,15 +244,15 @@ import SwiftUI
|
||||
if fullScreenCoverModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CoordinatorProtocol
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
@@ -264,7 +264,7 @@ import SwiftUI
|
||||
}
|
||||
|
||||
// MARK: - CustomStringConvertible
|
||||
|
||||
|
||||
var description: String {
|
||||
switch (sidebarModule?.coordinator, detailModule?.coordinator) {
|
||||
case (.some(let sidebarCoordinator), .some(let detailCoordinator)):
|
||||
@@ -533,10 +533,10 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
}
|
||||
|
||||
popToRoot(animated: false)
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
rootModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -550,7 +550,7 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
func push(_ coordinator: any CoordinatorProtocol, animated: Bool = true, dismissalCallback: (() -> Void)? = nil) {
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
stackModules.append(NavigationModule(coordinator, dismissalCallback: dismissalCallback))
|
||||
}
|
||||
@@ -562,10 +562,10 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
guard !stackModules.isEmpty else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
stackModules.removeAll()
|
||||
}
|
||||
@@ -576,7 +576,7 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
func pop(animated: Bool = true) {
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
_ = stackModules.popLast()
|
||||
}
|
||||
@@ -617,15 +617,15 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
if sheetModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// periphery:ignore - might be useful to have
|
||||
/// Present a fullscreen cover on top of the stack. If this NavigationStackCoordinator is embedded within a NavigationSplitCoordinator
|
||||
/// then the presentation will be proxied to the split
|
||||
@@ -647,10 +647,10 @@ private struct NavigationSplitCoordinatorView: View {
|
||||
if fullScreenCoverModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
|
||||
@@ -77,15 +77,15 @@ import SwiftUI
|
||||
if sheetModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - CoordinatorProtocol
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
|
||||
@@ -57,7 +57,7 @@ import SwiftUI
|
||||
var id: ObjectIdentifier {
|
||||
module.id
|
||||
}
|
||||
|
||||
|
||||
@MainActor var coordinator: CoordinatorProtocol? {
|
||||
module.coordinator
|
||||
}
|
||||
@@ -137,10 +137,10 @@ import SwiftUI
|
||||
if sheetModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
sheetModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -183,10 +183,10 @@ import SwiftUI
|
||||
if fullScreenCoverModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
fullScreenCoverModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
}
|
||||
@@ -234,10 +234,10 @@ import SwiftUI
|
||||
if overlayModule?.coordinator === coordinator {
|
||||
fatalError("Cannot use the same coordinator more than once")
|
||||
}
|
||||
|
||||
|
||||
var transaction = Transaction()
|
||||
transaction.disablesAnimations = !animated
|
||||
|
||||
|
||||
withTransaction(transaction) {
|
||||
overlayPresentationMode = presentationMode
|
||||
overlayModule = NavigationModule(coordinator, dismissalCallback: dismissalCallback)
|
||||
|
||||
@@ -13,7 +13,7 @@ enum AppAppearance: CaseIterable, Codable {
|
||||
case system
|
||||
case dark
|
||||
case light
|
||||
|
||||
|
||||
var interfaceStyle: UIUserInterfaceStyle {
|
||||
switch self {
|
||||
case .light:
|
||||
|
||||
@@ -17,7 +17,7 @@ import SwiftUI
|
||||
protocol CommonSettingsProtocol: AnyObject, Sendable {
|
||||
var lastNotificationBootTime: TimeInterval? { get set }
|
||||
var selectedNotificationTone: NotificationTone? { get set }
|
||||
|
||||
|
||||
var logLevel: LogLevel { get }
|
||||
var traceLogPacks: Set<TraceLogPack> { get }
|
||||
var bugReportRageshakeURL: RemotePreference<RageshakeConfiguration> { get }
|
||||
@@ -95,7 +95,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
}
|
||||
|
||||
static let suiteName: String = InfoPlistReader.main.appGroupIdentifier
|
||||
|
||||
|
||||
/// UserDefaults to be used on reads and writes.
|
||||
private let store: UserDefaultsProtocol
|
||||
|
||||
@@ -174,7 +174,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
/// deleted between runs so should clear data in the shared container and keychain.
|
||||
@UserPreference
|
||||
var lastVersionLaunched: String?
|
||||
|
||||
|
||||
/// The Set of room identifiers of invites that the user already saw in the invites list.
|
||||
/// This Set is being used to implement badges for unread invites.
|
||||
@UserPreference
|
||||
@@ -196,7 +196,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
/// The task identifier used for background app refresh. Also used in main target's the Info.plist
|
||||
let backgroundAppRefreshTaskIdentifier = "io.element.elementx.background.refresh"
|
||||
|
||||
|
||||
/// A URL where users can go read more about the app.
|
||||
private(set) var websiteURL: URL = "https://element.io"
|
||||
/// A URL that contains the app's logo that may be used when showing content in a web view.
|
||||
@@ -217,7 +217,7 @@ final class AppSettings: @unchecked Sendable {
|
||||
private(set) var identityPinningViolationDetailsURL: URL = "https://element.io/help#encryption18"
|
||||
/// A URL describing how history sharing works
|
||||
private(set) var historySharingDetailsURL: URL = "https://element.io/en/help#e2ee-history-sharing"
|
||||
|
||||
|
||||
/// Any domains that Element web may be hosted on - used for handling links.
|
||||
private(set) var elementWebHosts = ["app.element.io", "staging.element.io", "develop.element.io"]
|
||||
/// The domain that account provisioning links will be hosted on - used for handling the links.
|
||||
@@ -279,13 +279,13 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
@UserPreference
|
||||
var enableNotifications: Bool
|
||||
|
||||
|
||||
@UserPreference
|
||||
var enableInAppNotifications: Bool
|
||||
|
||||
@UserPreference
|
||||
var hideQuietNotificationAlerts: Bool
|
||||
|
||||
|
||||
/// Tag describing which set of device specific rules a pusher executes.
|
||||
@UserPreference
|
||||
var pusherProfileTag: String?
|
||||
@@ -293,13 +293,13 @@ final class AppSettings: @unchecked Sendable {
|
||||
/// The device's last boot time as recorded by the NSE.
|
||||
@UserPreference
|
||||
var lastNotificationBootTime: TimeInterval?
|
||||
|
||||
|
||||
/// The sound played when delivering noisy notifications. If nil, use the ElementX default
|
||||
@UserPreference
|
||||
var selectedNotificationTone: NotificationTone?
|
||||
|
||||
|
||||
// MARK: - Logging
|
||||
|
||||
|
||||
@UserPreference
|
||||
var logLevel: LogLevel
|
||||
|
||||
@@ -369,14 +369,14 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
@UserPreference
|
||||
var optimizeMediaUploads: Bool
|
||||
|
||||
|
||||
@UserPreference
|
||||
var voiceMessagePlaybackSpeed: AudioPlaybackSpeed
|
||||
|
||||
|
||||
/// Whether or not to show a warning on the media caption composer so the user knows
|
||||
/// that captions might not be visible to users who are using other Matrix clients.
|
||||
let shouldShowMediaCaptionWarning = true
|
||||
|
||||
|
||||
// MARK: - Element Call
|
||||
|
||||
#if IS_MAIN_APP
|
||||
@@ -434,13 +434,13 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
@UserPreference
|
||||
var focusEventOnNotificationTap: Bool
|
||||
|
||||
|
||||
@UserPreference
|
||||
var linkPreviewsEnabled: Bool
|
||||
|
||||
@UserPreference
|
||||
var jumpToReadMarkerEnabled: Bool
|
||||
|
||||
|
||||
@UserPreference
|
||||
var linkNewDeviceEnabled: Bool
|
||||
|
||||
@@ -452,11 +452,11 @@ final class AppSettings: @unchecked Sendable {
|
||||
|
||||
@UserPreference
|
||||
var developerOptionsEnabled: Bool
|
||||
|
||||
|
||||
init(store: UserDefaultsProtocol) {
|
||||
// UserDefaults to be used on reads and writes.
|
||||
self.store = store
|
||||
|
||||
|
||||
_lastVersionLaunched = UserPreference(key: .lastVersionLaunched, storage: store)
|
||||
_seenInvites = UserPreference(key: .seenInvites, defaultValue: [], storage: store)
|
||||
_hasSeenNewSoundBanner = UserPreference(key: .hasSeenNewSoundBanner, defaultValue: true, storage: store)
|
||||
|
||||
@@ -19,7 +19,7 @@ class RemotePreference<T: Equatable> {
|
||||
var publisher: CurrentValuePublisher<T, Never> {
|
||||
subject.asCurrentValuePublisher()
|
||||
}
|
||||
|
||||
|
||||
var isRemotelyConfigured: Bool {
|
||||
subject.value != defaultValue
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ final class UserPreference<T: Codable> {
|
||||
private var remoteKey: String {
|
||||
"\(Self.remotePrefix)\(key)"
|
||||
}
|
||||
|
||||
|
||||
private var keyedStorage: any KeyedStorage<T>
|
||||
private let defaultValue: T
|
||||
private let subject: PassthroughSubject<T, Never> = .init()
|
||||
@@ -84,7 +84,7 @@ final class UserPreference<T: Codable> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var projectedValue: AnyPublisher<T, Never> {
|
||||
subject
|
||||
.prepend(wrappedValue)
|
||||
@@ -97,7 +97,7 @@ final class UserPreference<T: Codable> {
|
||||
extension UserPreference {
|
||||
convenience init(key: any PreferenceKeyable, defaultValue: T, storage backingStorage: UserDefaultsProtocol, mode: Mode = .localOverRemote) {
|
||||
let storage: any KeyedStorage<T> = UserDefaultsStorage(userDefaults: backingStorage)
|
||||
|
||||
|
||||
self.init(key: key, defaultValue: defaultValue, keyedStorage: storage, mode: mode)
|
||||
}
|
||||
|
||||
|
||||
@@ -9,36 +9,36 @@ import Foundation
|
||||
|
||||
public final class VolatileUserDefaults: UserDefaultsProtocol, Sendable {
|
||||
private let lock = NSLock()
|
||||
|
||||
|
||||
private nonisolated(unsafe) var _storage: [String: Any]
|
||||
public private(set) var storage: [String: Any] {
|
||||
get { lock.withLock { _storage } }
|
||||
set { lock.withLock { _storage = newValue } }
|
||||
}
|
||||
|
||||
|
||||
public init(initialValues: [String: Any] = [:]) {
|
||||
lock.lock()
|
||||
defer { lock.unlock() }
|
||||
|
||||
|
||||
_storage = initialValues
|
||||
}
|
||||
|
||||
|
||||
public func data(forKey key: String) -> Data? {
|
||||
storage[key] as? Data
|
||||
}
|
||||
|
||||
|
||||
public func object(forKey key: String) -> Any? {
|
||||
storage[key]
|
||||
}
|
||||
|
||||
|
||||
public func removeObject(forKey key: String) {
|
||||
storage.removeValue(forKey: key)
|
||||
}
|
||||
|
||||
|
||||
public func set(_ value: Any?, forKey key: String) {
|
||||
storage[key] = value
|
||||
}
|
||||
|
||||
|
||||
public func reset() {
|
||||
storage = [:]
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class WindowManager: SecureWindowManagerProtocol {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var windows: [UIWindow] {
|
||||
[mainWindow, overlayWindow, globalSearchWindow, alternateWindow]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user