diff --git a/ElementX/Resources/Localizations/en.lproj/Letro.strings b/ElementX/Resources/Localizations/en.lproj/Letro.strings index 3e16ab116..12c0f18c8 100644 --- a/ElementX/Resources/Localizations/en.lproj/Letro.strings +++ b/ElementX/Resources/Localizations/en.lproj/Letro.strings @@ -154,6 +154,7 @@ "screen_room_timeline_tombstoned_room_message" = "This silo has been replaced and is no longer active"; "screen_room_timeline_upgraded_room_message" = "This silo is a continuation of another silo"; "screen_roomlist_a11y_create_message" = "Create a new conversation or silo"; +"screen_roomlist_empty_title" = ""; "screen_roomlist_filter_people" = "Directs"; "screen_roomlist_filter_rooms" = "Silos"; "screen_roomlist_filter_rooms_empty_state_title" = "You’re not in any silo yet"; @@ -183,7 +184,7 @@ "screen_space_announcement_title" = "Introducing Workspaces"; "screen_space_empty_state_title" = "Add your first silo"; "screen_space_list_description" = "Workspaces you have created or joined."; -"screen_space_list_empty_state_title" = "Create spaces to organize silos"; +"screen_space_list_empty_state_title" = "Create workspaces to organize your desk"; "screen_space_list_parent_space" = "%1$@ workspace"; "screen_space_list_title" = "Workspaces"; "screen_space_remove_rooms_confirmation_content" = "Removing a silo will not affect the silo access. To change the access go to Silo info > Privacy & security."; diff --git a/ElementX/Resources/Localizations/en.lproj/Letro.stringsdict b/ElementX/Resources/Localizations/en.lproj/Letro.stringsdict index 52d6c493f..56f065596 100644 --- a/ElementX/Resources/Localizations/en.lproj/Letro.stringsdict +++ b/ElementX/Resources/Localizations/en.lproj/Letro.stringsdict @@ -1,286 +1,118 @@ - + - - - - common_spaces - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - %1$d Workspace - - - other - - - %1$d Workspaces - - - - - screen_leave_space_submit - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - Leave %1$d silo and space - - - other - - - Leave %1$d silos and space - - - - - common_rooms - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - %1$d Silo - - - other - - - %1$d Silos - - - - - notification_unread_notified_messages_in_room_rooms - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - %d silo - - - other - - - %d silos - - - - - screen_room_multiple_knock_requests_title - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - %1$@ +%2$d other want to join this silo - - - other - - - %1$@ +%2$d others want to join this silo - - - - - screen_room_timeline_state_changes - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - %1$d change - - - other - - - %1$d changes - - - - - screen_space_remove_rooms_confirmation_title - - - - NSStringLocalizedFormatKey - - - %#@COUNT@ - - - COUNT - - - - NSStringFormatSpecTypeKey - - - NSStringPluralRuleType - - - NSStringFormatValueTypeKey - - - d - - - one - - - Remove %1$d silo from %2$@ - - - other - - - Remove %1$d silos from %2$@ - - - - + + + common_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Silo + other + %1$d Silos + + + common_spaces + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d Workspace + other + %1$d Workspaces + + + notification_unread_notified_messages_in_room_rooms + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %d silo + other + %d silos + + + screen_leave_space_submit + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Leave %1$d silo and space + other + Leave %1$d silos and space + + + screen_room_multiple_knock_requests_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$@ +%2$d other want to join this silo + other + %1$@ +%2$d others want to join this silo + + + screen_room_timeline_state_changes + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + %1$d change + other + %1$d changes + + + screen_space_remove_rooms_confirmation_title + + NSStringLocalizedFormatKey + %#@COUNT@ + COUNT + + NSStringFormatSpecTypeKey + NSStringPluralRuleType + NSStringFormatValueTypeKey + d + one + Remove %1$d silo from %2$@ + other + Remove %1$d silos from %2$@ + + + diff --git a/ElementX/Sources/Application/Settings/AppSettings.swift b/ElementX/Sources/Application/Settings/AppSettings.swift index ba61f7900..9f852356e 100644 --- a/ElementX/Sources/Application/Settings/AppSettings.swift +++ b/ElementX/Sources/Application/Settings/AppSettings.swift @@ -224,15 +224,15 @@ final class AppSettings { /// A URL where users can go read more about identity pinning violations private(set) var identityPinningViolationDetailsURL: URL = "https://letro.com/help#encryption18" /// A URL describing how history sharing works - private(set) var historySharingDetailsURL: URL = "https://letro.com/en/help#e2ee-history-sharing" + private(set) var historySharingDetailsURL: URL = "https://letro.com/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"] + private(set) var elementWebHosts = ["app.letro.com", "staging.letro.com", "develop.letro.com"] /// The domain that account provisioning links will be hosted on - used for handling the links. - private(set) var accountProvisioningHost = "mobile.element.io" + private(set) var accountProvisioningHost = "mobile.letro.com" /// The App Store URL for Element Pro, shown to the user when a homeserver requires that app. /// **Note:** This property isn't overridable as it in unexpected for forks to come across the error (or to even have a "Pro" app). - let elementProAppStoreURL: URL = "https://apps.apple.com/app/element-pro-for-work/id6502951615" + let elementProAppStoreURL: URL = "https://apps.apple.com/app/letro-pro/id6758909629" @UserPreference(key: UserDefaultsKeys.appAppearance, defaultValue: .system, storageType: .userDefaults(store)) var appAppearance: AppAppearance @@ -279,7 +279,7 @@ final class AppSettings { #endif } - private(set) var pushGatewayBaseURL: URL = "https://matrix.org" + private(set) var pushGatewayBaseURL: URL = "https://letro.com" var pushGatewayNotifyEndpoint: URL { pushGatewayBaseURL.appending(path: "_matrix/push/v1/notify") } @@ -318,14 +318,14 @@ final class AppSettings { 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 - private(set) var bugReportApplicationID = "element-x-ios" + private(set) var bugReportApplicationID = "letro" // MARK: - Analytics /// The configuration to use for analytics. Set to `nil` to disable analytics. let analyticsConfiguration: AnalyticsConfiguration? = AppSettings.makeAnalyticsConfiguration() /// The URL to open with more information about analytics terms. When this is `nil` the "Learn more" link will be hidden. - private(set) var analyticsTermsURL: URL? = "https://element.io/cookie-policy" + private(set) var analyticsTermsURL: URL? = "https://letro.com/cookie-policy" /// Whether or not there the app is able ask for user consent to enable analytics or sentry reporting. var canPromptForAnalytics: Bool { analyticsConfiguration != nil || bugReportSentryURL != nil diff --git a/ElementX/Sources/Letro/Extensions/CompoundExtensions.swift b/ElementX/Sources/Letro/Extensions/CompoundExtensions.swift index 60f433d82..45c788768 100644 --- a/ElementX/Sources/Letro/Extensions/CompoundExtensions.swift +++ b/ElementX/Sources/Letro/Extensions/CompoundExtensions.swift @@ -20,28 +20,42 @@ enum CompoundExtensions { extension CompoundColors { @MainActor func applyLetroOverrides() { - override(\.gradientSubtleStop1, with: CompoundCoreColorTokens.alphaOrange500) - override(\.gradientSubtleStop2, with: CompoundCoreColorTokens.alphaOrange400) - override(\.gradientSubtleStop3, with: CompoundCoreColorTokens.alphaOrange300) - override(\.gradientSubtleStop4, with: CompoundCoreColorTokens.alphaOrange200) - override(\.gradientSubtleStop5, with: CompoundCoreColorTokens.alphaOrange100) - override(\.gradientSubtleStop6, with: CompoundCoreColorTokens.transparent) - override(\.iconAccentTertiary, with: CompoundCoreColorTokens.orange800) - override(\.bgAccentRest, with: CompoundCoreColorTokens.orange900) + override(\.gradientActionStop1, with: .letroGradient1) + override(\.gradientActionStop2, with: .letroGradient2) + override(\.gradientActionStop3, with: .letroGradient3) + override(\.gradientActionStop4, with: .letroGradient5) + override(\.gradientSubtleStop1, with: .letroGradient1.opacity(0.33)) + override(\.gradientSubtleStop2, with: .letroGradient2.opacity(0.22)) + override(\.gradientSubtleStop3, with: .letroGradient3.opacity(0.11)) + override(\.gradientSubtleStop4, with: .letroGradient4.opacity(0.07)) + override(\.gradientSubtleStop5, with: .letroGradient5.opacity(0.04)) + override(\.bgActionPrimaryRest, with: .letroPrimary) + override(\.bgActionPrimaryPressed, with: .letroGradient1) + override(\.bgActionPrimaryDisabled, with: .letroGray.opacity(0.4)) + override(\.iconAccentTertiary, with: .letroPrimary) + override(\.bgAccentRest, with: .letroPrimary) + override(\.textActionPrimary, with: .letroPrimary) } } extension CompoundUIColors { @MainActor func applyLetroOverrides() { - override(\.gradientSubtleStop1, with: CompoundCoreUIColorTokens.alphaOrange500) - override(\.gradientSubtleStop2, with: CompoundCoreUIColorTokens.alphaOrange400) - override(\.gradientSubtleStop3, with: CompoundCoreUIColorTokens.alphaOrange300) - override(\.gradientSubtleStop4, with: CompoundCoreUIColorTokens.alphaOrange200) - override(\.gradientSubtleStop5, with: CompoundCoreUIColorTokens.alphaOrange100) - override(\.gradientSubtleStop6, with: CompoundCoreUIColorTokens.transparent) - override(\.iconAccentTertiary, with: CompoundCoreUIColorTokens.orange800) - override(\.bgAccentRest, with: CompoundCoreUIColorTokens.orange900) + override(\.gradientActionStop1, with: .letroGradient1) + override(\.gradientActionStop2, with: .letroGradient2) + override(\.gradientActionStop3, with: .letroGradient3) + override(\.gradientActionStop4, with: .letroGradient5) + override(\.gradientSubtleStop1, with: .letroGradient1.withAlphaComponent(0.33)) + override(\.gradientSubtleStop2, with: .letroGradient2.withAlphaComponent(0.22)) + override(\.gradientSubtleStop3, with: .letroGradient3.withAlphaComponent(0.11)) + override(\.gradientSubtleStop4, with: .letroGradient4.withAlphaComponent(0.07)) + override(\.gradientSubtleStop5, with: .letroGradient5.withAlphaComponent(0.04)) + override(\.bgActionPrimaryRest, with: .letroPrimary) + override(\.bgActionPrimaryPressed, with: .letroGradient1) + override(\.bgActionPrimaryDisabled, with: .letroGray.withAlphaComponent(0.4)) + override(\.iconAccentTertiary, with: .letroPrimary) + override(\.bgAccentRest, with: .letroPrimary) + override(\.textActionPrimary, with: .letroPrimary) } } diff --git a/ElementX/Sources/Letro/Extensions/SwiftUIExtensions.swift b/ElementX/Sources/Letro/Extensions/SwiftUIExtensions.swift index 462545d75..8d9c6534d 100644 --- a/ElementX/Sources/Letro/Extensions/SwiftUIExtensions.swift +++ b/ElementX/Sources/Letro/Extensions/SwiftUIExtensions.swift @@ -9,8 +9,15 @@ import SwiftUI import UIKit public extension Color { - static let letroPrimary = Color(hex: 0xC20000) + static let letroPrimary = Color(hex: 0xF32D1B) + static let letroSecondary = Color(hex: 0xF9BC15) static let letroGray = Color(hex: 0xB1B3B9) + static let letroGradient1 = Color(hex: 0xCB2000) + static let letroGradient2 = Color(hex: 0xD33900) + static let letroGradient3 = Color(hex: 0xDD5A00) + static let letroGradient4 = Color(hex: 0xE98200) + static let letroGradient5 = Color(hex: 0xF7B000) + init(hex: UInt32) { self.init(.sRGB, red: Double((hex >> 16) & 0xFF) / 255.0, green: Double((hex >> 8) & 0xFF) / 255.0, blue: Double(hex & 0xFF) / 255.0, opacity: 1) @@ -18,8 +25,14 @@ public extension Color { } public extension UIColor { - static let letroPrimary = UIColor(hex: 0xC20000) + static let letroPrimary = UIColor(hex: 0xF32D1B) + static let letroSecondary = UIColor(hex: 0xF9BC15) static let letroGray = UIColor(hex: 0xB1B3B9) + static let letroGradient1 = UIColor(hex: 0xCB2000) + static let letroGradient2 = UIColor(hex: 0xD33900) + static let letroGradient3 = UIColor(hex: 0xDD5A00) + static let letroGradient4 = UIColor(hex: 0xE98200) + static let letroGradient5 = UIColor(hex: 0xF7B000) convenience init(hex: UInt32) { self.init(red: CGFloat((hex >> 16) & 0xFF) / 255.0, green: CGFloat((hex >> 8) & 0xFF) / 255.0, blue: CGFloat(hex & 0xFF) / 255.0, alpha: 1) diff --git a/ElementX/SupportingFiles/Info.plist b/ElementX/SupportingFiles/Info.plist index d0a8ac9a7..714655422 100644 --- a/ElementX/SupportingFiles/Info.plist +++ b/ElementX/SupportingFiles/Info.plist @@ -69,6 +69,8 @@ To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. NSFaceIDUsageDescription Face ID is used to access your app. + NSLocationAlwaysAndWhenInUseUsageDescription + To share your live location, $(APP_DISPLAY_NAME) needs location access when the app is in the background. NSLocationWhenInUseUsageDescription Grant location access so that $(APP_DISPLAY_NAME) can share your location. NSMicrophoneUsageDescription diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index ded680685..a8f99e15c 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -88,6 +88,7 @@ targets: NSCameraUsageDescription: To take pictures or videos and send them as a message $(APP_DISPLAY_NAME) needs access to the camera. NSMicrophoneUsageDescription: To record and send messages with audio, $(APP_DISPLAY_NAME) needs to access the microphone. NSPhotoLibraryAddUsageDescription: This lets you save images and videos to your photo library. + NSLocationAlwaysAndWhenInUseUsageDescription: To share your live location, $(APP_DISPLAY_NAME) needs location access when the app is in the background. NSLocationWhenInUseUsageDescription: Grant location access so that $(APP_DISPLAY_NAME) can share your location. NSFaceIDUsageDescription: Face ID is used to access your app. UIBackgroundModes: [ diff --git a/compound-ios/Sources/Compound/BaseStyles/CompoundButtonStyle.swift b/compound-ios/Sources/Compound/BaseStyles/CompoundButtonStyle.swift index 680cb3645..d3dd229c5 100644 --- a/compound-ios/Sources/Compound/BaseStyles/CompoundButtonStyle.swift +++ b/compound-ios/Sources/Compound/BaseStyles/CompoundButtonStyle.swift @@ -138,7 +138,7 @@ public struct CompoundButtonStyle: ButtonStyle { Capsule().strokeBorder(strokeColor(configuration: configuration)) } case .primary: - Capsule().fill(fillColor(configuration: configuration)) + makePrimaryBackground(configuration: configuration) case .secondary: Capsule().strokeBorder(strokeColor(configuration: configuration)) case .tertiary: @@ -148,6 +148,20 @@ public struct CompoundButtonStyle: ButtonStyle { } } + // Letro: custom action buttons + @ViewBuilder + private func makePrimaryBackground(configuration: Self.Configuration) -> some View { + if !isEnabled || configuration.role == .destructive { + Capsule().fill(fillColor(configuration: configuration)) + } else { + Capsule() + .fill(LinearGradient(gradient: .compound.action, + startPoint: .bottomLeading, + endPoint: .topTrailing)) + .opacity(configuration.isPressed ? pressedOpacity : 1) + } + } + private var contentShape: AnyShape { switch kind { case .super, .primary, .secondary, .tertiary: