Add an app setting to disable rendering the chrome around the app logo/brand.

This commit is contained in:
Stefan Ceriu
2025-09-19 14:32:12 +03:00
committed by Stefan Ceriu
parent ab41783c4d
commit 94db3adf3a
10 changed files with 41 additions and 27 deletions
@@ -108,6 +108,7 @@ final class AppSettings {
// swiftlint:disable:next function_parameter_count // swiftlint:disable:next function_parameter_count
func override(accountProviders: [String], func override(accountProviders: [String],
allowOtherAccountProviders: Bool, allowOtherAccountProviders: Bool,
hideBrandChrome: Bool,
pushGatewayBaseURL: URL, pushGatewayBaseURL: URL,
oidcRedirectURL: URL, oidcRedirectURL: URL,
websiteURL: URL, websiteURL: URL,
@@ -126,6 +127,7 @@ final class AppSettings {
mapTilerConfiguration: MapTilerConfiguration) { mapTilerConfiguration: MapTilerConfiguration) {
self.accountProviders = accountProviders self.accountProviders = accountProviders
self.allowOtherAccountProviders = allowOtherAccountProviders self.allowOtherAccountProviders = allowOtherAccountProviders
self.hideBrandChrome = hideBrandChrome
self.pushGatewayBaseURL = pushGatewayBaseURL self.pushGatewayBaseURL = pushGatewayBaseURL
self.oidcRedirectURL = oidcRedirectURL self.oidcRedirectURL = oidcRedirectURL
self.websiteURL = websiteURL self.websiteURL = websiteURL
@@ -164,6 +166,8 @@ final class AppSettings {
private(set) var accountProviders = ["matrix.org"] private(set) var accountProviders = ["matrix.org"]
/// Whether or not the user is allowed to manually enter their own account provider or must select from one of `defaultAccountProviders`. /// Whether or not the user is allowed to manually enter their own account provider or must select from one of `defaultAccountProviders`.
private(set) var allowOtherAccountProviders = true private(set) var allowOtherAccountProviders = true
/// Whether the components surrounding the app brand/logo should be hidden or not
private(set) var hideBrandChrome = false
/// The task identifier used for background app refresh. Also used in main target's the Info.plist /// The task identifier used for background app refresh. Also used in main target's the Info.plist
let backgroundAppRefreshTaskIdentifier = "io.element.elementx.background.refresh" let backgroundAppRefreshTaskIdentifier = "io.element.elementx.background.refresh"
@@ -218,7 +218,7 @@ class AppLockFlowCoordinator: CoordinatorProtocol {
/// Displays the unlock flow with the app's placeholder view to hide obscure the view hierarchy in the app switcher. /// Displays the unlock flow with the app's placeholder view to hide obscure the view hierarchy in the app switcher.
private func showPlaceholder() { private func showPlaceholder() {
navigationCoordinator.setRootCoordinator(PlaceholderScreenCoordinator(showsBackgroundGradient: true), animated: false) navigationCoordinator.setRootCoordinator(PlaceholderScreenCoordinator(hideBrandChrome: false), animated: false)
actionsSubject.send(.lockApp) actionsSubject.send(.lockApp)
} }
@@ -37,6 +37,8 @@ struct AuthenticationStartScreenViewState: BindableState {
let showCreateAccountButton: Bool let showCreateAccountButton: Bool
let showQRCodeLoginButton: Bool let showQRCodeLoginButton: Bool
let hideBrandChrome: Bool
var bindings = AuthenticationStartScreenViewStateBindings() var bindings = AuthenticationStartScreenViewStateBindings()
var loginButtonTitle: String { var loginButtonTitle: String {
@@ -42,17 +42,20 @@ class AuthenticationStartScreenViewModel: AuthenticationStartScreenViewModelType
// The assumption here being that if you're running a custom app, your users will already be created. // The assumption here being that if you're running a custom app, your users will already be created.
AuthenticationStartScreenViewState(serverName: appSettings.accountProviders.count == 1 ? appSettings.accountProviders[0] : nil, AuthenticationStartScreenViewState(serverName: appSettings.accountProviders.count == 1 ? appSettings.accountProviders[0] : nil,
showCreateAccountButton: false, showCreateAccountButton: false,
showQRCodeLoginButton: isQRCodeScanningSupported) showQRCodeLoginButton: isQRCodeScanningSupported,
hideBrandChrome: appSettings.hideBrandChrome)
} else if let provisioningParameters { } else if let provisioningParameters {
// We only show the "Sign in to …" button when using a provisioning link. // We only show the "Sign in to …" button when using a provisioning link.
AuthenticationStartScreenViewState(serverName: provisioningParameters.accountProvider, AuthenticationStartScreenViewState(serverName: provisioningParameters.accountProvider,
showCreateAccountButton: false, showCreateAccountButton: false,
showQRCodeLoginButton: false) showQRCodeLoginButton: false,
hideBrandChrome: appSettings.hideBrandChrome)
} else { } else {
// The default configuration. // The default configuration.
AuthenticationStartScreenViewState(serverName: nil, AuthenticationStartScreenViewState(serverName: nil,
showCreateAccountButton: appSettings.showCreateAccountButton, showCreateAccountButton: appSettings.showCreateAccountButton,
showQRCodeLoginButton: isQRCodeScanningSupported) showQRCodeLoginButton: isQRCodeScanningSupported,
hideBrandChrome: appSettings.hideBrandChrome)
} }
super.init(initialViewState: initialViewState) super.init(initialViewState: initialViewState)
@@ -62,23 +62,25 @@ struct AuthenticationStartScreen: View {
if verticalSizeClass == .regular { if verticalSizeClass == .regular {
Spacer() Spacer()
AuthenticationStartLogo(isOnGradient: true) AuthenticationStartLogo(isOnGradient: !context.viewState.hideBrandChrome)
} }
Spacer() Spacer()
VStack(spacing: 8) { if !context.viewState.hideBrandChrome {
Text(L10n.screenOnboardingWelcomeTitle) VStack(spacing: 8) {
.font(.compound.headingLGBold) Text(L10n.screenOnboardingWelcomeTitle)
.foregroundColor(.compound.textPrimary) .font(.compound.headingLGBold)
.multilineTextAlignment(.center) .foregroundColor(.compound.textPrimary)
Text(L10n.screenOnboardingWelcomeMessage(InfoPlistReader.main.productionAppName)) .multilineTextAlignment(.center)
.font(.compound.bodyLG) Text(L10n.screenOnboardingWelcomeMessage(InfoPlistReader.main.productionAppName))
.foregroundColor(.compound.textSecondary) .font(.compound.bodyLG)
.multilineTextAlignment(.center) .foregroundColor(.compound.textSecondary)
.multilineTextAlignment(.center)
}
.padding()
.fixedSize(horizontal: false, vertical: true)
} }
.padding()
.fixedSize(horizontal: false, vertical: true)
Spacer() Spacer()
} }
@@ -8,26 +8,26 @@
import SwiftUI import SwiftUI
class PlaceholderScreenCoordinator: CoordinatorProtocol { class PlaceholderScreenCoordinator: CoordinatorProtocol {
private let showsBackgroundGradient: Bool private let hideBrandChrome: Bool
init(showsBackgroundGradient: Bool = false) { init(hideBrandChrome: Bool = true) {
self.showsBackgroundGradient = showsBackgroundGradient self.hideBrandChrome = hideBrandChrome
} }
func toPresentable() -> AnyView { func toPresentable() -> AnyView {
AnyView(PlaceholderScreen(showsBackgroundGradient: showsBackgroundGradient)) AnyView(PlaceholderScreen(hideBrandChrome: hideBrandChrome))
} }
} }
/// The screen shown in split view when the detail has no content. /// The screen shown in split view when the detail has no content.
struct PlaceholderScreen: View { struct PlaceholderScreen: View {
let showsBackgroundGradient: Bool let hideBrandChrome: Bool
var body: some View { var body: some View {
AuthenticationStartLogo(isOnGradient: showsBackgroundGradient) AuthenticationStartLogo(isOnGradient: !hideBrandChrome)
.frame(maxWidth: .infinity, maxHeight: .infinity) .frame(maxWidth: .infinity, maxHeight: .infinity)
.background { .background {
if showsBackgroundGradient { if !hideBrandChrome {
AuthenticationStartScreenBackgroundImage() AuthenticationStartScreenBackgroundImage()
} }
} }
@@ -40,10 +40,10 @@ struct PlaceholderScreen: View {
struct PlaceholderScreen_Previews: PreviewProvider, TestablePreview { struct PlaceholderScreen_Previews: PreviewProvider, TestablePreview {
static var previews: some View { static var previews: some View {
PlaceholderScreen(showsBackgroundGradient: false) PlaceholderScreen(hideBrandChrome: true)
.previewDisplayName("Screen") .previewDisplayName("Screen")
PlaceholderScreen(showsBackgroundGradient: true) PlaceholderScreen(hideBrandChrome: false)
.previewDisplayName("With background") .previewDisplayName("With background")
NavigationSplitView { NavigationSplitView {
@@ -53,7 +53,7 @@ struct PlaceholderScreen_Previews: PreviewProvider, TestablePreview {
} }
} }
} detail: { } detail: {
PlaceholderScreen(showsBackgroundGradient: false) PlaceholderScreen(hideBrandChrome: true)
} }
.previewDisplayName("Split View") .previewDisplayName("Split View")
.previewInterfaceOrientation(.landscapeLeft) .previewInterfaceOrientation(.landscapeLeft)
@@ -127,6 +127,7 @@ class MockScreen: Identifiable {
let accountProviders = id == .singleProviderAuthenticationFlow ? ["example.com"] : ["guest.example.com", "example.com"] let accountProviders = id == .singleProviderAuthenticationFlow ? ["example.com"] : ["guest.example.com", "example.com"]
appSettings.override(accountProviders: accountProviders, appSettings.override(accountProviders: accountProviders,
allowOtherAccountProviders: false, allowOtherAccountProviders: false,
hideBrandChrome: false,
pushGatewayBaseURL: appSettings.pushGatewayBaseURL, pushGatewayBaseURL: appSettings.pushGatewayBaseURL,
oidcRedirectURL: appSettings.oidcRedirectURL, oidcRedirectURL: appSettings.oidcRedirectURL,
websiteURL: appSettings.websiteURL, websiteURL: appSettings.websiteURL,
@@ -159,6 +159,7 @@ class AuthenticationStartScreenViewModelTests: XCTestCase {
private func setAllowedAccountProviders(_ providers: [String]) { private func setAllowedAccountProviders(_ providers: [String]) {
appSettings.override(accountProviders: providers, appSettings.override(accountProviders: providers,
allowOtherAccountProviders: false, allowOtherAccountProviders: false,
hideBrandChrome: false,
pushGatewayBaseURL: appSettings.pushGatewayBaseURL, pushGatewayBaseURL: appSettings.pushGatewayBaseURL,
oidcRedirectURL: appSettings.oidcRedirectURL, oidcRedirectURL: appSettings.oidcRedirectURL,
websiteURL: appSettings.websiteURL, websiteURL: appSettings.websiteURL,
@@ -311,6 +311,7 @@ class ServerConfirmationScreenViewModelTests: XCTestCase {
if restrictedFlow { if restrictedFlow {
appSettings.override(accountProviders: ["matrix.org", "beta.matrix.org"], appSettings.override(accountProviders: ["matrix.org", "beta.matrix.org"],
allowOtherAccountProviders: false, allowOtherAccountProviders: false,
hideBrandChrome: false,
pushGatewayBaseURL: appSettings.pushGatewayBaseURL, pushGatewayBaseURL: appSettings.pushGatewayBaseURL,
oidcRedirectURL: appSettings.oidcRedirectURL, oidcRedirectURL: appSettings.oidcRedirectURL,
websiteURL: appSettings.websiteURL, websiteURL: appSettings.websiteURL,