Bundle ClientProxy & MediaProvider injections together in UserSession.

This commit is contained in:
Doug
2025-08-27 17:25:28 +01:00
committed by Doug
parent b34816e159
commit f67f826bb7
74 changed files with 315 additions and 499 deletions
@@ -33,7 +33,7 @@ enum TimelineInteractionHandlerAction {
class TimelineInteractionHandler {
private let roomProxy: JoinedRoomProxyProtocol
private let timelineController: TimelineControllerProtocol
private let mediaProvider: MediaProviderProtocol
private let userSession: UserSessionProtocol
private let mediaPlayerProvider: MediaPlayerProviderProtocol
private let voiceMessageRecorder: VoiceMessageRecorderProtocol
private let voiceMessageMediaManager: VoiceMessageMediaManagerProtocol
@@ -44,7 +44,6 @@ class TimelineInteractionHandler {
private let emojiProvider: EmojiProviderProtocol
private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let pollInteractionHandler: PollInteractionHandlerProtocol
private let clientProxy: ClientProxyProtocol
private let actionsSubject: PassthroughSubject<TimelineInteractionHandlerAction, Never> = .init()
var actions: AnyPublisher<TimelineInteractionHandlerAction, Never> {
@@ -61,7 +60,7 @@ class TimelineInteractionHandler {
init(roomProxy: JoinedRoomProxyProtocol,
timelineController: TimelineControllerProtocol,
mediaProvider: MediaProviderProtocol,
userSession: UserSessionProtocol,
mediaPlayerProvider: MediaPlayerProviderProtocol,
voiceMessageMediaManager: VoiceMessageMediaManagerProtocol,
voiceMessageRecorder: VoiceMessageRecorderProtocol,
@@ -70,11 +69,10 @@ class TimelineInteractionHandler {
appSettings: AppSettings,
analyticsService: AnalyticsService,
emojiProvider: EmojiProviderProtocol,
timelineControllerFactory: TimelineControllerFactoryProtocol,
clientProxy: ClientProxyProtocol) {
timelineControllerFactory: TimelineControllerFactoryProtocol) {
self.roomProxy = roomProxy
self.timelineController = timelineController
self.mediaProvider = mediaProvider
self.userSession = userSession
self.mediaPlayerProvider = mediaPlayerProvider
self.voiceMessageMediaManager = voiceMessageMediaManager
self.voiceMessageRecorder = voiceMessageRecorder
@@ -84,7 +82,6 @@ class TimelineInteractionHandler {
self.analyticsService = analyticsService
self.emojiProvider = emojiProvider
self.timelineControllerFactory = timelineControllerFactory
self.clientProxy = clientProxy
pollInteractionHandler = PollInteractionHandler(analyticsService: analyticsService,
timelineController: timelineController)
@@ -582,14 +579,14 @@ class TimelineInteractionHandler {
presentation: newTimelinePresentation,
roomProxy: roomProxy,
timelineItemFactory: timelineItemFactory,
mediaProvider: mediaProvider) else {
mediaProvider: userSession.mediaProvider) else {
MXLog.error("Failed presenting media timeline")
return .none
}
let timelineViewModel = TimelineViewModel(roomProxy: roomProxy,
timelineController: timelineController,
mediaProvider: mediaProvider,
userSession: userSession,
mediaPlayerProvider: mediaPlayerProvider,
voiceMessageMediaManager: voiceMessageMediaManager,
userIndicatorController: userIndicatorController,
@@ -597,8 +594,7 @@ class TimelineInteractionHandler {
appSettings: appSettings,
analyticsService: analyticsService,
emojiProvider: emojiProvider,
timelineControllerFactory: timelineControllerFactory,
clientProxy: clientProxy)
timelineControllerFactory: timelineControllerFactory)
return .displayMediaPreview(item: item, timelineViewModel: .new(timelineViewModel))
} else {
@@ -23,7 +23,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
private let roomProxy: JoinedRoomProxyProtocol
private let timelineController: TimelineControllerProtocol
private let mediaProvider: MediaProviderProtocol
private let userSession: UserSessionProtocol
private let mediaPlayerProvider: MediaPlayerProviderProtocol
private let userIndicatorController: UserIndicatorControllerProtocol
private let appMediator: AppMediatorProtocol
@@ -31,7 +31,6 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
private let analyticsService: AnalyticsService
private let emojiProvider: EmojiProviderProtocol
private let timelineControllerFactory: TimelineControllerFactoryProtocol
private let clientProxy: ClientProxyProtocol
private let timelineInteractionHandler: TimelineInteractionHandler
@@ -50,7 +49,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
init(roomProxy: JoinedRoomProxyProtocol,
focussedEventID: String? = nil,
timelineController: TimelineControllerProtocol,
mediaProvider: MediaProviderProtocol,
userSession: UserSessionProtocol,
mediaPlayerProvider: MediaPlayerProviderProtocol,
voiceMessageMediaManager: VoiceMessageMediaManagerProtocol,
userIndicatorController: UserIndicatorControllerProtocol,
@@ -58,25 +57,23 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
appSettings: AppSettings,
analyticsService: AnalyticsService,
emojiProvider: EmojiProviderProtocol,
timelineControllerFactory: TimelineControllerFactoryProtocol,
clientProxy: ClientProxyProtocol) {
self.timelineController = timelineController
self.mediaProvider = mediaProvider
self.mediaPlayerProvider = mediaPlayerProvider
timelineControllerFactory: TimelineControllerFactoryProtocol) {
self.roomProxy = roomProxy
self.timelineController = timelineController
self.userSession = userSession
self.mediaPlayerProvider = mediaPlayerProvider
self.appSettings = appSettings
self.analyticsService = analyticsService
self.userIndicatorController = userIndicatorController
self.appMediator = appMediator
self.emojiProvider = emojiProvider
self.timelineControllerFactory = timelineControllerFactory
self.clientProxy = clientProxy
let voiceMessageRecorder = VoiceMessageRecorder(audioRecorder: AudioRecorder(), mediaPlayerProvider: mediaPlayerProvider)
timelineInteractionHandler = TimelineInteractionHandler(roomProxy: roomProxy,
timelineController: timelineController,
mediaProvider: mediaProvider,
userSession: userSession,
mediaPlayerProvider: mediaPlayerProvider,
voiceMessageMediaManager: voiceMessageMediaManager,
voiceMessageRecorder: voiceMessageRecorder,
@@ -85,10 +82,9 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
appSettings: appSettings,
analyticsService: analyticsService,
emojiProvider: emojiProvider,
timelineControllerFactory: timelineControllerFactory,
clientProxy: clientProxy)
timelineControllerFactory: timelineControllerFactory)
let hideTimelineMedia = switch clientProxy.timelineMediaVisibilityPublisher.value {
let hideTimelineMedia = switch userSession.clientProxy.timelineMediaVisibilityPublisher.value {
case .always:
false
case .privateOnly:
@@ -109,7 +105,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
emojiProvider: emojiProvider,
mapTilerConfiguration: appSettings.mapTilerConfiguration,
bindings: .init(reactionsCollapsed: [:])),
mediaProvider: mediaProvider)
mediaProvider: userSession.mediaProvider)
if focussedEventID != nil {
// The timeline controller will start loading a detached timeline.
@@ -132,11 +128,11 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
}
state.roomNameForIDResolver = { [weak self] roomID in
self?.clientProxy.roomSummaryForIdentifier(roomID)?.name
self?.userSession.clientProxy.roomSummaryForIdentifier(roomID)?.name
}
state.roomNameForAliasResolver = { [weak self] alias in
self?.clientProxy.roomSummaryForAlias(alias)?.name
self?.userSession.clientProxy.roomSummaryForAlias(alias)?.name
}
state.timelineState.paginationState = timelineController.paginationState
@@ -290,7 +286,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
roomProxy: roomProxy,
userIndicatorController: userIndicatorController,
analyticsService: analyticsService,
mediaProvider: mediaProvider)
mediaProvider: userSession.mediaProvider)
viewModel.actions.sink { [weak self] action in
guard let self else { return }
@@ -509,7 +505,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
.weakAssign(to: \.state.areThreadsEnabled, on: self)
.store(in: &cancellables)
clientProxy.timelineMediaVisibilityPublisher
userSession.clientProxy.timelineMediaVisibilityPublisher
.removeDuplicates()
.flatMap { [weak self] timelineMediaVisibility -> AnyPublisher<Bool, Never> in
switch timelineMediaVisibility {
@@ -738,7 +734,7 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
return TimelineMediaPreviewViewModel(initialItem: item,
timelineViewModel: timelineViewModel,
mediaProvider: mediaProvider,
mediaProvider: userSession.mediaProvider,
photoLibraryManager: PhotoLibraryManager(),
userIndicatorController: userIndicatorController,
appMediator: appMediator)
@@ -928,18 +924,18 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
let pillViewState: PillViewState
switch room {
case .roomAlias(let alias):
let roomSummary = clientProxy.roomSummaryForAlias(alias)
let roomSummary = userSession.clientProxy.roomSummaryForAlias(alias)
pillViewState = .reference(displayText: PillUtilities.eventPillDisplayText(roomName: roomSummary?.name, rawRoomText: alias))
case .roomID(let id):
let roomSummary = clientProxy.roomSummaryForIdentifier(id)
let roomSummary = userSession.clientProxy.roomSummaryForIdentifier(id)
pillViewState = .reference(displayText: PillUtilities.eventPillDisplayText(roomName: roomSummary?.name, rawRoomText: id))
}
pillContext.viewState = pillViewState
case .roomAlias(let alias):
let roomSummary = clientProxy.roomSummaryForAlias(alias)
let roomSummary = userSession.clientProxy.roomSummaryForAlias(alias)
pillContext.viewState = .reference(displayText: PillUtilities.roomPillDisplayText(roomName: roomSummary?.name, rawRoomText: alias))
case .roomID(let id):
let roomSummary = clientProxy.roomSummaryForIdentifier(id)
let roomSummary = userSession.clientProxy.roomSummaryForIdentifier(id)
pillContext.viewState = .reference(displayText: PillUtilities.roomPillDisplayText(roomName: roomSummary?.name, rawRoomText: id))
}
}
@@ -1003,7 +999,7 @@ extension TimelineViewModel {
return TimelineViewModel(roomProxy: roomProxy,
focussedEventID: nil,
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init(clientProxy: clientProxyMock)),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
@@ -1011,8 +1007,7 @@ extension TimelineViewModel {
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: clientProxyMock)
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}
}
@@ -45,7 +45,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
let roomProxyMock = JoinedRoomProxyMock(.init(name: "Room", members: members))
let mock = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: UserIndicatorControllerMock(),
@@ -53,8 +53,7 @@ struct ReadReceiptsSummaryView_Previews: PreviewProvider, TestablePreview {
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: ClientProxyMock(.init()))
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
return mock
}()
@@ -334,7 +334,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
return TimelineViewModel(roomProxy: roomProxy,
focussedEventID: nil,
timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
@@ -342,8 +342,7 @@ struct TimelineItemBubbledStylerView_Previews: PreviewProvider, TestablePreview
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: ClientProxyMock(.init()))
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
}()
static var previews: some View {
@@ -80,7 +80,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
static let viewModel = TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Test", members: members)),
timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
@@ -88,8 +88,7 @@ struct TimelineReadReceiptsView_Previews: PreviewProvider, TestablePreview {
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: ClientProxyMock(.init()))
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static let singleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now")]
static let doubleReceipt = [ReadReceipt(userID: RoomMemberProxyMock.mockAlice.userID, formattedTimestamp: "Now"),
@@ -90,7 +90,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
focussedEventID: focussedEventID,
timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
@@ -98,8 +98,7 @@ struct HighlightedTimelineItemTimeline_Previews: PreviewProvider {
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: ClientProxyMock(.init()))
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static var previews: some View {
NavigationStack {
@@ -142,7 +142,7 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview {
static let roomViewModel = RoomScreenViewModel.mock(roomProxyMock: roomProxyMock)
static let timelineViewModel = TimelineViewModel(roomProxy: roomProxyMock,
timelineController: MockTimelineController(),
mediaProvider: MediaProviderMock(configuration: .init()),
userSession: UserSessionMock(.init()),
mediaPlayerProvider: MediaPlayerProviderMock(),
voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
userIndicatorController: ServiceLocator.shared.userIndicatorController,
@@ -150,8 +150,7 @@ struct TimelineView_Previews: PreviewProvider, TestablePreview {
appSettings: ServiceLocator.shared.settings,
analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: ClientProxyMock(.init()))
timelineControllerFactory: TimelineControllerFactoryMock(.init()))
static var previews: some View {
NavigationStack {