mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 10:33:45 +00:00
Initial integration of RTE (#1464)
* Initial integration of RTE * Fix `clipped`, `focused` and composer view type * Remove horizontal padding * Add `ComposerToolbar` mock * Restore `composerFocusedSubject` * Allow using HTML from RTE on message sent * Fix new message content API * Add feature flag for Rich Text Editor
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
import Combine
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
struct RoomScreenCoordinatorParameters {
|
||||
let roomProxy: RoomProxyProtocol
|
||||
@@ -40,6 +41,7 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
private var parameters: RoomScreenCoordinatorParameters
|
||||
private var viewModel: RoomScreenViewModelProtocol
|
||||
private var composerViewModel: ComposerToolbarViewModel
|
||||
private var wysiwygViewModel: WysiwygComposerViewModel
|
||||
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
@@ -58,7 +60,8 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
composerViewModel = ComposerToolbarViewModel()
|
||||
wysiwygViewModel = WysiwygComposerViewModel(minHeight: 22, maxExpandedHeight: 250)
|
||||
composerViewModel = ComposerToolbarViewModel(wysiwygViewModel: wysiwygViewModel)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -111,6 +114,10 @@ final class RoomScreenCoordinator: CoordinatorProtocol {
|
||||
}
|
||||
|
||||
func toPresentable() -> AnyView {
|
||||
AnyView(RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar(context: composerViewModel.context)))
|
||||
let composerToolbar = ComposerToolbar(context: composerViewModel.context,
|
||||
wysiwygViewModel: wysiwygViewModel,
|
||||
keyCommandHandler: composerViewModel.handleKeyCommand)
|
||||
|
||||
return AnyView(RoomScreen(context: viewModel.context, composerToolbar: composerToolbar))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,8 +146,10 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
func process(composerAction: ComposerToolbarViewModelAction) {
|
||||
switch composerAction {
|
||||
case .sendMessage(let message, let mode):
|
||||
Task { await sendCurrentMessage(message, mode: mode) }
|
||||
case .sendMessage(let message, let html, let mode):
|
||||
Task { await sendCurrentMessage(message, html: html, mode: mode) }
|
||||
case .sendPlainTextMessage(let message, let mode):
|
||||
Task { await sendCurrentMessage(message, html: nil, mode: mode) }
|
||||
case .displayCameraPicker:
|
||||
actionsSubject.send(.displayCameraPicker)
|
||||
case .displayMediaPicker:
|
||||
@@ -160,7 +162,7 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
handlePasteOrDrop(provider)
|
||||
case .composerModeChanged(mode: let mode):
|
||||
trackComposerMode(mode)
|
||||
case .focusedChanged(isFocused: let isFocused):
|
||||
case .composerFocusedChanged(isFocused: let isFocused):
|
||||
composerFocusedSubject.send(isFocused)
|
||||
}
|
||||
}
|
||||
@@ -427,8 +429,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
return eventTimelineItem.properties.reactions.isEmpty && eventTimelineItem.sender == otherEventTimelineItem.sender
|
||||
}
|
||||
|
||||
private func sendCurrentMessage(_ currentMessage: String, mode: RoomScreenComposerMode) async {
|
||||
guard !currentMessage.isEmpty else {
|
||||
private func sendCurrentMessage(_ message: String, html: String?, mode: RoomScreenComposerMode) async {
|
||||
guard !message.isEmpty else {
|
||||
fatalError("This message should never be empty")
|
||||
}
|
||||
|
||||
@@ -436,11 +438,11 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
|
||||
|
||||
switch mode {
|
||||
case .reply(let itemId, _):
|
||||
await timelineController.sendMessage(currentMessage, inReplyTo: itemId)
|
||||
await timelineController.sendMessage(message, html: html, inReplyTo: itemId)
|
||||
case .edit(let originalItemId):
|
||||
await timelineController.editMessage(currentMessage, original: originalItemId)
|
||||
await timelineController.editMessage(message, html: html, original: originalItemId)
|
||||
default:
|
||||
await timelineController.sendMessage(currentMessage)
|
||||
await timelineController.sendMessage(message, html: html)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
struct RoomScreen: View {
|
||||
@ObservedObject var context: RoomScreenViewModel.Context
|
||||
@@ -22,7 +23,7 @@ struct RoomScreen: View {
|
||||
let composerToolbar: ComposerToolbar
|
||||
|
||||
private let attachmentButtonPadding = 10.0
|
||||
|
||||
|
||||
var body: some View {
|
||||
timeline
|
||||
.background(Color.compound.bgCanvasDefault.ignoresSafeArea())
|
||||
@@ -152,12 +153,10 @@ struct RoomScreen_Previews: PreviewProvider {
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
static let composerViewModel = ComposerToolbarViewModel()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar(context: composerViewModel.context))
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import WysiwygComposer
|
||||
|
||||
/// A table view wrapper that displays the timeline of a room.
|
||||
struct UITimelineView: UIViewControllerRepresentable {
|
||||
@@ -86,11 +87,9 @@ struct UITimelineView_Previews: PreviewProvider {
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
static let composerViewModel = ComposerToolbarViewModel()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar(context: composerViewModel.context))
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import Combine
|
||||
import SwiftUI
|
||||
|
||||
import SwiftUIIntrospect
|
||||
import WysiwygComposer
|
||||
|
||||
struct TimelineView: View {
|
||||
let viewState: TimelineViewState
|
||||
@@ -174,11 +175,9 @@ struct TimelineView_Previews: PreviewProvider {
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController)
|
||||
|
||||
static let composerViewModel = ComposerToolbarViewModel()
|
||||
|
||||
static var previews: some View {
|
||||
NavigationStack {
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar(context: composerViewModel.context))
|
||||
RoomScreen(context: viewModel.context, composerToolbar: ComposerToolbar.mock())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user