Fix state change commented by mistake and simplify snapshot test setup (+ a couple of warnings)

This commit is contained in:
Stefan Ceriu
2024-12-17 09:31:00 +02:00
committed by Stefan Ceriu
parent 52463cdf8f
commit 598e604851
7 changed files with 72 additions and 41 deletions
@@ -88,13 +88,40 @@ struct KnockRequestsListScreen_Previews: PreviewProvider, TestablePreview {
static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([])) static let emptyViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([]))
static let singleRequestViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello"))])) static let singleRequestViewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([KnockRequestProxyMock(.init(eventID: "1",
userID: "@alice:matrix.org",
displayName: "Alice",
avatarURL: nil,
timestamp: "Now",
reason: "Hello"))]))
static let viewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([KnockRequestProxyMock(.init(eventID: "1", userID: "@alice:matrix.org", displayName: "Alice", avatarURL: nil, timestamp: "Now", reason: "Hello")), static let viewModel = KnockRequestsListScreenViewModel.mockWithRequestsState(.loaded([
// swiftlint:disable:next line_length KnockRequestProxyMock(.init(eventID: "1",
KnockRequestProxyMock(.init(eventID: "2", userID: "@bob:matrix.org", displayName: "Bob", avatarURL: nil, timestamp: "Now", reason: "Hello this one is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason")), userID: "@alice:matrix.org",
KnockRequestProxyMock(.init(eventID: "3", userID: "@charlie:matrix.org", displayName: "Charlie", avatarURL: nil, timestamp: "Now", reason: nil)), displayName: "Alice",
KnockRequestProxyMock(.init(eventID: "4", userID: "@dan:matrix.org", displayName: "Dan", avatarURL: nil, timestamp: "Now", reason: "Hello! It's a me! Dan!"))])) avatarURL: nil,
timestamp: "Now",
reason: "Hello")),
KnockRequestProxyMock(.init(eventID: "2",
userID: "@bob:matrix.org",
displayName: "Bob",
avatarURL: nil,
timestamp: "Now",
// swiftlint:disable:next line_length
reason: "Hello this one is a very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very very long reason")),
KnockRequestProxyMock(.init(eventID: "3",
userID: "@charlie:matrix.org",
displayName: "Charlie",
avatarURL: nil,
timestamp: "Now",
reason: nil)),
KnockRequestProxyMock(.init(eventID: "4",
userID: "@dan:matrix.org",
displayName: "Dan",
avatarURL: nil,
timestamp: "Now",
reason: "Hello! It's a me! Dan!"))
]))
static var previews: some View { static var previews: some View {
NavigationStack { NavigationStack {
@@ -23,8 +23,9 @@ struct MediaEventsTimelineGroup: Identifiable {
} }
struct MediaEventsTimelineScreenViewState: BindableState { struct MediaEventsTimelineScreenViewState: BindableState {
var hasReachedTimelineStart = false
var isBackPaginating = false var isBackPaginating = false
var shouldShowEmptyState = false
var groups = [MediaEventsTimelineGroup]() var groups = [MediaEventsTimelineGroup]()
var activeTimelineContextProvider: (() -> TimelineViewModel.Context)! var activeTimelineContextProvider: (() -> TimelineViewModel.Context)!
@@ -32,10 +33,6 @@ struct MediaEventsTimelineScreenViewState: BindableState {
var bindings: MediaEventsTimelineScreenViewStateBindings var bindings: MediaEventsTimelineScreenViewStateBindings
var currentPreviewItemID: TimelineItemIdentifier? var currentPreviewItemID: TimelineItemIdentifier?
var shouldShowEmptyState: Bool {
groups.isEmpty && hasReachedTimelineStart
}
} }
struct MediaEventsTimelineScreenViewStateBindings { struct MediaEventsTimelineScreenViewStateBindings {
@@ -35,8 +35,8 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
init(mediaTimelineViewModel: TimelineViewModelProtocol, init(mediaTimelineViewModel: TimelineViewModelProtocol,
filesTimelineViewModel: TimelineViewModelProtocol, filesTimelineViewModel: TimelineViewModelProtocol,
mediaProvider: MediaProviderProtocol,
initialViewState: MediaEventsTimelineScreenViewState = .init(bindings: .init(screenMode: .media)), initialViewState: MediaEventsTimelineScreenViewState = .init(bindings: .init(screenMode: .media)),
mediaProvider: MediaProviderProtocol,
userIndicatorController: UserIndicatorControllerProtocol) { userIndicatorController: UserIndicatorControllerProtocol) {
self.mediaTimelineViewModel = mediaTimelineViewModel self.mediaTimelineViewModel = mediaTimelineViewModel
self.filesTimelineViewModel = filesTimelineViewModel self.filesTimelineViewModel = filesTimelineViewModel
@@ -130,8 +130,8 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
state.groups = newGroups state.groups = newGroups
state.isBackPaginating = (timelineViewState.timelineState.paginationState.backward == .paginating) state.isBackPaginating = timelineViewState.timelineState.paginationState.backward == .paginating
// state.hasReachedTimelineStart = (timelineViewState.timelineState.paginationState.backward == .timelineEndReached) state.shouldShowEmptyState = newGroups.isEmpty && timelineViewState.timelineState.paginationState.backward == .timelineEndReached
backPaginateIfNecessary(paginationStatus: timelineViewState.timelineState.paginationState.backward) backPaginateIfNecessary(paginationStatus: timelineViewState.timelineState.paginationState.backward)
} }
@@ -157,10 +157,9 @@ class MediaEventsTimelineScreenViewModel: MediaEventsTimelineScreenViewModelType
actionsSubject.send(.viewItem(.init(item: item, actionsSubject.send(.viewItem(.init(item: item,
viewModel: activeTimelineViewModel, viewModel: activeTimelineViewModel,
namespace: namespace, namespace: namespace) { [weak self] in
completion: { [weak self] in self?.state.currentPreviewItemID = nil
self?.state.currentPreviewItemID = nil }))
})))
// Set the current item in the next run loop so that (hopefully) the presentation will be ready before we flip the thumbnail. // Set the current item in the next run loop so that (hopefully) the presentation will be ready before we flip the thumbnail.
Task { state.currentPreviewItemID = item.id } Task { state.currentPreviewItemID = item.id }
@@ -225,8 +225,8 @@ struct MediaEventsTimelineScreen: View {
struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview { struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
static let mediaViewModel = makeViewModel(screenMode: .media) static let mediaViewModel = makeViewModel(screenMode: .media)
static let filesViewModel = makeViewModel(screenMode: .files) static let filesViewModel = makeViewModel(screenMode: .files)
static let emptyMediaViewModel = makeViewModel(timelineKind: .detached, screenMode: .media) static let emptyMediaViewModel = makeViewModel(empty: true, screenMode: .media)
static let emptyFilesViewModel = makeViewModel(timelineKind: .detached, screenMode: .files) static let emptyFilesViewModel = makeViewModel(empty: true, screenMode: .files)
static var previews: some View { static var previews: some View {
NavigationStack { NavigationStack {
@@ -250,18 +250,22 @@ struct MediaEventsTimelineScreen_Previews: PreviewProvider, TestablePreview {
.previewDisplayName("Empty Files") .previewDisplayName("Empty Files")
} }
private static func makeViewModel(timelineKind: TimelineKind = .media(.mediaFilesScreen), private static func makeViewModel(empty: Bool = false,
screenMode: MediaEventsTimelineScreenMode) -> MediaEventsTimelineScreenViewModel { screenMode: MediaEventsTimelineScreenMode) -> MediaEventsTimelineScreenViewModel {
MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: makeTimelineViewModel(timelineKind: timelineKind), MediaEventsTimelineScreenViewModel(mediaTimelineViewModel: makeTimelineViewModel(empty: empty),
filesTimelineViewModel: makeTimelineViewModel(timelineKind: timelineKind), filesTimelineViewModel: makeTimelineViewModel(empty: empty),
initialViewState: .init(bindings: .init(screenMode: screenMode)),
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
initialViewState: .init(hasReachedTimelineStart: true,
bindings: .init(screenMode: screenMode)),
userIndicatorController: UserIndicatorControllerMock()) userIndicatorController: UserIndicatorControllerMock())
} }
private static func makeTimelineViewModel(timelineKind: TimelineKind) -> TimelineViewModel { private static func makeTimelineViewModel(empty: Bool) -> TimelineViewModel {
let timelineController = MockRoomTimelineController(timelineKind: timelineKind) let timelineController = if empty {
MockRoomTimelineController.emptyMediaGallery
} else {
MockRoomTimelineController.mediaGallery
}
return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
timelineController: timelineController, timelineController: timelineController,
mediaProvider: MediaProviderMock(configuration: .init()), mediaProvider: MediaProviderMock(configuration: .init()),
@@ -37,8 +37,9 @@ class SecurityAndPrivacyScreenViewModel: SecurityAndPrivacyScreenViewModelType,
state.bindings.alertInfo = .init(id: .enableEncryption, state.bindings.alertInfo = .init(id: .enableEncryption,
title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertTitle, title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertTitle,
message: L10n.screenSecurityAndPrivacyEnableEncryptionAlertDescription, message: L10n.screenSecurityAndPrivacyEnableEncryptionAlertDescription,
primaryButton: .init(title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertConfirmButtonTitle, primaryButton: .init(title: L10n.screenSecurityAndPrivacyEnableEncryptionAlertConfirmButtonTitle) { [weak self] in
action: { [weak self] in self?.state.bindings.desiredSettings.isEncryptionEnabled = true }), self?.state.bindings.desiredSettings.isEncryptionEnabled = true
},
secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil)) secondaryButton: .init(title: L10n.actionCancel, role: .cancel, action: nil))
} else { } else {
state.bindings.desiredSettings.isEncryptionEnabled = false state.bindings.desiredSettings.isEncryptionEnabled = false
@@ -36,7 +36,7 @@ struct MediaFileRoomTimelineContent: View {
let additionalWhitespaces: Int let additionalWhitespaces: Int
var isAudioFile = false var isAudioFile = false
var onMediaTap: (() -> Void)? = nil var onMediaTap: (() -> Void)?
private var icon: KeyPath<CompoundIcons, Image> { private var icon: KeyPath<CompoundIcons, Image> {
isAudioFile ? \.audio : \.attachment isAudioFile ? \.audio : \.attachment
@@ -34,18 +34,21 @@ class MockRoomTimelineController: RoomTimelineControllerProtocol {
private var client: UITestsSignalling.Client? private var client: UITestsSignalling.Client?
init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false) { static var mediaGallery: MockRoomTimelineController {
MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen), timelineItems: (0..<5).reduce([]) { partialResult, _ in
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
})
}
static var emptyMediaGallery: MockRoomTimelineController {
let mock = MockRoomTimelineController(timelineKind: .media(.mediaFilesScreen))
mock.paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached)
return mock
}
init(timelineKind: TimelineKind = .live, listenForSignals: Bool = false, timelineItems: [RoomTimelineItemProtocol] = RoomTimelineItemFixtures.default) {
self.timelineKind = timelineKind self.timelineKind = timelineKind
self.timelineItems = timelineItems
switch timelineKind {
case .media:
paginationState = PaginationState(backward: .timelineEndReached, forward: .timelineEndReached)
timelineItems = (0..<5).reduce([]) { partialResult, _ in
partialResult + [RoomTimelineItemFixtures.separator] + RoomTimelineItemFixtures.mediaChunk
}
default:
paginationState = PaginationState(backward: .idle, forward: .timelineEndReached)
}
callbacks.send(.paginationState(paginationState)) callbacks.send(.paginationState(paginationState))
callbacks.send(.isLive(true)) callbacks.send(.isLive(true))