Skip to content

Commit

Permalink
Switch on TimelineKind instead of having an isPinnedEventsTimeline Bool.
Browse files Browse the repository at this point in the history
  • Loading branch information
pixlwave committed Dec 11, 2024
1 parent 4207bc4 commit e2f1fee
Show file tree
Hide file tree
Showing 19 changed files with 52 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Foundation
typealias TimelineMediaPreviewViewModelType = StateStoreViewModel<TimelineMediaPreviewViewState, TimelineMediaPreviewViewAction>

class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
private let isFromRoomScreen: Bool
private let timelineViewModel: TimelineViewModelProtocol
private let mediaProvider: MediaProviderProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
Expand All @@ -22,11 +21,9 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
}

init(initialItem: EventBasedMessageTimelineItemProtocol,
isFromRoomScreen: Bool,
timelineViewModel: TimelineViewModelProtocol,
mediaProvider: MediaProviderProtocol,
userIndicatorController: UserIndicatorControllerProtocol) {
self.isFromRoomScreen = true
self.timelineViewModel = timelineViewModel
self.mediaProvider = mediaProvider

Expand Down Expand Up @@ -94,7 +91,7 @@ class TimelineMediaPreviewViewModel: TimelineMediaPreviewViewModelType {
isDM: timelineContext.viewState.isEncryptedOneToOneRoom,
isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled,
isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled,
presentationContext: isFromRoomScreen ? .mediaDetailsOnRoom : .mediaDetailsOnBrowser,
timelineKind: timelineContext.viewState.timelineKind,
emojiProvider: timelineContext.viewState.emojiProvider)
state.currentItemActions = provider.makeActions()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,6 @@ struct TimelineMediaQuickLook_Previews: PreviewProvider {
contentType: .pdf))

return TimelineMediaPreviewViewModel(initialItem: item,
isFromRoomScreen: false,
timelineViewModel: TimelineViewModel.mock,
mediaProvider: MediaProviderMock(configuration: .init()),
userIndicatorController: UserIndicatorControllerMock())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ import UniformTypeIdentifiers
struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePreview {
static let viewModel = makeViewModel(contentType: .jpeg, isOutgoing: true)
static let unknownTypeViewModel = makeViewModel()
static let fromRoomViewModel = makeViewModel(isFromRoomScreen: true)
static let presentedOnRoomViewModel = makeViewModel(isPresentedOnRoomScreen: true)

static var previews: some View {
TimelineMediaPreviewDetailsView(context: viewModel.context)
Expand All @@ -151,12 +151,12 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie
.previewDisplayName("Unknown type")
.snapshotPreferences(delay: 0.1)

TimelineMediaPreviewDetailsView(context: fromRoomViewModel.context)
TimelineMediaPreviewDetailsView(context: presentedOnRoomViewModel.context)
.previewDisplayName("Incoming on Room")
.snapshotPreferences(delay: 0.1)
}

static func makeViewModel(contentType: UTType? = nil, isOutgoing: Bool = false, isFromRoomScreen: Bool = false) -> TimelineMediaPreviewViewModel {
static func makeViewModel(contentType: UTType? = nil, isOutgoing: Bool = false, isPresentedOnRoomScreen: Bool = false) -> TimelineMediaPreviewViewModel {
let item = ImageRoomTimelineItem(id: .randomEvent,
timestamp: .mock,
isOutgoing: isOutgoing,
Expand All @@ -171,9 +171,9 @@ struct TimelineMediaPreviewDetailsView_Previews: PreviewProvider, TestablePrevie
thumbnailInfo: .mockThumbnail,
contentType: contentType))

let timelineKind = TimelineKind.media(isPresentedOnRoomScreen ? .roomScreen : .mediaFilesScreen)
return TimelineMediaPreviewViewModel(initialItem: item,
isFromRoomScreen: isFromRoomScreen,
timelineViewModel: TimelineViewModel.mock,
timelineViewModel: TimelineViewModel.mock(timelineKind: timelineKind),
mediaProvider: MediaProviderMock(configuration: .init()),
userIndicatorController: UserIndicatorControllerMock())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ struct TimelineMediaPreviewRedactConfirmationView_Previews: PreviewProvider, Tes
contentType: contentType))

return TimelineMediaPreviewViewModel(initialItem: item,
isFromRoomScreen: false,
timelineViewModel: TimelineViewModel.mock,
mediaProvider: MediaProviderMock(configuration: .init()),
userIndicatorController: UserIndicatorControllerMock())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
}

let viewModel = TimelineMediaPreviewViewModel(initialItem: item,
isFromRoomScreen: false,
timelineViewModel: activeTimelineViewModel,
mediaProvider: mediaProvider,
userIndicatorController: userIndicatorController)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ extension View {

struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
static let timelineViewModel: TimelineViewModel = {
let timelineController = MockRoomTimelineController(timelineKind: .media)
let timelineController = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen))
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
timelineController: timelineController,
mediaProvider: MediaProviderMock(configuration: .init()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct PinnedEventsTimelineScreen: View {
isDM: timelineContext.viewState.isEncryptedOneToOneRoom,
isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled,
isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled,
presentationContext: .pinnedEvents,
timelineKind: timelineContext.viewState.timelineKind,
emojiProvider: timelineContext.viewState.emojiProvider)
.makeActions()
if let actions {
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Screens/RoomScreen/View/RoomScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ struct RoomScreen: View {
isDM: timelineContext.viewState.isEncryptedOneToOneRoom,
isViewSourceEnabled: timelineContext.viewState.isViewSourceEnabled,
isCreateMediaCaptionsEnabled: timelineContext.viewState.isCreateMediaCaptionsEnabled,
presentationContext: .room,
timelineKind: timelineContext.viewState.timelineKind,
emojiProvider: timelineContext.viewState.emojiProvider)
.makeActions()
if let actions {
Expand Down
2 changes: 1 addition & 1 deletion ElementX/Sources/Screens/Timeline/TimelineModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ enum TimelineComposerAction {
}

struct TimelineViewState: BindableState {
let isPinnedEventsTimeline: Bool
let timelineKind: TimelineKind
var roomID: String
var members: [String: RoomMemberState] = [:]
var typingMembers: [String] = []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ class TimelineTableViewController: UIViewController {
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, TimelineUniqueId>()

// We don't want to display the typing notification in this timeline
if !coordinator.context.viewState.isPinnedEventsTimeline {
if coordinator.context.viewState.timelineKind != .pinned {
snapshot.appendSections([.typingIndicator])
snapshot.appendItems([TimelineUniqueId(id: TimelineTypingIndicatorCell.reuseIdentifier)])
}
Expand Down
46 changes: 19 additions & 27 deletions ElementX/Sources/Screens/Timeline/TimelineViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
appSettings: appSettings,
analyticsService: analyticsService)

super.init(initialViewState: TimelineViewState(isPinnedEventsTimeline: timelineController.timelineKind == .pinned,
super.init(initialViewState: TimelineViewState(timelineKind: timelineController.timelineKind,
roomID: roomProxy.id,
isEncryptedOneToOneRoom: roomProxy.isEncryptedOneToOneRoom,
timelineState: TimelineState(focussedEvent: focussedEventID.map { .init(eventID: $0, appearance: .immediate) }),
Expand Down Expand Up @@ -690,13 +690,13 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
} else {
for (index, item) in itemGroup.enumerated() {
if index == 0 {
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .first),
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .first),
forKey: item.id.uniqueID)
} else if index == itemGroup.count - 1 {
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .last),
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .last),
forKey: item.id.uniqueID)
} else {
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.isPinnedEventsTimeline ? .single : .middle),
timelineItemsDictionary.updateValue(updateViewState(item: item, groupStyle: state.timelineKind == .pinned ? .single : .middle),
forKey: item.id.uniqueID)
}
}
Expand Down Expand Up @@ -868,29 +868,21 @@ private extension RoomInfoProxy {
// MARK: - Mocks

extension TimelineViewModel {
static let mock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
focussedEventID: nil,
timelineController: MockRoomTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings))

static let pinnedEventsTimelineMock = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
focussedEventID: nil,
timelineController: MockRoomTimelineController(timelineKind: .pinned),
mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings))
static let mock = mock(timelineKind: .live)

static func mock(timelineKind: TimelineKind = .live) -> TimelineViewModel {
TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
focussedEventID: nil,
timelineController: MockRoomTimelineController(timelineKind: timelineKind),
mediaProvider: MediaProviderMock(configuration: .init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
appMediator: AppMediatorMock.default,
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings))
}
}

extension EnvironmentValues {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ struct TimelineItemMenu_Previews: PreviewProvider, TestablePreview {
isDM: true,
isViewSourceEnabled: true,
isCreateMediaCaptionsEnabled: true,
presentationContext: .room,
timelineKind: .live,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings))
guard let actions = provider.makeActions() else { return nil }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import Foundation

@MainActor
struct TimelineItemMenuActionProvider {
enum PresentationContext { case room, pinnedEvents, mediaDetailsOnBrowser, mediaDetailsOnRoom }

let timelineItem: RoomTimelineItemProtocol
let canCurrentUserRedactSelf: Bool
let canCurrentUserRedactOthers: Bool
Expand All @@ -19,7 +17,7 @@ struct TimelineItemMenuActionProvider {
let isDM: Bool
let isViewSourceEnabled: Bool
let isCreateMediaCaptionsEnabled: Bool
let presentationContext: PresentationContext
let timelineKind: TimelineKind
let emojiProvider: EmojiProviderProtocol

// swiftlint:disable:next cyclomatic_complexity
Expand All @@ -41,7 +39,7 @@ struct TimelineItemMenuActionProvider {
var actions: [TimelineItemMenuAction] = []
var secondaryActions: [TimelineItemMenuAction] = []

if presentationContext == .pinnedEvents || presentationContext == .mediaDetailsOnBrowser {
if timelineKind == .pinned || timelineKind == .media(.mediaFilesScreen) {
actions.append(.viewInRoomTimeline)
}

Expand Down Expand Up @@ -105,15 +103,15 @@ struct TimelineItemMenuActionProvider {
secondaryActions.append(.redact)
}

switch presentationContext {
case .room:
break // viewInRoomTimeline is added conditionally so we don't need to filter.
case .pinnedEvents:
switch timelineKind {
case .pinned:
actions = actions.filter(\.canAppearInPinnedEventsTimeline)
secondaryActions = secondaryActions.filter(\.canAppearInPinnedEventsTimeline)
case .mediaDetailsOnBrowser, .mediaDetailsOnRoom:
case .media:
actions = actions.filter(\.canAppearInMediaDetails)
secondaryActions = secondaryActions.filter(\.canAppearInMediaDetails)
case .live, .detached:
break // viewInRoomTimeline is the only non-room item and was added conditionally.
}

if item.hasFailedToSend {
Expand All @@ -125,11 +123,10 @@ struct TimelineItemMenuActionProvider {
actions = actions.filter(\.canAppearInRedacted)
secondaryActions = secondaryActions.filter(\.canAppearInRedacted)
}

let isReactable = timelineKind == .live || timelineKind == .detached ? item.isReactable : false

return .init(isReactable: presentationContext == .room ? item.isReactable : false,
actions: actions,
secondaryActions: secondaryActions,
emojiProvider: emojiProvider)
return .init(isReactable: isReactable, actions: actions, secondaryActions: secondaryActions, emojiProvider: emojiProvider)
}

private func makeEncryptedItemActions(_ encryptedItem: EncryptedRoomTimelineItem) -> TimelineItemMenuActions? {
Expand Down
Loading

0 comments on commit e2f1fee

Please sign in to comment.