Add a feature flag for spaces. (#4429)

* Remove the huge conditional compilation block on AppSettings.

It is still required for the ElementCallBaseURL however.

* Add a feature flag for spaces.
This commit is contained in:
Doug
2025-08-22 13:47:23 +01:00
committed by GitHub
parent 487fd90bdb
commit 4bd846118a
15 changed files with 147 additions and 80 deletions
@@ -0,0 +1,16 @@
//
// Copyright 2022-2024 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 Foundation
/// A type that represents how to set up the analytics module in the app.
struct AnalyticsConfiguration {
/// The host to use for PostHog analytics.
let host: String
/// The public key for submitting analytics.
let apiKey: String
}
@@ -0,0 +1,14 @@
//
// Copyright 2023, 2024 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 Foundation
enum AnalyticsConsentState: String, Codable {
case optedOut
case optedIn
case unknown
}
@@ -0,0 +1,26 @@
//
// Copyright 2023, 2024 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 SwiftUI
/// Used to specify the user's app specific appearance preference
enum AppAppearance: CaseIterable, Codable {
case system
case dark
case light
var interfaceStyle: UIUserInterfaceStyle {
switch self {
case .light:
return .light
case .dark:
return .dark
case .system:
return .unspecified
}
}
}
@@ -5,7 +5,7 @@
// Please see LICENSE files in the repository root for full details.
//
#if canImport(EmbeddedElementCall)
#if IS_MAIN_APP
import EmbeddedElementCall
#endif
@@ -59,6 +59,7 @@ final class AppSettings {
case enableKeyShareOnInvite
case knockingEnabled
case threadsEnabled
case spacesEnabled
case developerOptionsEnabled
// Doug's tweaks 🔧
@@ -80,8 +81,6 @@ final class AppSettings {
return apps.contains(InfoPlistReader.main.baseBundleIdentifier)
#endif
}()
#if IS_MAIN_APP
static func resetAllSettings() {
MXLog.warning("Resetting the AppSettings.")
@@ -216,13 +215,13 @@ final class AppSettings {
/// The redirect URL used for OIDC. This no longer uses universal links so we don't need the bundle ID to avoid conflicts between Element X, Nightly and PR builds.
private(set) var oidcRedirectURL: URL = "https://element.io/oidc/login"
private(set) lazy var oidcConfiguration = OIDCConfigurationProxy(clientName: InfoPlistReader.main.bundleDisplayName,
redirectURI: oidcRedirectURL,
clientURI: websiteURL,
logoURI: logoURL,
tosURI: acceptableUseURL,
policyURI: privacyURL,
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString })
private(set) lazy var oidcConfiguration = OIDCConfiguration(clientName: InfoPlistReader.main.bundleDisplayName,
redirectURI: oidcRedirectURL,
clientURI: websiteURL,
logoURI: logoURL,
tosURI: acceptableUseURL,
policyURI: privacyURL,
staticRegistrations: oidcStaticRegistrations.mapKeys { $0.absoluteString })
/// Whether or not the Create Account button is shown on the start screen.
///
@@ -247,13 +246,25 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.enableInAppNotifications, defaultValue: true, storageType: .userDefaults(store))
var enableInAppNotifications
@UserPreference(key: UserDefaultsKeys.hideQuietNotificationAlerts, defaultValue: false, storageType: .userDefaults(store))
var hideQuietNotificationAlerts
/// Tag describing which set of device specific rules a pusher executes.
@UserPreference(key: UserDefaultsKeys.pusherProfileTag, storageType: .userDefaults(store))
var pusherProfileTag: String?
// MARK: - Logging
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: LogLevel.info, storageType: .userDefaults(store))
var logLevel
@UserPreference(key: UserDefaultsKeys.traceLogPacks, defaultValue: [], storageType: .userDefaults(store))
var traceLogPacks: Set<TraceLogPack>
// MARK: - Bug report
let bugReportRageshakeURL: RemotePreference<RageshakeConfiguration> = .init(Secrets.rageshakeURL.map { .url(URL(string: $0)!) } ?? .disabled) // swiftlint:disable:this force_unwrapping
let bugReportSentryURL: URL? = Secrets.sentryDSN.map { URL(string: $0)! } // swiftlint:disable:this force_unwrapping
let bugReportSentryRustURL: URL? = Secrets.sentryRustDSN.map { URL(string: $0)! } // swiftlint:disable:this force_unwrapping
/// The name allocated by the bug report server
@@ -307,8 +318,10 @@ final class AppSettings {
// MARK: - Element Call
#if IS_MAIN_APP
// swiftlint:disable:next force_unwrapping
let elementCallBaseURL: URL = EmbeddedElementCall.appURL!
#endif
// These are publicly availble on https://call.element.io so we don't neeed to treat them as secrets
let elementCallPosthogAPIHost = "https://posthog-element-call.element.io"
@@ -347,24 +360,6 @@ final class AppSettings {
@UserPreference(key: UserDefaultsKeys.lowPriorityFilterEnabled, defaultValue: false, storageType: .userDefaults(store))
var lowPriorityFilterEnabled
@UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store))
var knockingEnabled
@UserPreference(key: UserDefaultsKeys.developerOptionsEnabled, defaultValue: isDevelopmentBuild, storageType: .userDefaults(store))
var developerOptionsEnabled
#endif
// MARK: - Shared
@UserPreference(key: UserDefaultsKeys.logLevel, defaultValue: LogLevel.info, storageType: .userDefaults(store))
var logLevel
@UserPreference(key: UserDefaultsKeys.traceLogPacks, defaultValue: [], storageType: .userDefaults(store))
var traceLogPacks: Set<TraceLogPack>
let bugReportRageshakeURL: RemotePreference<RageshakeConfiguration> = .init(Secrets.rageshakeURL.map { .url(URL(string: $0)!) } ?? .disabled) // swiftlint:disable:this force_unwrapping
/// Configuration to enable only signed device isolation mode for crypto. In this mode only devices signed by their owner will be considered in e2ee rooms.
@UserPreference(key: UserDefaultsKeys.enableOnlySignedDeviceIsolationMode, defaultValue: false, storageType: .userDefaults(store))
var enableOnlySignedDeviceIsolationMode
@@ -372,12 +367,18 @@ final class AppSettings {
/// Configuration to enable encrypted history sharing on invite, and accepting keys from inviters.
@UserPreference(key: UserDefaultsKeys.enableKeyShareOnInvite, defaultValue: false, storageType: .userDefaults(store))
var enableKeyShareOnInvite
@UserPreference(key: UserDefaultsKeys.knockingEnabled, defaultValue: false, storageType: .userDefaults(store))
var knockingEnabled
@UserPreference(key: UserDefaultsKeys.threadsEnabled, defaultValue: false, storageType: .userDefaults(store))
var threadsEnabled
@UserPreference(key: UserDefaultsKeys.hideQuietNotificationAlerts, defaultValue: false, storageType: .userDefaults(store))
var hideQuietNotificationAlerts
@UserPreference(key: UserDefaultsKeys.spacesEnabled, defaultValue: false, storageType: .userDefaults(store))
var spacesEnabled
@UserPreference(key: UserDefaultsKeys.developerOptionsEnabled, defaultValue: isDevelopmentBuild, storageType: .userDefaults(store))
var developerOptionsEnabled
}
extension AppSettings: CommonSettingsProtocol { }
@@ -0,0 +1,15 @@
//
// 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.
//
struct FrequentlyUsedEmoji: Codable, Hashable {
let count: UInt
let key: String
static func == (lhs: FrequentlyUsedEmoji, rhs: FrequentlyUsedEmoji) -> Bool {
lhs.key == rhs.key
}
}
@@ -0,0 +1,25 @@
//
// 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 Foundation
/// All of the configuration necessary to use MapTiler maps.
///
/// The style IDs need to be generated with the account that the API key belongs to. For more information read
/// [FORKING.md](https://github.com/element-hq/element-x-ios/blob/develop/docs/FORKING.md#setup-the-location-sharing)
struct MapTilerConfiguration {
let baseURL: URL
/// The API key for fetching map tiles. When not set, location sharing will be disabled and
/// any received locations will be shown in the timeline with a generic blurred map image.
let apiKey: String?
/// A MapLibre style ID for a light-mode map.
let lightStyleID: String
/// A MapLibre style ID for a dark-mode map.
let darkStyleID: String
var isEnabled: Bool { apiKey != nil }
}
@@ -0,0 +1,34 @@
//
// Copyright 2024 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 Foundation
struct OIDCConfiguration {
let clientName: String
let redirectURI: URL
let clientURI: URL
let logoURI: URL
let tosURI: URL
let policyURI: URL
let staticRegistrations: [String: String]
}
#if canImport(MatrixRustSDK)
import MatrixRustSDK
extension OIDCConfiguration {
var rustValue: OidcConfiguration {
OidcConfiguration(clientName: clientName,
redirectUri: redirectURI.absoluteString,
clientUri: clientURI.absoluteString,
logoUri: logoURI.absoluteString,
tosUri: tosURI.absoluteString,
policyUri: policyURI.absoluteString,
staticRegistrations: staticRegistrations)
}
}
#endif