Add quote and copy context menu actions.

This commit is contained in:
Stefan Ceriu
2022-04-18 15:13:30 +03:00
parent 7f1c24059f
commit 1e76faa1c8
6 changed files with 81 additions and 3 deletions
@@ -20,6 +20,11 @@ enum RoomScreenViewModelResult {
}
enum TimelineItemContextMenuAction: Hashable {
case copy
case quote
}
enum RoomScreenViewAction {
case loadPreviousPage
case itemAppeared(id: String)
@@ -34,6 +39,8 @@ struct RoomScreenViewState: BindableState {
var isBackPaginating = false
var bindings: RoomScreenViewStateBindings
var contextMenuBuilder: ((_ itemId: String) -> TimelineItemContextMenu)?
var sendButtonDisabled: Bool {
bindings.composerText.count == 0
}
@@ -56,6 +56,8 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
}
}.store(in: &cancellables)
state.contextMenuBuilder = buildContexMenuForItemId(_:)
buildTimelineViews()
}
@@ -93,4 +95,35 @@ class RoomScreenViewModel: RoomScreenViewModelType, RoomScreenViewModelProtocol
state.items = stateItems
}
// MARK: ContextMenus
private func buildContexMenuForItemId(_ itemId: String) -> TimelineItemContextMenu {
TimelineItemContextMenu(contextMenuActions: self.contextMenuActionsForItemId(itemId)) { [weak self] action in
self?.processContentMenuAction(action, itemId: itemId)
}
}
private func contextMenuActionsForItemId(_ itemId: String) -> [TimelineItemContextMenuAction] {
guard let timelineItem = self.timelineController.timelineItems.first(where: { $0.id == itemId }),
timelineItem is EventBasedTimelineItemProtocol else {
return []
}
return [.copy, .quote]
}
private func processContentMenuAction(_ action: TimelineItemContextMenuAction, itemId: String) {
guard let timelineItem = self.timelineController.timelineItems.first(where: { $0.id == itemId }),
let item = timelineItem as? EventBasedTimelineItemProtocol else {
return
}
switch action {
case .copy:
UIPasteboard.general.string = item.text
case .quote:
state.bindings.composerText = "> \(item.text)"
}
}
}
@@ -129,9 +129,9 @@ private struct UITextViewWrapper: UIViewRepresentable {
self.maxHeight = maxHeight
}
func textViewDidChange(_ uiView: UITextView) {
text.wrappedValue = uiView.text
UITextViewWrapper.recalculateHeight(view: uiView,
func textViewDidChange(_ textView: UITextView) {
text.wrappedValue = textView.text
UITextViewWrapper.recalculateHeight(view: textView,
result: calculatedHeight,
maxHeight: maxHeight)
}
@@ -0,0 +1,31 @@
//
// TimelineItemContextMenu.swift
// ElementX
//
// Created by Stefan Ceriu on 18/04/2022.
// Copyright © 2022 element.io. All rights reserved.
//
import SwiftUI
public struct TimelineItemContextMenu: View {
let contextMenuActions: [TimelineItemContextMenuAction]
let callback: (TimelineItemContextMenuAction) -> Void
@ViewBuilder
public var body: some View {
ForEach(contextMenuActions, id: \.self) { item in
switch item {
case .copy:
Button("Copy") {
callback(item)
}
case .quote:
Button("Quote") {
callback(item)
}
}
}
}
}
@@ -36,6 +36,9 @@ struct TimelineItemList: View {
// No idea why previews don't work otherwise
ForEach(isPreview ? context.viewState.items : timelineItems) { timelineItem in
timelineItem
.contextMenu(menuItems: {
context.viewState.contextMenuBuilder?(timelineItem.id)
})
.listRowSeparator(.hidden)
.onAppear {
context.send(viewAction: .itemAppeared(id: timelineItem.id))