diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index 8fec6dbce..d53e69ba6 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -103,6 +103,7 @@ 237FC70AA257B935F53316BA /* SessionVerificationControllerProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = C55D7E514F9DE4E3D72FDCAD /* SessionVerificationControllerProxy.swift */; }; 245F7FE5961BD10C145A26E0 /* UITimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA689E792E679F5E3956F21 /* UITimelineView.swift */; }; 24A75F72EEB7561B82D726FD /* Date.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2141693488CE5446BB391964 /* Date.swift */; }; + 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2B1CC9AA154F4D5435BF60A /* Comparable.swift */; }; 24BDDD09A90B8BFE3793F3AA /* ClientProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6033779EB37259F27F938937 /* ClientProxyProtocol.swift */; }; 25618589E0DE0F1E95FC7B5C /* EmojiProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 099F2D36C141D845A445B1E6 /* EmojiProviderTests.swift */; }; 256D76972BA3254F7CB7F88B /* LocationAnnotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = AAD8234D0E9C9B12BF9F240B /* LocationAnnotation.swift */; }; @@ -1491,6 +1492,7 @@ E1E0B4A34E69BD2132BEC521 /* MessageText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageText.swift; sourceTree = ""; }; E24B88AD3D1599E8CB1376E0 /* AvatarSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarSize.swift; sourceTree = ""; }; E26747B3154A5DBC3A7E24A5 /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = ""; }; + E2B1CC9AA154F4D5435BF60A /* Comparable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comparable.swift; sourceTree = ""; }; E2DCA495ED42D2463DDAA94D /* TimelineBubbleLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineBubbleLayout.swift; sourceTree = ""; }; E3059CFA00C67D8787273B20 /* ServerSelectionScreenViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerSelectionScreenViewModel.swift; sourceTree = ""; }; E36CB905A2B9EC2C92A2DA7C /* KeychainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainController.swift; sourceTree = ""; }; @@ -2205,6 +2207,7 @@ 52BD6ED18E2EB61E28C340AD /* AttributedString.swift */, B6E89E530A8E92EC44301CA1 /* Bundle.swift */, A9FAFE1C2149E6AC8156ED2B /* Collection.swift */, + E2B1CC9AA154F4D5435BF60A /* Comparable.swift */, B383DCD3DCB19E00FD478A5F /* ConfirmationDialog.swift */, 2141693488CE5446BB391964 /* Date.swift */, BFDCAC6CAAD65A2C24EA9C4B /* Dictionary.swift */, @@ -4460,6 +4463,7 @@ 9FAF6DA7E8E85C9699757764 /* CollapsibleRoomTimelineView.swift in Sources */, 0DC815CA24E1BD7F408F37D3 /* CollapsibleTimelineItem.swift in Sources */, 663E198678778F7426A9B27D /* Collection.swift in Sources */, + 24B7CD41342C143117ADA768 /* Comparable.swift in Sources */, 0B57C2399B9E1CE5CE0D8005 /* ComposerToolbar.swift in Sources */, 56BAB81A0D03C2EF09B86294 /* ComposerToolbarModels.swift in Sources */, 5995C63B1C61DE1373AA2BCE /* ComposerToolbarViewModel.swift in Sources */, diff --git a/ElementX/Resources/Assets.xcassets/colors/grabber.colorset/Contents.json b/ElementX/Resources/Assets.xcassets/colors/grabber.colorset/Contents.json new file mode 100644 index 000000000..3b150a2f6 --- /dev/null +++ b/ElementX/Resources/Assets.xcassets/colors/grabber.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "199", + "green" : "197", + "red" : "197" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "89", + "green" : "83", + "red" : "81" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ElementX/Resources/Assets.xcassets/images/composer/text-format.imageset/Contents.json b/ElementX/Resources/Assets.xcassets/images/composer/text-format.imageset/Contents.json index f36cbb199..5d93da13c 100644 --- a/ElementX/Resources/Assets.xcassets/images/composer/text-format.imageset/Contents.json +++ b/ElementX/Resources/Assets.xcassets/images/composer/text-format.imageset/Contents.json @@ -10,6 +10,7 @@ "version" : 1 }, "properties" : { - "preserves-vector-representation" : true + "preserves-vector-representation" : true, + "template-rendering-intent" : "template" } } diff --git a/ElementX/Sources/Generated/Assets.swift b/ElementX/Sources/Generated/Assets.swift index e6e44e028..2d3a0943a 100644 --- a/ElementX/Sources/Generated/Assets.swift +++ b/ElementX/Sources/Generated/Assets.swift @@ -27,6 +27,7 @@ internal enum Asset { internal enum Colors { internal static let accentColor = ColorAsset(name: "colors/accent-color") internal static let backgroundColor = ColorAsset(name: "colors/background-color") + internal static let grabber = ColorAsset(name: "colors/grabber") } internal enum Images { internal static let appLogo = ImageAsset(name: "images/app-logo") diff --git a/ElementX/Sources/Other/Extensions/Comparable.swift b/ElementX/Sources/Other/Extensions/Comparable.swift new file mode 100644 index 000000000..03277b42d --- /dev/null +++ b/ElementX/Sources/Other/Extensions/Comparable.swift @@ -0,0 +1,21 @@ +// +// Copyright 2023 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +extension Comparable { + func clamped(to limits: ClosedRange) -> Self { + min(max(self, limits.lowerBound), limits.upperBound) + } +} diff --git a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift index 68a1816a6..76f73b6bf 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarModels.swift @@ -68,6 +68,7 @@ struct ComposerToolbarViewStateBindings { var composerPlainText = "" var composerFocused = false var composerActionsEnabled = false + var composerExpanded = false var formatItems: [FormatItem] = .init() var alertInfo: AlertInfo? diff --git a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift index 4a0f2e20e..be865623b 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift @@ -90,7 +90,6 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool actionsSubject.send(.sendPlainTextMessage(message: context.composerPlainText, mode: state.composerMode)) } - state.bindings.composerActionsEnabled = false case .cancelReply: set(mode: .default) case .cancelEdit: diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift index 8cade5e45..57c4e1ecb 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift @@ -43,6 +43,10 @@ struct ComposerToolbar: View { } messageComposer .environmentObject(context) + .onTapGesture { + guard !composerFocused else { return } + composerFocused = true + } if !context.composerActionsEnabled { sendButton } @@ -53,6 +57,7 @@ struct ComposerToolbar: View { HStack(alignment: .bottom, spacing: 10) { Button { context.composerActionsEnabled = false + context.composerExpanded = false } label: { Image(systemName: "xmark.circle.fill") .font(.compound.headingLG) @@ -89,7 +94,9 @@ struct ComposerToolbar: View { private var messageComposer: some View { MessageComposer(plainText: $context.composerPlainText, composerView: composerView, - mode: context.viewState.composerMode) { + mode: context.viewState.composerMode, + showResizeGrabber: context.viewState.bindings.composerActionsEnabled, + isExpanded: $context.composerExpanded) { context.send(viewAction: .sendMessage) } pasteAction: { provider in context.send(viewAction: .handlePasteOrDrop(provider: provider)) diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/MessageComposer.swift b/ElementX/Sources/Screens/ComposerToolbar/View/MessageComposer.swift index f509f1bc4..70fa9ab17 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/MessageComposer.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/MessageComposer.swift @@ -24,6 +24,8 @@ struct MessageComposer: View { @Binding var plainText: String let composerView: WysiwygComposerView let mode: RoomScreenComposerMode + let showResizeGrabber: Bool + @Binding var isExpanded: Bool let sendAction: EnterKeyHandler let pasteAction: PasteHandler let replyCancellationAction: () -> Void @@ -32,14 +34,43 @@ struct MessageComposer: View { @FocusState private var focused: Bool @State private var isMultiline = false + @State private var composerTranslation: CGFloat = 0 var body: some View { - let roundedRectangle = RoundedRectangle(cornerRadius: borderRadius) + VStack(spacing: 0) { + if showResizeGrabber { + resizeGrabber + } + + mainContent + .padding(.horizontal, 12.0) + .clipShape(RoundedRectangle(cornerRadius: borderRadius)) + .background { + let roundedRectangle = RoundedRectangle(cornerRadius: borderRadius) + ZStack { + roundedRectangle + .fill(Color.compound.bgSubtleSecondary) + roundedRectangle + .stroke(Color.compound._borderTextFieldFocused, lineWidth: 1) + .opacity(focused ? 1 : 0) + } + } + // Explicitly disable all animations to fix weirdness with the header immediately + // appearing whilst the text field and keyboard are still animating up to it. + .animation(.noAnimation, value: mode) + } + .gesture(showResizeGrabber ? dragGesture : nil) + } + + // MARK: - Private + + private var mainContent: some View { VStack(alignment: .leading, spacing: -6) { header HStack(alignment: .bottom) { if ServiceLocator.shared.settings.richTextEditorEnabled { composerView + .frame(minHeight: composerHeight, alignment: .top) .tint(.compound.iconAccentTertiary) .padding(.vertical, 10) .focused($focused) @@ -59,20 +90,11 @@ struct MessageComposer: View { } } } - .padding(.horizontal, 12.0) - .clipped() - .background { - ZStack { - roundedRectangle - .fill(Color.compound.bgSubtleSecondary) - roundedRectangle - .stroke(Color.compound._borderTextFieldFocused, lineWidth: 1) - .opacity(focused ? 1 : 0) - } - } - // Explicitly disable all animations to fix weirdness with the header immediately - // appearing whilst the text field and keyboard are still animating up to it. - .animation(.noAnimation, value: mode) + } + + private var composerHeight: CGFloat { + let baseHeight = isExpanded ? ComposerConstant.maxHeight : ComposerConstant.minHeight + return (baseHeight - composerTranslation).clamped(to: ComposerConstant.allowedHeightRange) } @ViewBuilder @@ -95,6 +117,31 @@ struct MessageComposer: View { return 20 } } + + private var resizeGrabber: some View { + Capsule() + .foregroundColor(Asset.Colors.grabber.swiftUIColor) + .frame(width: 36, height: 5) + .padding(.vertical, 8) + .frame(maxWidth: .infinity) + } + + private var dragGesture: some Gesture { + DragGesture() + .onChanged { value in + composerTranslation += value.translation.height + } + .onEnded { _ in + withElementAnimation(.easeIn(duration: 0.3)) { + if composerTranslation > ComposerConstant.translationThreshold { + isExpanded = false + } else if composerTranslation < -ComposerConstant.translationThreshold { + isExpanded = true + } + composerTranslation = 0 + } + } + } } private struct MessageComposerReplyHeader: View { @@ -169,6 +216,8 @@ struct MessageComposer_Previews: PreviewProvider { return MessageComposer(plainText: .constant(content), composerView: composerView, mode: mode, + showResizeGrabber: false, + isExpanded: .constant(false), sendAction: { }, pasteAction: { _ in }, replyCancellationAction: { }, diff --git a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift index 330fabd23..74b03c17a 100644 --- a/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift +++ b/ElementX/Sources/Screens/RoomScreen/RoomScreenCoordinator.swift @@ -61,7 +61,9 @@ final class RoomScreenCoordinator: CoordinatorProtocol { analytics: ServiceLocator.shared.analytics, userIndicatorController: ServiceLocator.shared.userIndicatorController) - wysiwygViewModel = WysiwygComposerViewModel(minHeight: 22, maxExpandedHeight: 250) + wysiwygViewModel = WysiwygComposerViewModel(minHeight: ComposerConstant.minHeight, + maxCompressedHeight: ComposerConstant.maxHeight, + maxExpandedHeight: ComposerConstant.maxHeight) composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel) } @@ -124,3 +126,10 @@ final class RoomScreenCoordinator: CoordinatorProtocol { return AnyView(RoomScreen(context: viewModel.context, composerToolbar: composerToolbar)) } } + +enum ComposerConstant { + static let minHeight: CGFloat = 22 + static let maxHeight: CGFloat = 250 + static let allowedHeightRange = minHeight...maxHeight + static let translationThreshold: CGFloat = 60 +} diff --git a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift index 99cc196fb..dd909ed50 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift @@ -19,11 +19,18 @@ import WysiwygComposer struct RoomScreen: View { @ObservedObject var context: RoomScreenViewModel.Context + @ObservedObject private var composerToolbarContext: ComposerToolbarViewModel.Context @State private var dragOver = false let composerToolbar: ComposerToolbar private let attachmentButtonPadding = 10.0 + init(context: RoomScreenViewModel.Context, composerToolbar: ComposerToolbar) { + self.context = context + self.composerToolbar = composerToolbar + composerToolbarContext = composerToolbar.context + } + var body: some View { timeline .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) @@ -31,12 +38,20 @@ struct RoomScreen: View { composerToolbar .padding(.leading, attachmentButtonPadding) .padding(.trailing, 12) - .padding(.top, 8) .padding(.bottom) + .background { + if composerToolbarContext.composerActionsEnabled { + RoundedRectangle(cornerRadius: 20) + .stroke(Color.compound._borderTextFieldFocused, lineWidth: 1) + .ignoresSafeArea() + } + } + .padding(.top, 8) .background(Color.compound.bgCanvasDefault.ignoresSafeArea()) .environmentObject(context) } .navigationBarTitleDisplayMode(.inline) + .navigationBarHidden(isNavigationBarHidden) .toolbar { toolbar } .toolbarBackground(.visible, for: .navigationBar) // Fix the toolbar's background. .overlay { loadingIndicator } @@ -142,6 +157,10 @@ struct RoomScreen: View { RoomHeaderView(context: context) } } + + private var isNavigationBarHidden: Bool { + composerToolbarContext.composerActionsEnabled && composerToolbarContext.composerExpanded && UIDevice.current.userInterfaceIdiom == .pad + } } // MARK: - Previews diff --git a/ElementX/Sources/UITests/UITestsAppCoordinator.swift b/ElementX/Sources/UITests/UITestsAppCoordinator.swift index 67320e757..f639c062e 100644 --- a/ElementX/Sources/UITests/UITestsAppCoordinator.swift +++ b/ElementX/Sources/UITests/UITestsAppCoordinator.swift @@ -372,7 +372,9 @@ class MockScreen: Identifiable { var sessionVerificationControllerProxy = SessionVerificationControllerProxyMock.configureMock(requestDelay: .seconds(5)) let parameters = SessionVerificationScreenCoordinatorParameters(sessionVerificationControllerProxy: sessionVerificationControllerProxy) return SessionVerificationScreenCoordinator(parameters: parameters) - case .userSessionScreen, .userSessionScreenReply: + case .userSessionScreen, .userSessionScreenReply, .userSessionScreenRTE: + let appSettings: AppSettings = ServiceLocator.shared.settings + appSettings.richTextEditorEnabled = id == .userSessionScreenRTE let navigationSplitCoordinator = NavigationSplitCoordinator(placeholderCoordinator: PlaceholderScreenCoordinator()) let clientProxy = MockClientProxy(userID: "@mock:client.com", roomSummaryProvider: MockRoomSummaryProvider(state: .loaded(.mockRooms))) @@ -383,7 +385,7 @@ class MockScreen: Identifiable { navigationSplitCoordinator: navigationSplitCoordinator, bugReportService: BugReportServiceMock(), roomTimelineControllerFactory: MockRoomTimelineControllerFactory(), - appSettings: ServiceLocator.shared.settings, + appSettings: appSettings, analytics: ServiceLocator.shared.analytics) coordinator.start() diff --git a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift index 1d95f48e9..dd69d121f 100644 --- a/ElementX/Sources/UITests/UITestsScreenIdentifier.swift +++ b/ElementX/Sources/UITests/UITestsScreenIdentifier.swift @@ -51,6 +51,7 @@ enum UITestsScreenIdentifier: String { case sessionVerification case userSessionScreen case userSessionScreenReply + case userSessionScreenRTE case roomDetailsScreen case roomDetailsScreenWithRoomAvatar case roomDetailsScreenWithEmptyTopic diff --git a/UITests/Sources/UserSessionScreenTests.swift b/UITests/Sources/UserSessionScreenTests.swift index 9d6d94657..030ccc353 100644 --- a/UITests/Sources/UserSessionScreenTests.swift +++ b/UITests/Sources/UserSessionScreenTests.swift @@ -45,4 +45,19 @@ class UserSessionScreenTests: XCTestCase { try await app.assertScreenshot(.userSessionScreenReply) } + + func testUserSessionRTE() async throws { + let roomName = "First room" + let app = Application.launch(.userSessionScreenRTE) + + app.buttons[A11yIdentifiers.homeScreen.roomName(roomName)].tap() + XCTAssert(app.staticTexts[roomName].waitForExistence(timeout: 5.0)) + try await Task.sleep(for: .seconds(1)) + + app.buttons[A11yIdentifiers.roomScreen.composerToolbar.openComposeOptions].tap() + try await app.assertScreenshot(.userSessionScreenRTE, step: 1) + + app.buttons[A11yIdentifiers.roomScreen.attachmentPickerTextFormatting].tap() + try await app.assertScreenshot(.userSessionScreenRTE, step: 2) + } } diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-1.png new file mode 100644 index 000000000..303b2dcd0 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8d7f556db626ee3ed168db298001c1b96c5e7d14a22388bb115eb3dfd2c4ccab +size 404694 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-2.png new file mode 100644 index 000000000..ff06feb28 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPad-9th-generation.userSessionScreenRTE-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acf654f8fee9ec9db076a8a170618776dee89800ca5b227dafd779d6db45827d +size 327770 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-1.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-1.png new file mode 100644 index 000000000..a151df437 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b6403aaef45f204a3de0ac10e0a1258226930ca821174a25bf3a596c60e8c316 +size 252152 diff --git a/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-2.png b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-2.png new file mode 100644 index 000000000..7a24cc93e --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/en-GB-iPhone-14.userSessionScreenRTE-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a002779814ca094c20052a22a87057fd669ca975819dd7a006befefa97692e20 +size 278085 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-1.png new file mode 100644 index 000000000..623ec3802 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3a91f32ae1b082fd0bfff8f51b273ae76544ed2570362f6b7195116ff2dc5c7 +size 390489 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-2.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-2.png new file mode 100644 index 000000000..b3de216f9 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPad-9th-generation.userSessionScreenRTE-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f5075ddecf5997355ad6938fe5587e6763c87d3aa8ead6adf5d781f37a279e72 +size 329962 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-1.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-1.png new file mode 100644 index 000000000..f2f372a33 --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-1.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b59ef2cf7292221d20be32da9f81a524c0b9246127debc75ce3ceae671b1e209 +size 260379 diff --git a/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-2.png b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-2.png new file mode 100644 index 000000000..b4390d6af --- /dev/null +++ b/UITests/Sources/__Snapshots__/Application/pseudo-iPhone-14.userSessionScreenRTE-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:489bc71a45a9f943b164f69e085a70e70eac781bd2fdfee7750071936c848eb1 +size 278264 diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index 3dac7cb5b..33f435619 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -78,12 +78,12 @@ class ComposerToolbarViewModelTests: XCTestCase { XCTAssertTrue(viewModel.state.bindings.composerFocused) } - func testRTEDisabledAfterSendingMessage() { + func testRTEEnabledAfterSendingMessage() { viewModel.process(viewAction: .enableTextFormatting) XCTAssertTrue(viewModel.state.bindings.composerFocused) viewModel.state.composerEmpty = false viewModel.process(viewAction: .sendMessage) - XCTAssertFalse(viewModel.state.bindings.composerActionsEnabled) + XCTAssertTrue(viewModel.state.bindings.composerActionsEnabled) } func testAlertIsShownAfterLinkAction() {