diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 68dba9dbf..59f0f5f5c 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -210,7 +210,7 @@ 54C774874BED4A8FAD1F22FE /* AnalyticsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77B3D4950F1707E66E4A45A /* AnalyticsConfiguration.swift */; }; 564BF06B3E93D6DD55F903B2 /* CreateRoomCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C618CA2B6C8758B06C88013C /* CreateRoomCoordinator.swift */; }; 565868808A1DA565707394ED /* CurrentValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */; }; - 56B253546E15DE3E961A4C74 /* EqualIconWithLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C993E02E4A29204F1510D7A /* EqualIconWithLabelStyle.swift */; }; + 56B253546E15DE3E961A4C74 /* FixedIconSizeLabelStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9C993E02E4A29204F1510D7A /* FixedIconSizeLabelStyle.swift */; }; 56F0A22972A3BB519DA2261C /* HomeScreenViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24F5530B2212862FA4BEFF2D /* HomeScreenViewModelProtocol.swift */; }; 5770C4906668C6D3008A2AC9 /* SessionVerificationScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B5046BB295AEAFA6FB81655 /* SessionVerificationScreenModels.swift */; }; 5780E444F405AA1304E1C23E /* DeveloperOptionsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 38E521D6C2BF8DF0DFB35146 /* DeveloperOptionsScreen.swift */; }; @@ -779,7 +779,7 @@ 1222DB76B917EB8A55365BA5 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; 127A57D053CE8C87B5EFB089 /* Consumable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Consumable.swift; sourceTree = ""; }; 127C8472672A5BA09EF1ACF8 /* CurrentValuePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CurrentValuePublisher.swift; sourceTree = ""; }; - 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; path = IntegrationTests.xctestplan; sourceTree = ""; }; + 1304D9191300873EADA52D6E /* IntegrationTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = IntegrationTests.xctestplan; sourceTree = ""; }; 130ED565A078F7E0B59D9D25 /* UNTextInputNotificationResponse+Creator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UNTextInputNotificationResponse+Creator.swift"; sourceTree = ""; }; 13802897C7AFA360EA74C0B0 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = en; path = en.lproj/Localizable.stringsdict; sourceTree = ""; }; 1423AB065857FA546444DB15 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = ""; }; @@ -901,7 +901,7 @@ 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomProxyProtocol.swift; sourceTree = ""; }; 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineView.swift; sourceTree = ""; }; 47873756E45B46683D97DC32 /* LegalInformationScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegalInformationScreenModels.swift; sourceTree = ""; }; - 478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; name = DesignKit; path = DesignKit; sourceTree = SOURCE_ROOT; }; + 478BE8591BD13E908EF70C0C /* DesignKit */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DesignKit; sourceTree = SOURCE_ROOT; }; 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramePreferenceKey.swift; sourceTree = ""; }; 47EBB5D698CE9A25BB553A2D /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; 47F29139BC2A804CE5E0757E /* MediaUploadPreviewScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadPreviewScreenViewModel.swift; sourceTree = ""; }; @@ -1058,7 +1058,7 @@ 8D6094DEAAEB388E1AE118C6 /* MockRoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockRoomTimelineProvider.swift; sourceTree = ""; }; 8D8169443E5AC5FF71BFB3DB /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/Localizable.strings; sourceTree = ""; }; 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineStyle.swift; sourceTree = ""; }; - 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; path = UITests.xctestplan; sourceTree = ""; }; + 8E088F2A1B9EC529D3221931 /* UITests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UITests.xctestplan; sourceTree = ""; }; 8E1BBA73B611EDEEA6E20E05 /* InvitesScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenModels.swift; sourceTree = ""; }; 8EC57A32ABC80D774CC663DB /* SettingsScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenUITests.swift; sourceTree = ""; }; 8F61A0DD8243B395499C99A2 /* InvitesScreenUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InvitesScreenUITests.swift; sourceTree = ""; }; @@ -1098,7 +1098,7 @@ 9C5E81214D27A6B898FC397D /* ElementX.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ElementX.entitlements; sourceTree = ""; }; 9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationStackCoordinatorTests.swift; sourceTree = ""; }; 9C7F7DE62D33C6A26CBFCD72 /* IntegrationTests.xctest */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = wrapper.cfbundle; path = IntegrationTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 9C993E02E4A29204F1510D7A /* EqualIconWithLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EqualIconWithLabelStyle.swift; sourceTree = ""; }; + 9C993E02E4A29204F1510D7A /* FixedIconSizeLabelStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FixedIconSizeLabelStyle.swift; sourceTree = ""; }; 9CE3C90E487B255B735D73C8 /* RoomScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModel.swift; sourceTree = ""; }; 9E6D88E8AFFBF2C1D589C0FA /* UIConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIConstants.swift; sourceTree = ""; }; 9F85164F9475FF2867F71AAA /* RoomTimelineController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineController.swift; sourceTree = ""; }; @@ -1161,7 +1161,7 @@ B43456E73F8A2D52B69B9FB9 /* TemplateScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TemplateScreenViewModel.swift; sourceTree = ""; }; B590BD4507D4F0A377FDE01A /* LoadableAvatarImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadableAvatarImage.swift; sourceTree = ""; }; B5B243E7818E5E9F6A4EDC7A /* NoticeRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoticeRoomTimelineView.swift; sourceTree = ""; }; - B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; path = ConfettiScene.scn; sourceTree = ""; }; + B61C339A2FDDBD067FF6635C /* ConfettiScene.scn */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; path = ConfettiScene.scn; sourceTree = ""; }; B6311F21F911E23BE4DF51B4 /* ReadMarkerRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadMarkerRoomTimelineView.swift; sourceTree = ""; }; B6E89E530A8E92EC44301CA1 /* Bundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bundle.swift; sourceTree = ""; }; B7AE92E7BFF71797BDE1D261 /* MapTilerStyleBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapTilerStyleBuilder.swift; sourceTree = ""; }; @@ -1231,7 +1231,7 @@ CD6B0C4639E066915B5E6463 /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = ""; }; CDB3227C7A74B734924942E9 /* RoomSummaryProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomSummaryProvider.swift; sourceTree = ""; }; CEE0E6043EFCF6FD2A341861 /* TimelineReplyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineReplyView.swift; sourceTree = ""; }; - CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; path = UnitTests.xctestplan; sourceTree = ""; }; + CEE41494C837AA403A06A5D9 /* UnitTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = UnitTests.xctestplan; sourceTree = ""; }; CF48AF076424DBC1615C74AD /* AuthenticationServiceProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationServiceProxy.swift; sourceTree = ""; }; D06A27D9C70E0DCC1E199163 /* OnboardingBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingBackgroundView.swift; sourceTree = ""; }; D071F86CD47582B9196C9D16 /* UserDiscoverySection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDiscoverySection.swift; sourceTree = ""; }; @@ -1298,7 +1298,7 @@ ECF79FB25E2D4BD6F50CE7C9 /* RoomMembersListScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomMembersListScreenViewModel.swift; sourceTree = ""; }; ED044D00F2176681CC02CD54 /* HomeScreenRoomCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenRoomCell.swift; sourceTree = ""; }; ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineItemProtocol.swift; sourceTree = ""; }; - ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; path = message.caf; sourceTree = ""; }; + ED482057AE39D5C6D9C5F3D8 /* message.caf */ = {isa = PBXFileReference; lastKnownFileType = file; path = message.caf; sourceTree = ""; }; ED983D4DCA5AFA6E1ED96099 /* StateRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateRoomTimelineView.swift; sourceTree = ""; }; EDAA4472821985BF868CC21C /* ServerSelectionViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionViewModelTests.swift; sourceTree = ""; }; EE378083653EF0C9B5E9D580 /* EmoteRoomTimelineItemContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmoteRoomTimelineItemContent.swift; sourceTree = ""; }; @@ -3044,7 +3044,7 @@ isa = PBXGroup; children = ( 8872E9C5E91E9F2BFC4EBCCA /* AlignedScrollView.swift */, - 9C993E02E4A29204F1510D7A /* EqualIconWithLabelStyle.swift */, + 9C993E02E4A29204F1510D7A /* FixedIconSizeLabelStyle.swift */, 4798B3B7A1E8AE3901CEE8C6 /* FramePreferenceKey.swift */, 565F1B2B300597C616B37888 /* FullscreenDialog.swift */, 398817652FA8ABAE0A31AC6D /* ReadableFrameModifier.swift */, @@ -3952,7 +3952,7 @@ 8B1D5CE017EEC734CF5FE130 /* Encodable.swift in Sources */, 4C5A638DAA8AF64565BA4866 /* EncryptedRoomTimelineItem.swift in Sources */, B5903E48CF43259836BF2DBF /* EncryptedRoomTimelineView.swift in Sources */, - 56B253546E15DE3E961A4C74 /* EqualIconWithLabelStyle.swift in Sources */, + 56B253546E15DE3E961A4C74 /* FixedIconSizeLabelStyle.swift in Sources */, F78BAD28482A467287A9A5A3 /* EventBasedMessageTimelineItemProtocol.swift in Sources */, 02D8DF8EB7537EB4E9019DDB /* EventBasedTimelineItemProtocol.swift in Sources */, 63E46D18B91D08E15FC04125 /* ExpiringTaskRunner.swift in Sources */, diff --git a/ElementX/Resources/Localizations/en.lproj/Localizable.strings b/ElementX/Resources/Localizations/en.lproj/Localizable.strings index 6e8371bc3..3b19ec95a 100644 --- a/ElementX/Resources/Localizations/en.lproj/Localizable.strings +++ b/ElementX/Resources/Localizations/en.lproj/Localizable.strings @@ -14,6 +14,7 @@ "action_continue" = "Continue"; "action_copy" = "Copy"; "action_copy_link" = "Copy link"; +"action_copy_link_to_message" = "Copy link to message"; "action_create" = "Create"; "action_create_a_room" = "Create a room"; "action_decline" = "Decline"; @@ -109,6 +110,7 @@ "common_sticker" = "Sticker"; "common_success" = "Success"; "common_suggestions" = "Suggestions"; +"common_syncing" = "Syncing"; "common_third_party_notices" = "Third-party notices"; "common_topic" = "Topic"; "common_topic_placeholder" = "What is this room about?"; diff --git a/ElementX/Sources/Application/AppCoordinator.swift b/ElementX/Sources/Application/AppCoordinator.swift index 8f764890f..3cfc00b36 100644 --- a/ElementX/Sources/Application/AppCoordinator.swift +++ b/ElementX/Sources/Application/AppCoordinator.swift @@ -523,7 +523,7 @@ class AppCoordinator: AppCoordinatorProtocol, AuthenticationCoordinatorDelegate, let identifier = "StaleDataIndicator" - ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: identifier, type: .toast, title: L10n.commonLoading, persistent: true)) + ServiceLocator.shared.userIndicatorController.submitIndicator(.init(id: identifier, type: .toast(progress: .indeterminate), title: L10n.commonSyncing, persistent: true)) initialSyncObserver = userSession.clientProxy .callbacks diff --git a/ElementX/Sources/Generated/Strings.swift b/ElementX/Sources/Generated/Strings.swift index ff41a3097..dce40302d 100644 --- a/ElementX/Sources/Generated/Strings.swift +++ b/ElementX/Sources/Generated/Strings.swift @@ -40,6 +40,8 @@ public enum L10n { public static var actionCopy: String { return L10n.tr("Localizable", "action_copy") } /// Copy link public static var actionCopyLink: String { return L10n.tr("Localizable", "action_copy_link") } + /// Copy link to message + public static var actionCopyLinkToMessage: String { return L10n.tr("Localizable", "action_copy_link_to_message") } /// Create public static var actionCreate: String { return L10n.tr("Localizable", "action_create") } /// Create a room @@ -240,6 +242,8 @@ public enum L10n { public static var commonSuccess: String { return L10n.tr("Localizable", "common_success") } /// Suggestions public static var commonSuggestions: String { return L10n.tr("Localizable", "common_suggestions") } + /// Syncing + public static var commonSyncing: String { return L10n.tr("Localizable", "common_syncing") } /// Third-party notices public static var commonThirdPartyNotices: String { return L10n.tr("Localizable", "common_third_party_notices") } /// Topic diff --git a/ElementX/Sources/Other/Extensions/AttributedString.swift b/ElementX/Sources/Other/Extensions/AttributedString.swift index 19f9ea621..f5027c7ab 100644 --- a/ElementX/Sources/Other/Extensions/AttributedString.swift +++ b/ElementX/Sources/Other/Extensions/AttributedString.swift @@ -33,20 +33,29 @@ extension AttributedString { } } - /// Replaces the specified placeholder with the a string that links to the specified URL. + /// Replaces the specified placeholder with a string that links to the specified URL. /// - Parameters: /// - linkPlaceholder: The text in the string that will be replaced. Make sure this is unique within the string. /// - string: The text for the link that will be substituted into the placeholder. /// - url: The URL that the link should open. mutating func replace(_ linkPlaceholder: String, with string: String, asLinkTo url: URL) { - guard let range = range(of: linkPlaceholder) else { - MXLog.failure("Failed to find the link placeholder to be replaced.") - return - } - // Replace the placeholder with a link. var replacement = AttributedString(string) replacement.link = url + replace(linkPlaceholder, with: replacement) + } + + /// Replaces the specified placeholder with the supplied attributed string. + /// - Parameters: + /// - placeholder: The text in the string that will be replaced. Make sure this is unique within the string. + /// - attributedString: The text for the link that will be substituted into the placeholder. + mutating func replace(_ placeholder: String, with replacement: AttributedString) { + guard let range = range(of: placeholder) else { + MXLog.failure("Failed to find the placeholder to be replaced.") + return + } + + // Replace the placeholder. replaceSubrange(range, with: replacement) } @@ -63,4 +72,12 @@ extension AttributedString { } return newValue } + + /// Makes the entire string bold by setting the presentation intent to strongly emphasized. + /// + /// In practice, this is rendered as semibold for smaller font sizes and just so happens to nicely + /// line up with the semibold → bold font switch used by compound. + mutating func bold() { + self[startIndex.. { get } } -protocol ProgressPublisher { +protocol ProgressPublisher: AnyObject { var publisher: AnyPublisher { get } } diff --git a/ElementX/Sources/Other/SwiftUI/Layout/EqualIconWithLabelStyle.swift b/ElementX/Sources/Other/SwiftUI/Layout/FixedIconSizeLabelStyle.swift similarity index 92% rename from ElementX/Sources/Other/SwiftUI/Layout/EqualIconWithLabelStyle.swift rename to ElementX/Sources/Other/SwiftUI/Layout/FixedIconSizeLabelStyle.swift index aa3f288f7..4c43126f6 100644 --- a/ElementX/Sources/Other/SwiftUI/Layout/EqualIconWithLabelStyle.swift +++ b/ElementX/Sources/Other/SwiftUI/Layout/FixedIconSizeLabelStyle.swift @@ -19,8 +19,10 @@ import SwiftUI struct FixedIconSizeLabelStyle: LabelStyle { @ScaledMetric private var iconSize = 24.0 + var spacing: CGFloat = 16 + func makeBody(configuration: Configuration) -> some View { - HStack { + HStack(spacing: spacing) { configuration .icon .frame(width: iconSize, height: iconSize) diff --git a/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift b/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift index 29b11cd6f..511bfc26c 100644 --- a/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift +++ b/ElementX/Sources/Other/SwiftUI/Views/PlaceholderAvatarImage.swift @@ -25,7 +25,7 @@ struct PlaceholderAvatarImage: View { var body: some View { GeometryReader { geometry in ZStack(alignment: .center) { - bgColor + backgroundColor // This text's frame doesn't look right when redacted if redactionReasons != .placeholder { @@ -47,8 +47,8 @@ struct PlaceholderAvatarImage: View { self.contentID = contentID } - private var bgColor: Color { - if redactionReasons == .placeholder { + private var backgroundColor: Color { + if redactionReasons.contains(.placeholder) { return Color(.systemGray4) // matches the default text redaction } diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicator.swift b/ElementX/Sources/Other/UserIndicator/UserIndicator.swift index 1dd727909..8a6200f7b 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicator.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicator.swift @@ -18,41 +18,51 @@ import Combine import Foundation enum UserIndicatorType: Equatable { - case toast - case modal(interactiveDismissDisabled: Bool) + case toast(progress: UserIndicator.Progress?) + case modal(progress: UserIndicator.Progress?, interactiveDismissDisabled: Bool) - static var modal: Self { - .modal(interactiveDismissDisabled: false) - } + static var toast: Self { .toast(progress: .none) } + static var modal: Self { .modal(progress: .indeterminate, interactiveDismissDisabled: false) } } struct UserIndicator: Equatable, Identifiable { - static func == (lhs: UserIndicator, rhs: UserIndicator) -> Bool { - lhs.id == rhs.id && - lhs.type == rhs.type && - lhs.title == rhs.title && - lhs.iconName == rhs.iconName && - lhs.persistent == rhs.persistent - } - - enum LoaderType { - case unknownProgress - case progress(ProgressPublisher) + enum Progress: Equatable { + static func == (lhs: UserIndicator.Progress, rhs: UserIndicator.Progress) -> Bool { + switch (lhs, rhs) { + case (.indeterminate, .indeterminate): return true + case (.published(let lhsPublisher), .published(let rhsPublisher)): return lhsPublisher === rhsPublisher + default: return false + } + } + + case indeterminate + case published(ProgressPublisher) } var id: String = UUID().uuidString - var type = UserIndicatorType.toast + var type: UserIndicatorType = .toast var title: String var iconName: String? var persistent = false - var loaderType: LoaderType? = .unknownProgress + + // MARK: - Associated values from the type + + var progress: Progress? { + switch type { + case .toast(let progress): return progress + case .modal(let progress, _): return progress + } + } var progressPublisher: AnyPublisher { - switch loaderType { - case .none, .unknownProgress: - return Empty().eraseToAnyPublisher() - case .some(.progress(let progress)): - return progress.publisher.eraseToAnyPublisher() + switch type { + case .toast(let progress), .modal(let progress, _): + switch progress { + case .none, .indeterminate: + return Empty().eraseToAnyPublisher() + case .some(.published(let progress)): + return progress.publisher.eraseToAnyPublisher() + } } } @@ -60,7 +70,7 @@ struct UserIndicator: Equatable, Identifiable { switch type { case .toast: return false - case .modal(let interactiveDismissDisabled): + case .modal(_, let interactiveDismissDisabled): return interactiveDismissDisabled } } diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift index 1af47730c..138c293a0 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorModalView.swift @@ -24,15 +24,17 @@ struct UserIndicatorModalView: View { var body: some View { ZStack { VStack(spacing: 12.0) { - if case .unknownProgress = indicator.loaderType { + if case .indeterminate = indicator.progress { ProgressView() - } else if case .progress = indicator.loaderType { + } else if case .published = indicator.progress { ProgressView(value: progressFraction) } HStack { if let iconName = indicator.iconName { Image(systemName: iconName) + .font(.compound.bodyLG) + .foregroundColor(.compound.iconPrimary) } Text(indicator.title) .font(.compound.bodyLG) @@ -66,17 +68,17 @@ struct UserIndicatorModalView_Previews: PreviewProvider { iconName: "checkmark") ) .previewDisplayName("Spinner") - UserIndicatorModalView(indicator: UserIndicator(type: .modal, + + UserIndicatorModalView(indicator: UserIndicator(type: .modal(progress: .published(ProgressTracker(initialValue: 0.5)), + interactiveDismissDisabled: false), title: "Successfully logged in", - iconName: "checkmark", - loaderType: .progress(ProgressTracker(initialValue: 0.5))) + iconName: "checkmark") ) .previewDisplayName("Progress Bar") - UserIndicatorModalView(indicator: UserIndicator(type: .modal, + UserIndicatorModalView(indicator: UserIndicator(type: .modal(progress: .none, interactiveDismissDisabled: false), title: "Successfully logged in", - iconName: "checkmark", - loaderType: .none) + iconName: "checkmark") ) .previewDisplayName("No progress") } diff --git a/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift b/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift index aaf1fb6f0..164587a83 100644 --- a/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift +++ b/ElementX/Sources/Other/UserIndicator/UserIndicatorToastView.swift @@ -20,21 +20,27 @@ struct UserIndicatorToastView: View { let indicator: UserIndicator var body: some View { - HStack { + HStack(spacing: 4) { + if case .indeterminate = indicator.progress { + ProgressView() + .controlSize(.small) + .tint(.compound.iconPrimary) + } if let iconName = indicator.iconName { Image(systemName: iconName) + .font(.compound.bodyMD) + .foregroundColor(.compound.iconPrimary) } Text(indicator.title) - .font(.compound.bodySM) + .font(.compound.bodyMD) .foregroundColor(.compound.textPrimary) } .id(indicator.id) .padding(.horizontal, 12.0) .padding(.vertical, 10.0) - .frame(minWidth: 150.0) .background(Color.compound.bgSubtlePrimary) .clipShape(RoundedCornerShape(radius: 24.0, corners: .allCorners)) - .shadow(color: .black.opacity(0.25), radius: 10.0, y: 4.0) + .shadow(color: .black.opacity(0.1), radius: 6.0, y: 4.0) .transition(toastTransition) } @@ -48,11 +54,14 @@ struct UserIndicatorToastView: View { struct UserIndicatorToastView_Previews: PreviewProvider { static var previews: some View { - VStack { + VStack(spacing: 30) { UserIndicatorToastView(indicator: UserIndicator(title: "Successfully logged in", iconName: "checkmark")) UserIndicatorToastView(indicator: UserIndicator(title: "Toast without icon")) + + UserIndicatorToastView(indicator: UserIndicator(type: .toast(progress: .indeterminate), + title: "Syncing")) } } } diff --git a/ElementX/Sources/Screens/AnalyticsPromptScreen/AnalyticsPromptScreenModels.swift b/ElementX/Sources/Screens/AnalyticsPromptScreen/AnalyticsPromptScreenModels.swift index d0bd0df6d..879a535d0 100644 --- a/ElementX/Sources/Screens/AnalyticsPromptScreen/AnalyticsPromptScreenModels.swift +++ b/ElementX/Sources/Screens/AnalyticsPromptScreen/AnalyticsPromptScreenModels.swift @@ -44,12 +44,15 @@ struct AnalyticsPromptScreenStrings { init(termsURL: URL) { let content = AttributedString(L10n.screenAnalyticsPromptHelpUsImprove(InfoPlistReader.main.bundleDisplayName)) - // Create the opt in content with a placeholder. + + // Create the 'read terms' with a placeholder. let linkPlaceholder = "{link}" - var readTerms = AttributedString(L10n.screenAnalyticsPromptReadTerms(linkPlaceholder)) - readTerms.replace(linkPlaceholder, - with: L10n.screenAnalyticsPromptReadTermsContentLink, - asLinkTo: termsURL) + var readTerms = AttributedString(L10n.screenAnalyticsSettingsReadTerms(linkPlaceholder)) + var linkString = AttributedString(L10n.screenAnalyticsSettingsReadTermsContentLink) + linkString.link = termsURL + linkString.bold() + readTerms.replace(linkPlaceholder, with: linkString) + optInContent = content + "\n\n" + readTerms } } diff --git a/ElementX/Sources/Screens/AnalyticsPromptScreen/View/AnalyticsPromptScreen.swift b/ElementX/Sources/Screens/AnalyticsPromptScreen/View/AnalyticsPromptScreen.swift index 0bf5f9d5a..019040fab 100644 --- a/ElementX/Sources/Screens/AnalyticsPromptScreen/View/AnalyticsPromptScreen.swift +++ b/ElementX/Sources/Screens/AnalyticsPromptScreen/View/AnalyticsPromptScreen.swift @@ -49,7 +49,6 @@ struct AnalyticsPromptScreen: View { .font(.compound.bodyLG) .multilineTextAlignment(.center) .foregroundColor(.compound.textSecondary) - .tint(.compound.textLinkExternal) Divider() .overlay { Color.compound._borderRowSeparator } diff --git a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift index 5e8f1e71e..ea5b3bd7d 100644 --- a/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift +++ b/ElementX/Sources/Screens/Authentication/LoginScreen/LoginScreenCoordinator.swift @@ -92,14 +92,6 @@ final class LoginScreenCoordinator: CoordinatorProtocol { ServiceLocator.shared.userIndicatorController.retractIndicatorWithId(Self.loadingIndicatorIdentifier) } - private func indicateSuccess() { - ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonSuccess)) - } - - private func indicateFailure() { - ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(title: L10n.commonError)) - } - /// Processes an error to either update the flow or display it to the user. private func handleError(_ error: AuthenticationServiceError) { MXLog.info("Error occurred: \(error)") @@ -163,7 +155,6 @@ final class LoginScreenCoordinator: CoordinatorProtocol { /// Updates the view model with a different homeserver. private func updateViewModel() { viewModel.update(homeserver: authenticationService.homeserver.value) - indicateSuccess() } /// Shows the forgot password screen. diff --git a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift index 0acdd9201..33d324944 100644 --- a/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift +++ b/ElementX/Sources/Screens/BugReportScreen/BugReportScreenCoordinator.swift @@ -88,10 +88,9 @@ final class BugReportScreenCoordinator: CoordinatorProtocol { private func startLoading(label: String = L10n.commonLoading, progressPublisher: ProgressPublisher) { parameters.userIndicatorController?.submitIndicator( UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal, + type: .modal(progress: .published(progressPublisher), interactiveDismissDisabled: false), title: label, - persistent: true, - loaderType: .progress(progressPublisher)) + persistent: true) ) } diff --git a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift index 3a37ad4d7..430f84a69 100644 --- a/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift +++ b/ElementX/Sources/Screens/CreateRoom/CreateRoomViewModel.swift @@ -168,7 +168,7 @@ class CreateRoomViewModel: CreateRoomViewModelType, CreateRoomViewModelProtocol private func showLoadingIndicator() { userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal(interactiveDismissDisabled: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true), title: L10n.commonLoading, persistent: true)) } diff --git a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift index f1ed371a9..9eb12144d 100644 --- a/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift +++ b/ElementX/Sources/Screens/HomeScreen/HomeScreenViewModel.swift @@ -288,10 +288,9 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol state.bindings.alertInfo = AlertInfo(id: UUID(), title: L10n.errorUnknown) case .some(.success): ServiceLocator.shared.userIndicatorController.submitIndicator(UserIndicator(id: UUID().uuidString, - type: .modal, + type: .modal(progress: .none, interactiveDismissDisabled: false), title: L10n.commonCurrentUserLeftRoom, - iconName: "checkmark", - loaderType: .none)) + iconName: "checkmark")) callback?(.roomLeft(roomIdentifier: roomId)) } } diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift index 9942b3dad..56c1697cf 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreen.swift @@ -154,7 +154,7 @@ struct HomeScreen: View { Label(L10n.actionInvite, systemImage: "square.and.arrow.up") } Button(action: feedback) { - Label(L10n.commonReportABug, systemImage: "questionmark.circle") + Label(L10n.commonReportABug, systemImage: "ladybug") } } Section { diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInvitesButton.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInvitesButton.swift index 3badd3e40..8cc57b98f 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInvitesButton.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenInvitesButton.swift @@ -28,7 +28,7 @@ struct HomeScreenInvitesButton: View { HStack(spacing: 8) { Text(title) .foregroundColor(.compound.textPrimary) - .font(.compound.bodyMD) + .font(.compound.bodyMDSemibold) if hasBadge { badge diff --git a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift index ab6aad990..60ca09f4b 100644 --- a/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift +++ b/ElementX/Sources/Screens/HomeScreen/View/HomeScreenRoomCell.swift @@ -92,7 +92,7 @@ struct HomeScreenRoomCell: View { if let timestamp = room.timestamp { Text(timestamp) - .font(.compound.bodySM) + .font(room.hasUnreads ? .compound.bodySMSemibold : .compound.bodySM) .foregroundColor(room.hasUnreads ? .compound.textActionAccent : .compound.textSecondary) } } diff --git a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift index 8570e9b42..ee9cea3c5 100644 --- a/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomDetailsEditScreen/RoomDetailsEditScreenViewModel.swift @@ -78,7 +78,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe userIndicatorController?.retractIndicatorWithId(userIndicatorID) } userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID, - type: .modal(interactiveDismissDisabled: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true), title: L10n.commonLoading, persistent: true)) @@ -102,7 +102,7 @@ class RoomDetailsEditScreenViewModel: RoomDetailsEditScreenViewModelType, RoomDe userIndicatorController?.retractIndicatorWithId(userIndicatorID) } userIndicatorController?.submitIndicator(UserIndicator(id: userIndicatorID, - type: .modal(interactiveDismissDisabled: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true), title: L10n.screenRoomDetailsUpdatingRoom, persistent: true)) diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift index c67592e9d..f1871b664 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenViewModel.swift @@ -519,7 +519,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol private func showLoadingIndicator(with delay: Duration) -> Task { userIndicatorController.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal(interactiveDismissDisabled: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true), title: L10n.commonLoading, persistent: true), delay: delay) diff --git a/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift b/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift index 0d293400b..2572bee89 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/MessageComposer.swift @@ -133,7 +133,7 @@ private struct MessageComposerReplyHeader: View { .overlay(alignment: .topTrailing) { Button(action: action) { Image(systemName: "xmark") - .font(.caption2.weight(.medium)) + .font(.compound.bodySM.weight(.medium)) .foregroundColor(.compound.iconTertiary) .padding(16.0) } @@ -151,9 +151,9 @@ private struct MessageComposerEditHeader: View { Spacer() Button(action: action) { Image(systemName: "xmark") - .font(.caption2.weight(.medium)) + .font(.compound.bodySM.weight(.medium)) .foregroundColor(.compound.iconTertiary) - .padding(12.0) + .padding(EdgeInsets(top: 10, leading: 12, bottom: 12, trailing: 14)) } } } @@ -220,6 +220,17 @@ struct MessageComposer_Previews: PreviewProvider { pasteAction: { _ in }, replyCancellationAction: { }, editCancellationAction: { }) + + MessageComposer(text: .constant(""), + focused: .constant(false), + sendingDisabled: false, + mode: .reply(itemID: UUID().uuidString, + replyDetails: .loaded(sender: .init(id: "Kirk"), + contentType: .text(.init(body: "Text: Where the wild things are")))), + sendAction: { }, + pasteAction: { _ in }, + replyCancellationAction: { }, + editCancellationAction: { }) } .padding(.horizontal) diff --git a/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift b/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift index bd8f9ef6b..96e3a5d48 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Replies/TimelineReplyView.swift @@ -113,7 +113,7 @@ struct TimelineReplyView: View { Spacer().frame(width: 4.0) } - VStack(alignment: .leading) { + VStack(alignment: .leading, spacing: 4) { Text(sender.displayName ?? sender.id) .font(.compound.bodySMSemibold) .foregroundColor(.compound.textPrimary) diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomAttachmentPicker.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomAttachmentPicker.swift index dcb302f72..0f695437e 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomAttachmentPicker.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomAttachmentPicker.swift @@ -54,6 +54,7 @@ struct RoomAttachmentPicker: View { PickerLabel(title: L10n.screenRoomAttachmentSourceCamera, systemImageName: "camera.fill") } } + .padding(.top, 20) .background { // This is done in the background otherwise GeometryReader tends to expand to // all the space given to it like color or shape. @@ -79,7 +80,16 @@ struct RoomAttachmentPicker: View { .labelStyle(FixedIconSizeLabelStyle()) .multilineTextAlignment(.leading) .frame(maxWidth: .infinity, alignment: .leading) - .padding() + .padding(16) } } } + +struct RoomAttachmentPicker_Previews: PreviewProvider { + static let viewModel = RoomScreenViewModel(timelineController: MockRoomTimelineController(), + mediaProvider: MockMediaProvider(), + roomProxy: RoomProxyMock(with: .init(displayName: ""))) + static var previews: some View { + RoomAttachmentPicker(context: viewModel.context) + } +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 62334a5ef..988d164a1 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -21,17 +21,22 @@ struct RoomScreen: View { @State private var showReactionsMenuForItemId = "" @State private var dragOver = false + private let attachmentButtonPadding = 10.0 + var body: some View { timeline .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) // Kills the toolbar translucency. .safeAreaInset(edge: .bottom, spacing: 0) { - HStack(spacing: 4.0) { + HStack(alignment: .bottom, spacing: attachmentButtonPadding) { RoomAttachmentPicker(context: context) + .padding(.bottom, 5) // centre align with the send button messageComposer .environmentObject(context) } - .padding([.horizontal, .bottom]) + .padding(.leading, attachmentButtonPadding) + .padding(.trailing, 12) .padding(.top, 8) + .padding(.bottom) } .navigationBarTitleDisplayMode(.inline) .toolbar { toolbar } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift index 663689f04..ed70ef776 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/SeparatorRoomTimelineView.swift @@ -22,7 +22,7 @@ struct SeparatorRoomTimelineView: View { var body: some View { Text(timelineItem.text) .font(.compound.bodySMSemibold) - .foregroundColor(.compound.textSecondary) + .foregroundColor(.compound.textPrimary) .frame(maxWidth: .infinity) .padding(.horizontal, 36.0) .padding(.vertical, 8.0) diff --git a/ElementX/Sources/Screens/RoomScreen/View/TimelineItemMenu.swift b/ElementX/Sources/Screens/RoomScreen/View/TimelineItemMenu.swift index a1ee08be7..af94e57ae 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/TimelineItemMenu.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/TimelineItemMenu.swift @@ -187,7 +187,7 @@ public struct TimelineItemMenu: View { } case .copyPermalink: Button { send(action) } label: { - MenuLabel(title: L10n.commonPermalink, systemImageName: "link") + MenuLabel(title: L10n.actionCopyLinkToMessage, systemImageName: "link") } case .reply: Button { send(action) } label: { diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift index 657ca20a5..fb86133df 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/AnalyticsSettingsScreenModels.swift @@ -35,12 +35,15 @@ struct AnalyticsSettingsScreenStrings { init(termsURL: URL) { let content = AttributedString(L10n.screenAnalyticsSettingsHelpUsImprove(InfoPlistReader.main.bundleDisplayName)) + // Create the 'read terms' with a placeholder. let linkPlaceholder = "{link}" var readTerms = AttributedString(L10n.screenAnalyticsSettingsReadTerms(linkPlaceholder)) - readTerms.replace(linkPlaceholder, - with: L10n.screenAnalyticsSettingsReadTermsContentLink, - asLinkTo: termsURL) + var linkString = AttributedString(L10n.screenAnalyticsSettingsReadTermsContentLink) + linkString.link = termsURL + linkString.bold() + readTerms.replace(linkPlaceholder, with: linkString) + sectionFooter = content + "\n\n" + readTerms } } diff --git a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift index 79665d019..b20c56cab 100644 --- a/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/AnalyticsSettingsScreen/View/AnalyticsSettingsScreen.swift @@ -40,7 +40,6 @@ struct AnalyticsSettingsScreen: View { } footer: { Text(context.viewState.strings.sectionFooter) .compoundFormSectionFooter() - .tint(.compound.textLinkExternal) } .compoundFormSection() } diff --git a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift index c2c7931bd..0f85bf00f 100644 --- a/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift +++ b/ElementX/Sources/Screens/Settings/SettingsScreen/View/SettingsScreen.swift @@ -122,7 +122,7 @@ struct SettingsScreen: View { // Report Bug Button { context.send(viewAction: .reportBug) } label: { - Label(L10n.actionReportBug, systemImage: "ladybug") + Label(L10n.commonReportABug, systemImage: "ladybug") } .buttonStyle(.compoundForm(accessory: .navigationLink)) .accessibilityIdentifier("reportBugButton") diff --git a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift index 415aa3b61..c9b8cdf54 100644 --- a/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift +++ b/ElementX/Sources/Screens/StartChatScreen/StartChatScreenViewModel.swift @@ -153,7 +153,7 @@ class StartChatScreenViewModel: StartChatScreenViewModelType, StartChatScreenVie private func showLoadingIndicator() { userIndicatorController?.submitIndicator(UserIndicator(id: Self.loadingIndicatorIdentifier, - type: .modal(interactiveDismissDisabled: true), + type: .modal(progress: .indeterminate, interactiveDismissDisabled: true), title: L10n.commonLoading, persistent: true)) } diff --git a/changelog.d/1036.change b/changelog.d/1036.change new file mode 100644 index 000000000..23045ac00 --- /dev/null +++ b/changelog.d/1036.change @@ -0,0 +1 @@ +General app polish. \ No newline at end of file