mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-05 20:09:04 +00:00
Fix for the RTE not mantaining content when transitioning from a split navigation to a stack navigation (#2435)
This commit is contained in:
@@ -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(),
|
||||||
@@ -100,8 +103,6 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
Fixed RTE not retaining content when transitioning from a split navigation to a stack navigation.
|
||||||
+1
-1
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user