Skip to content

Commit

Permalink
Pinned Events Timeline actions and differentiation (#3182)
Browse files Browse the repository at this point in the history
  • Loading branch information
Velin92 authored Aug 22, 2024
1 parent d54e08e commit 4eb1ed5
Show file tree
Hide file tree
Showing 44 changed files with 671 additions and 200 deletions.
4 changes: 4 additions & 0 deletions ElementX.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
9C4EC28A921486B1775D7F8C /* IdentityConfirmedScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 307702DD66E7DDCDD9214784 /* IdentityConfirmedScreen.swift */; };
9C55746D8F6A3E35CFCF4A7A /* AuthenticationStartLogo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 598F01EBD0C4CC550C644418 /* AuthenticationStartLogo.swift */; };
9CBB04365408F9D6F46BA3A7 /* PinnedEventsTimelineFlowCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */; };
9D2E03DB175A6AB14589076D /* AnalyticsEvents in Frameworks */ = {isa = PBXBuildFile; productRef = 2A3F7BCCB18C15B30CCA39A9 /* AnalyticsEvents */; };
9D79B94493FB32249F7E472F /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = C705E605EF57C19DBE86FFA1 /* PlaceholderAvatarImage.swift */; };
9D9690D2FD4CD26FF670620F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C75EF87651B00A176AB08E97 /* AppDelegate.swift */; };
Expand Down Expand Up @@ -1869,6 +1870,7 @@
A436057DBEA1A23CA8CB1FD7 /* UIFont+AttributedStringBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIFont+AttributedStringBuilder.h"; sourceTree = "<group>"; };
A443FAE2EE820A5790C35C8D /* et */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = et; path = et.lproj/Localizable.strings; sourceTree = "<group>"; };
A4A1003A0F7A1DFB47F4E2D0 /* TimelineItemMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineItemMock.swift; sourceTree = "<group>"; };
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinnedEventsTimelineFlowCoordinator.swift; sourceTree = "<group>"; };
A58E93D91DE3288010390DEE /* EmojiDetectionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiDetectionTests.swift; sourceTree = "<group>"; };
A69869844D2B6F5BD9AABF85 /* OIDCConfigurationProxy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OIDCConfigurationProxy.swift; sourceTree = "<group>"; };
A6B19D10B102956066AF117B /* PollOptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3435,6 +3437,7 @@
A9B069D7772DDF6513E0F1B8 /* AuthenticationFlowCoordinator.swift */,
7367B3B9A8CAF902220F31D1 /* BugReportFlowCoordinator.swift */,
C3285BD95B564CA2A948E511 /* OnboardingFlowCoordinator.swift */,
A54AAF72E821B4084B7E4298 /* PinnedEventsTimelineFlowCoordinator.swift */,
9A008E57D52B07B78DFAD1BB /* RoomFlowCoordinator.swift */,
0833F51229E166BCA141D004 /* RoomRolesAndPermissionsFlowCoordinator.swift */,
D28F7A6CEEA4A2815B0F0F55 /* SettingsFlowCoordinator.swift */,
Expand Down Expand Up @@ -6503,6 +6506,7 @@
7708976CEE6AFB5CFAEFBA68 /* PillTextAttachment.swift in Sources */,
8C050A8012E6078BEAEF5BC8 /* PillTextAttachmentData.swift in Sources */,
7E2BB42805C59DB57E95610F /* PillView.swift in Sources */,
9CBB04365408F9D6F46BA3A7 /* PinnedEventsTimelineFlowCoordinator.swift in Sources */,
5D52925FEB1B780C65B0529F /* PinnedEventsTimelineScreen.swift in Sources */,
E184FFAD32342D3D6E2F89AA /* PinnedEventsTimelineScreenCoordinator.swift in Sources */,
FEC03105D1BDE0F49BD7F243 /* PinnedEventsTimelineScreenModels.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
"action_tap_for_options" = "Tap for options";
"action_try_again" = "Try again";
"action_unpin" = "Unpin";
"action_view_in_timeline" = "View in timeline";
"action_view_source" = "View source";
"action_yes" = "Yes";
"action.load_more" = "Load more";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//
// Copyright 2024 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Combine
import Foundation

enum PinnedEventsTimelineFlowCoordinatorAction {
case finished
case displayUser(userID: String)
case forwardedMessageToRoom(roomID: String)
case displayRoomScreenWithFocussedPin(eventID: String)
}

class PinnedEventsTimelineFlowCoordinator: FlowCoordinatorProtocol {
private let navigationStackCoordinator: NavigationStackCoordinator
private let userSession: UserSessionProtocol
private let roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol
private let roomProxy: JoinedRoomProxyProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let appMediator: AppMediatorProtocol

private let actionsSubject: PassthroughSubject<PinnedEventsTimelineFlowCoordinatorAction, Never> = .init()
var actionsPublisher: AnyPublisher<PinnedEventsTimelineFlowCoordinatorAction, Never> {
actionsSubject.eraseToAnyPublisher()
}

private var cancellables = Set<AnyCancellable>()

init(navigationStackCoordinator: NavigationStackCoordinator,
userSession: UserSessionProtocol,
roomTimelineControllerFactory: RoomTimelineControllerFactoryProtocol,
roomProxy: JoinedRoomProxyProtocol,
userIndicatorController: UserIndicatorControllerProtocol,
appMediator: AppMediatorProtocol) {
self.navigationStackCoordinator = navigationStackCoordinator
self.userSession = userSession
self.roomTimelineControllerFactory = roomTimelineControllerFactory
self.roomProxy = roomProxy
self.userIndicatorController = userIndicatorController
self.appMediator = appMediator
}

func start() {
Task { await presentPinnedEventsTimeline() }
}

func handleAppRoute(_ appRoute: AppRoute, animated: Bool) {
fatalError()
}

func clearRoute(animated: Bool) {
fatalError()
}

private func presentPinnedEventsTimeline() async {
let userID = userSession.clientProxy.userID
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
attributedStringBuilder: AttributedStringBuilder(mentionBuilder: MentionBuilder()),
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID))

guard let timelineController = await roomTimelineControllerFactory.buildRoomPinnedTimelineController(roomProxy: roomProxy, timelineItemFactory: timelineItemFactory) else {
fatalError("This can never fail because we allow this view to be presented only when the timeline is fully loaded and not nil")
}

let coordinator = PinnedEventsTimelineScreenCoordinator(parameters: .init(roomProxy: roomProxy,
timelineController: timelineController,
mediaProvider: userSession.mediaProvider,
mediaPlayerProvider: MediaPlayerProvider(),
voiceMessageMediaManager: userSession.voiceMessageMediaManager,
appMediator: appMediator))

coordinator.actions
.sink { [weak self] action in
guard let self else { return }

switch action {
case .dismiss:
actionsSubject.send(.finished)
case .displayUser(let userID):
actionsSubject.send(.displayUser(userID: userID))
case .presentLocationViewer(let geoURI, let description):
presentMapNavigator(geoURI: geoURI, description: description)
case .displayMessageForwarding(let forwardingItem):
presentMessageForwarding(with: forwardingItem)
case .displayRoomScreenWithFocussedPin(let eventID):
actionsSubject.send(.displayRoomScreenWithFocussedPin(eventID: eventID))
}
}
.store(in: &cancellables)

navigationStackCoordinator.setRootCoordinator(coordinator)
}

private func presentMapNavigator(geoURI: GeoURI, description: String?) {
let stackCoordinator = NavigationStackCoordinator()

let params = StaticLocationScreenCoordinatorParameters(interactionMode: .viewOnly(geoURI: geoURI, description: description), appMediator: appMediator)
let coordinator = StaticLocationScreenCoordinator(parameters: params)

coordinator.actions.sink { [weak self] action in
guard let self else { return }
switch action {
case .selectedLocation:
// We don't handle the sending/picker case in this flow
break
case .close:
self.navigationStackCoordinator.setSheetCoordinator(nil)
}
}
.store(in: &cancellables)

stackCoordinator.setRootCoordinator(coordinator)

navigationStackCoordinator.setSheetCoordinator(stackCoordinator)
}

private func presentMessageForwarding(with forwardingItem: MessageForwardingItem) {
guard let roomSummaryProvider = userSession.clientProxy.alternateRoomSummaryProvider else {
fatalError()
}

let stackCoordinator = NavigationStackCoordinator()

let parameters = MessageForwardingScreenCoordinatorParameters(forwardingItem: forwardingItem,
clientProxy: userSession.clientProxy,
roomSummaryProvider: roomSummaryProvider,
mediaProvider: userSession.mediaProvider,
userIndicatorController: userIndicatorController)
let coordinator = MessageForwardingScreenCoordinator(parameters: parameters)

coordinator.actions.sink { [weak self] action in
guard let self else { return }

switch action {
case .dismiss:
navigationStackCoordinator.setSheetCoordinator(nil)
case .sent(let roomID):
navigationStackCoordinator.setSheetCoordinator(nil)
actionsSubject.send(.forwardedMessageToRoom(roomID: roomID))
}
}
.store(in: &cancellables)

stackCoordinator.setRootCoordinator(coordinator)

navigationStackCoordinator.setSheetCoordinator(stackCoordinator)
}
}
Loading

0 comments on commit 4eb1ed5

Please sign in to comment.