From 2ac0c8f0e70d01eb4741d2dcb7d3b43589d9e44b Mon Sep 17 00:00:00 2001 From: Mauro <34335419+Velin92@users.noreply.github.com> Date: Thu, 8 Feb 2024 18:07:14 +0100 Subject: [PATCH] Fix for the RTE not mantaining content when transitioning from a split navigation to a stack navigation (#2435) --- ElementX.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 6 ++--- .../ComposerToolbarViewModel.swift | 23 +++++++++++++------ .../View/ComposerToolbar.swift | 5 ---- .../ComposerToolbarViewModelTests.swift | 13 +++++++---- changelog.d/2364.bugfix | 1 + project.yml | 2 +- 7 files changed, 31 insertions(+), 21 deletions(-) create mode 100644 changelog.d/2364.bugfix diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index c0b1a3947..504af8000 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -6787,7 +6787,7 @@ repositoryURL = "https://github.com/matrix-org/matrix-wysiwyg-composer-swift"; requirement = { kind = exactVersion; - version = 2.26.0; + version = 2.28.0; }; }; 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = { diff --git a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index a724ef7b2..59c9ff823 100644 --- a/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/ElementX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -138,8 +138,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift", "state" : { - "revision" : "be43b31dd47987ffbeb325c94805ab330390d555", - "version" : "2.26.0" + "revision" : "7b341602195b6527eb34c61cc6bd479f7631409d", + "version" : "2.28.0" } }, { @@ -262,7 +262,7 @@ { "identity" : "swiftui-introspect", "kind" : "remoteSourceControl", - "location" : "https://github.com/siteline/SwiftUI-Introspect.git", + "location" : "https://github.com/siteline/SwiftUI-Introspect", "state" : { "revision" : "b94da693e57eaf79d16464b8b7c90d09cba4e290", "version" : "0.9.2" diff --git a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift index 6bf2e2e94..8244d583c 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/ComposerToolbarViewModel.swift @@ -26,6 +26,8 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool private let wysiwygViewModel: WysiwygComposerViewModel private let completionSuggestionService: CompletionSuggestionServiceProtocol private let appSettings: AppSettings + private let mentionDisplayHelper: MentionDisplayHelper + private var hasAppeard = false private let actionsSubject: PassthroughSubject = .init() var actions: AnyPublisher { @@ -45,6 +47,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool self.wysiwygViewModel = wysiwygViewModel self.completionSuggestionService = completionSuggestionService self.appSettings = appSettings + self.mentionDisplayHelper = mentionDisplayHelper super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, duration: 0), audioRecorderState: .init(), @@ -99,9 +102,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } .weakAssign(to: \.state.suggestions, on: self) .store(in: &cancellables) - - setupMentionsHandling(mentionDisplayHelper: mentionDisplayHelper) - + focusComposerIfHardwareKeyboardConnected() } @@ -110,7 +111,11 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool override func process(viewAction: ComposerToolbarViewAction) { switch viewAction { case .composerAppeared: - wysiwygViewModel.setup() + setupMentionsHandlingIfNecessary() + if !hasAppeard { + hasAppeard = true + wysiwygViewModel.setup() + } case .sendMessage: guard !state.sendButtonDisabled else { return } @@ -200,8 +205,12 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } } - private func setupMentionsHandling(mentionDisplayHelper: MentionDisplayHelper) { - wysiwygViewModel.textView.mentionDisplayHelper = mentionDisplayHelper + private func setupMentionsHandlingIfNecessary() { + guard let textView = wysiwygViewModel.textView, + textView.mentionDisplayHelper == nil else { + return + } + textView.mentionDisplayHelper = mentionDisplayHelper let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder()) @@ -252,7 +261,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool } private func set(text: String) { - wysiwygViewModel.textView.flushPills() + wysiwygViewModel.textView?.flushPills() if appSettings.richTextEditorEnabled { wysiwygViewModel.setHtmlContent(text) diff --git a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift index 96ba61f97..0103f0772 100644 --- a/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift +++ b/ElementX/Sources/Screens/ComposerToolbar/View/ComposerToolbar.swift @@ -29,7 +29,6 @@ struct ComposerToolbar: View { @FocusState private var composerFocused: Bool @State private var frame: CGRect = .zero @Environment(\.verticalSizeClass) private var verticalSizeClass - @State private var hasAlreadyAppeared = false var body: some View { VStack(spacing: 8) { @@ -175,11 +174,7 @@ struct ComposerToolbar: View { } editCancellationAction: { context.send(viewAction: .cancelEdit) } onAppearAction: { - guard !hasAlreadyAppeared else { - return - } context.send(viewAction: .composerAppeared) - hasAlreadyAppeared = true } .focused($composerFocused) .onChange(of: context.composerFocused) { newValue in diff --git a/UnitTests/Sources/ComposerToolbarViewModelTests.swift b/UnitTests/Sources/ComposerToolbarViewModelTests.swift index 08d995f00..5f40024e7 100644 --- a/UnitTests/Sources/ComposerToolbarViewModelTests.swift +++ b/UnitTests/Sources/ComposerToolbarViewModelTests.swift @@ -33,6 +33,7 @@ class ComposerToolbarViewModelTests: XCTestCase { appSettings.richTextEditorEnabled = true ServiceLocator.shared.register(appSettings: appSettings) wysiwygViewModel = WysiwygComposerViewModel() + wysiwygViewModel.textView = WysiwygTextView() completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init()) viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, completionSuggestionService: completionSuggestionServiceMock, @@ -142,20 +143,24 @@ class ComposerToolbarViewModelTests: XCTestCase { XCTAssertEqual(wysiwygViewModel.content.html, string) } - func testUserMentionPillInRTE() { + func testUserMentionPillInRTE() async { + viewModel.context.send(viewAction: .composerAppeared) + await Task.yield() let userID = "@test:matrix.org" let suggestion = SuggestionItem.user(item: .init(id: userID, displayName: "Test", avatarURL: nil)) viewModel.context.send(viewAction: .selectedSuggestion(suggestion)) - let attachment = wysiwygViewModel.textView.attributedText.attribute(.attachment, at: 0, effectiveRange: nil) as? PillTextAttachment + let attachment = wysiwygViewModel.textView?.attributedText.attribute(.attachment, at: 0, effectiveRange: nil) as? PillTextAttachment XCTAssertEqual(attachment?.pillData?.type, .user(userID: userID)) } - func testAllUsersMentionPillInRTE() { + func testAllUsersMentionPillInRTE() async { + viewModel.context.send(viewAction: .composerAppeared) + await Task.yield() let suggestion = SuggestionItem.allUsers(item: .allUsersMention(roomAvatar: nil)) viewModel.context.send(viewAction: .selectedSuggestion(suggestion)) - let attachment = wysiwygViewModel.textView.attributedText.attribute(.attachment, at: 0, effectiveRange: nil) as? PillTextAttachment + let attachment = wysiwygViewModel.textView?.attributedText.attribute(.attachment, at: 0, effectiveRange: nil) as? PillTextAttachment XCTAssertEqual(attachment?.pillData?.type, .allUsers) } diff --git a/changelog.d/2364.bugfix b/changelog.d/2364.bugfix new file mode 100644 index 000000000..f63236a5b --- /dev/null +++ b/changelog.d/2364.bugfix @@ -0,0 +1 @@ +Fixed RTE not retaining content when transitioning from a split navigation to a stack navigation. \ No newline at end of file diff --git a/project.yml b/project.yml index 8fbfdad88..2c5115626 100644 --- a/project.yml +++ b/project.yml @@ -66,7 +66,7 @@ packages: # path: ../swift-ogg WysiwygComposer: url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift - exactVersion: 2.26.0 + exactVersion: 2.28.0 # path: ../matrix-wysiwyg/platforms/ios/lib/WysiwygComposer # External dependencies