Fix for the RTE not mantaining content when transitioning from a split navigation to a stack navigation (#2435)

This commit is contained in:
Mauro
2024-02-08 18:07:14 +01:00
committed by GitHub
parent 224e4e4881
commit 4ba7aa9e9d
7 changed files with 31 additions and 21 deletions
+1 -1
View File
@@ -6787,7 +6787,7 @@
repositoryURL = "https://github.com/matrix-org/matrix-wysiwyg-composer-swift"; repositoryURL = "https://github.com/matrix-org/matrix-wysiwyg-composer-swift";
requirement = { requirement = {
kind = exactVersion; kind = exactVersion;
version = 2.26.0; version = 2.28.0;
}; };
}; };
96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = { 96495DD8554E2F39D3954354 /* XCRemoteSwiftPackageReference "posthog-ios" */ = {
@@ -138,8 +138,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift", "location" : "https://github.com/matrix-org/matrix-wysiwyg-composer-swift",
"state" : { "state" : {
"revision" : "be43b31dd47987ffbeb325c94805ab330390d555", "revision" : "7b341602195b6527eb34c61cc6bd479f7631409d",
"version" : "2.26.0" "version" : "2.28.0"
} }
}, },
{ {
@@ -262,7 +262,7 @@
{ {
"identity" : "swiftui-introspect", "identity" : "swiftui-introspect",
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/siteline/SwiftUI-Introspect.git", "location" : "https://github.com/siteline/SwiftUI-Introspect",
"state" : { "state" : {
"revision" : "b94da693e57eaf79d16464b8b7c90d09cba4e290", "revision" : "b94da693e57eaf79d16464b8b7c90d09cba4e290",
"version" : "0.9.2" "version" : "0.9.2"
@@ -26,6 +26,8 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
private let wysiwygViewModel: WysiwygComposerViewModel private let wysiwygViewModel: WysiwygComposerViewModel
private let completionSuggestionService: CompletionSuggestionServiceProtocol private let completionSuggestionService: CompletionSuggestionServiceProtocol
private let appSettings: AppSettings private let appSettings: AppSettings
private let mentionDisplayHelper: MentionDisplayHelper
private var hasAppeard = false
private let actionsSubject: PassthroughSubject<ComposerToolbarViewModelAction, Never> = .init() private let actionsSubject: PassthroughSubject<ComposerToolbarViewModelAction, Never> = .init()
var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> { var actions: AnyPublisher<ComposerToolbarViewModelAction, Never> {
@@ -45,6 +47,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
self.wysiwygViewModel = wysiwygViewModel self.wysiwygViewModel = wysiwygViewModel
self.completionSuggestionService = completionSuggestionService self.completionSuggestionService = completionSuggestionService
self.appSettings = appSettings self.appSettings = appSettings
self.mentionDisplayHelper = mentionDisplayHelper
super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, duration: 0), super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, duration: 0),
audioRecorderState: .init(), audioRecorderState: .init(),
@@ -99,9 +102,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
} }
.weakAssign(to: \.state.suggestions, on: self) .weakAssign(to: \.state.suggestions, on: self)
.store(in: &cancellables) .store(in: &cancellables)
setupMentionsHandling(mentionDisplayHelper: mentionDisplayHelper)
focusComposerIfHardwareKeyboardConnected() focusComposerIfHardwareKeyboardConnected()
} }
@@ -110,7 +111,11 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
override func process(viewAction: ComposerToolbarViewAction) { override func process(viewAction: ComposerToolbarViewAction) {
switch viewAction { switch viewAction {
case .composerAppeared: case .composerAppeared:
wysiwygViewModel.setup() setupMentionsHandlingIfNecessary()
if !hasAppeard {
hasAppeard = true
wysiwygViewModel.setup()
}
case .sendMessage: case .sendMessage:
guard !state.sendButtonDisabled else { return } guard !state.sendButtonDisabled else { return }
@@ -200,8 +205,12 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
} }
} }
private func setupMentionsHandling(mentionDisplayHelper: MentionDisplayHelper) { private func setupMentionsHandlingIfNecessary() {
wysiwygViewModel.textView.mentionDisplayHelper = mentionDisplayHelper guard let textView = wysiwygViewModel.textView,
textView.mentionDisplayHelper == nil else {
return
}
textView.mentionDisplayHelper = mentionDisplayHelper
let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder()) let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder())
@@ -252,7 +261,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
} }
private func set(text: String) { private func set(text: String) {
wysiwygViewModel.textView.flushPills() wysiwygViewModel.textView?.flushPills()
if appSettings.richTextEditorEnabled { if appSettings.richTextEditorEnabled {
wysiwygViewModel.setHtmlContent(text) wysiwygViewModel.setHtmlContent(text)
@@ -29,7 +29,6 @@ struct ComposerToolbar: View {
@FocusState private var composerFocused: Bool @FocusState private var composerFocused: Bool
@State private var frame: CGRect = .zero @State private var frame: CGRect = .zero
@Environment(\.verticalSizeClass) private var verticalSizeClass @Environment(\.verticalSizeClass) private var verticalSizeClass
@State private var hasAlreadyAppeared = false
var body: some View { var body: some View {
VStack(spacing: 8) { VStack(spacing: 8) {
@@ -175,11 +174,7 @@ struct ComposerToolbar: View {
} editCancellationAction: { } editCancellationAction: {
context.send(viewAction: .cancelEdit) context.send(viewAction: .cancelEdit)
} onAppearAction: { } onAppearAction: {
guard !hasAlreadyAppeared else {
return
}
context.send(viewAction: .composerAppeared) context.send(viewAction: .composerAppeared)
hasAlreadyAppeared = true
} }
.focused($composerFocused) .focused($composerFocused)
.onChange(of: context.composerFocused) { newValue in .onChange(of: context.composerFocused) { newValue in
@@ -33,6 +33,7 @@ class ComposerToolbarViewModelTests: XCTestCase {
appSettings.richTextEditorEnabled = true appSettings.richTextEditorEnabled = true
ServiceLocator.shared.register(appSettings: appSettings) ServiceLocator.shared.register(appSettings: appSettings)
wysiwygViewModel = WysiwygComposerViewModel() wysiwygViewModel = WysiwygComposerViewModel()
wysiwygViewModel.textView = WysiwygTextView()
completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init()) completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init())
viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel, viewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel,
completionSuggestionService: completionSuggestionServiceMock, completionSuggestionService: completionSuggestionServiceMock,
@@ -142,20 +143,24 @@ class ComposerToolbarViewModelTests: XCTestCase {
XCTAssertEqual(wysiwygViewModel.content.html, string) XCTAssertEqual(wysiwygViewModel.content.html, string)
} }
func testUserMentionPillInRTE() { func testUserMentionPillInRTE() async {
viewModel.context.send(viewAction: .composerAppeared)
await Task.yield()
let userID = "@test:matrix.org" let userID = "@test:matrix.org"
let suggestion = SuggestionItem.user(item: .init(id: userID, displayName: "Test", avatarURL: nil)) let suggestion = SuggestionItem.user(item: .init(id: userID, displayName: "Test", avatarURL: nil))
viewModel.context.send(viewAction: .selectedSuggestion(suggestion)) 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)) 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)) let suggestion = SuggestionItem.allUsers(item: .allUsersMention(roomAvatar: nil))
viewModel.context.send(viewAction: .selectedSuggestion(suggestion)) 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) XCTAssertEqual(attachment?.pillData?.type, .allUsers)
} }
+1
View File
@@ -0,0 +1 @@
Fixed RTE not retaining content when transitioning from a split navigation to a stack navigation.
+1 -1
View File
@@ -66,7 +66,7 @@ packages:
# path: ../swift-ogg # path: ../swift-ogg
WysiwygComposer: WysiwygComposer:
url: https://github.com/matrix-org/matrix-wysiwyg-composer-swift 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 # path: ../matrix-wysiwyg/platforms/ios/lib/WysiwygComposer
# External dependencies # External dependencies