Implemented message forwarding for media previews and media timelines (#4579)

* implemented message forwarding for media previews and media timelines

* updated tests

* pr suggestion

* fix tests

* fix tests
This commit is contained in:
Mauro
2025-10-07 14:34:14 +02:00
committed by GitHub
parent 6def8e5973
commit e7ee0af70d
42 changed files with 166 additions and 50 deletions
@@ -270,6 +270,11 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
}
}
func makeForwardingItem(for itemID: TimelineItemIdentifier) async -> MessageForwardingItem? {
guard let content = await timelineController.messageEventContent(for: itemID) else { return nil }
return .init(id: itemID, roomID: roomProxy.id, content: content)
}
// MARK: - Private
private func handleTappedOnSenderDetails(sender: TimelineItemSender) {
@@ -899,8 +904,8 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
// MARK: - Message forwarding
private func forwardMessage(itemID: TimelineItemIdentifier) async {
guard let content = await timelineController.messageEventContent(for: itemID) else { return }
actionsSubject.send(.displayMessageForwarding(forwardingItem: .init(id: itemID, roomID: roomProxy.id, content: content)))
guard let forwardingItem = await makeForwardingItem(for: itemID) else { return }
actionsSubject.send(.displayMessageForwarding(forwardingItem: forwardingItem))
}
// MARK: Pills
@@ -17,4 +17,7 @@ protocol TimelineViewModelProtocol {
func process(composerAction: ComposerToolbarViewModelAction)
/// Updates the timeline to show and highlight the item with the corresponding event ID.
func focusOnEvent(eventID: String) async
/// Handles getting the content to forward an item given its item ID.
func makeForwardingItem(for itemID: TimelineItemIdentifier) async -> MessageForwardingItem?
}
@@ -131,7 +131,7 @@ enum TimelineItemMenuAction: Identifiable, Hashable {
var canAppearInMediaDetails: Bool {
switch self {
case .viewInRoomTimeline, .share, .save, .redact:
case .viewInRoomTimeline, .share, .save, .redact, .forward:
true
default:
false
@@ -323,12 +323,27 @@ private extension View {
struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview {
static let viewModel: TimelineViewModel = {
ServiceLocator.shared.settings.threadsEnabled = true
return TimelineViewModel.mock
let appSettings = AppSettings()
appSettings.threadsEnabled = true
let roomProxy = JoinedRoomProxyMock(.init())
return TimelineViewModel(roomProxy: roomProxy,
focussedEventID: nil,
timelineController: MockTimelineController(),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default,
appSettings: appSettings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
linkMetadataProvider: LinkMetadataProvider(),
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static let viewModelWithPins: TimelineViewModel = {
ServiceLocator.shared.settings.threadsEnabled = true
let appSettings = AppSettings()
appSettings.threadsEnabled = true
let roomProxy = JoinedRoomProxyMock(.init(name: "Preview Room", pinnedEventIDs: ["pinned"]))
return TimelineViewModel(roomProxy: roomProxy,
@@ -338,7 +353,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
mediaPlayerProvider: MediaPlayerProviderMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
appSettings: appSettings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
linkMetadataProvider: LinkMetadataProvider(),