mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Address PR comments
This commit is contained in:
@@ -177,9 +177,6 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
|
|
||||||
updateRooms()
|
updateRooms()
|
||||||
|
|
||||||
// The subscription above only delivers the current state through an async main queue
|
|
||||||
// hop, which can end up queued behind the first render and leave the skeletons up on a
|
|
||||||
// warm launch, where the provider has already published the cached rooms.
|
|
||||||
if let roomSummaryProvider {
|
if let roomSummaryProvider {
|
||||||
updateRoomListMode(with: roomSummaryProvider.statePublisher.value,
|
updateRoomListMode(with: roomSummaryProvider.statePublisher.value,
|
||||||
hasRooms: !roomSummaryProvider.roomListPublisher.value.isEmpty)
|
hasRooms: !roomSummaryProvider.roomListPublisher.value.isEmpty)
|
||||||
@@ -337,19 +334,16 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func updateRoomListMode(with roomSummaryProviderState: RoomSummaryProviderState, hasRooms: Bool) {
|
private func updateRoomListMode(with roomSummaryProviderState: RoomSummaryProviderState, hasRooms: Bool) {
|
||||||
let isLoadingData = !roomSummaryProviderState.isLoaded
|
let roomListMode: HomeScreenRoomListMode = if !roomSummaryProviderState.isLoaded {
|
||||||
let hasNoRooms = roomSummaryProviderState.isLoaded && roomSummaryProviderState.totalNumberOfRooms == 0
|
.skeletons // Still loading.
|
||||||
// Only the initial transition needs holding back until the rooms have published, an
|
} else if roomSummaryProviderState.totalNumberOfRooms == 0 {
|
||||||
// empty list later on is a filter or a search result.
|
.empty // Loaded, there are no rooms at all.
|
||||||
let isInitialLoad = state.roomListMode == .skeletons
|
} else if hasRooms {
|
||||||
|
.rooms // Loaded and the summaries have published.
|
||||||
var roomListMode = state.roomListMode
|
} else if state.roomListMode == .skeletons {
|
||||||
if isLoadingData {
|
.skeletons // Loaded but nothing published yet, flipping to .rooms would flash an empty list.
|
||||||
roomListMode = .skeletons
|
} else {
|
||||||
} else if hasNoRooms {
|
.rooms
|
||||||
roomListMode = .empty
|
|
||||||
} else if hasRooms || !isInitialLoad {
|
|
||||||
roomListMode = .rooms
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guard roomListMode != state.roomListMode else {
|
guard roomListMode != state.roomListMode else {
|
||||||
|
|||||||
@@ -68,9 +68,6 @@ struct HomeScreenContent: View {
|
|||||||
scrollViewAdapter.scrollView = scrollView
|
scrollViewAdapter.scrollView = scrollView
|
||||||
}
|
}
|
||||||
.onReceive(scrollViewAdapter.didScroll) { _ in
|
.onReceive(scrollViewAdapter.didScroll) { _ in
|
||||||
// Live, undelayed updates while scrolling: pagination needs to see the
|
|
||||||
// range early enough to grow the list before the user reaches the bottom,
|
|
||||||
// and the scroll geometry is valid mid-scroll.
|
|
||||||
sendVisibleRange()
|
sendVisibleRange()
|
||||||
}
|
}
|
||||||
.onReceive(scrollViewAdapter.isScrolling) { _ in
|
.onReceive(scrollViewAdapter.isScrolling) { _ in
|
||||||
|
|||||||
@@ -151,8 +151,7 @@ struct RunTests: AsyncParsableCommand {
|
|||||||
// -test-iterations is the total number of attempts (initial + retries)
|
// -test-iterations is the total number of attempts (initial + retries)
|
||||||
command += " -retry-tests-on-failure"
|
command += " -retry-tests-on-failure"
|
||||||
command += " -test-iterations \(retries + 1)"
|
command += " -test-iterations \(retries + 1)"
|
||||||
// Repetitions happen in the same process by default, so a runner that exits (e.g. code 75
|
// Ensure retries still happen when a runner exits early.
|
||||||
// after a failed app launch) takes its own retries down with it and the test gets skipped.
|
|
||||||
command += " -test-repetition-relaunch-enabled YES"
|
command += " -test-repetition-relaunch-enabled YES"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -399,9 +399,9 @@ final class HomeScreenViewModelTests {
|
|||||||
#expect(context.viewState.roomListMode == .skeletons)
|
#expect(context.viewState.roomListMode == .skeletons)
|
||||||
|
|
||||||
// The provider reports loaded before the first summaries have been published.
|
// The provider reports loaded before the first summaries have been published.
|
||||||
|
let failure = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.roomListMode != .skeletons }
|
||||||
stateSubject.send(.loaded(totalNumberOfRooms: 8))
|
stateSubject.send(.loaded(totalNumberOfRooms: 8))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await failure.fulfill()
|
||||||
#expect(context.viewState.roomListMode == .skeletons)
|
|
||||||
|
|
||||||
let deferred = deferFulfillment(context.$viewState) { $0.roomListMode == .rooms }
|
let deferred = deferFulfillment(context.$viewState) { $0.roomListMode == .rooms }
|
||||||
roomListSubject.send(.mockRooms)
|
roomListSubject.send(.mockRooms)
|
||||||
@@ -418,10 +418,10 @@ final class HomeScreenViewModelTests {
|
|||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
|
|
||||||
// A filter or a search without matches empties the list, the mode must not regress.
|
// A filter or a search without matches empties the list, the mode must not regress.
|
||||||
|
let failure = deferFailure(context.$viewState, timeout: .seconds(1)) { $0.roomListMode != .rooms }
|
||||||
roomListSubject.send([])
|
roomListSubject.send([])
|
||||||
stateSubject.send(.loaded(totalNumberOfRooms: 9))
|
stateSubject.send(.loaded(totalNumberOfRooms: 9))
|
||||||
try await Task.sleep(for: .milliseconds(100))
|
try await failure.fulfill()
|
||||||
#expect(context.viewState.roomListMode == .rooms)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupViewModelWithManualProvider() -> (CurrentValueSubject<[RoomSummary], Never>, CurrentValueSubject<RoomSummaryProviderState, Never>) {
|
private func setupViewModelWithManualProvider() -> (CurrentValueSubject<[RoomSummary], Never>, CurrentValueSubject<RoomSummaryProviderState, Never>) {
|
||||||
|
|||||||
@@ -271,8 +271,6 @@ struct RoomDetailsScreenViewModelTests {
|
|||||||
#expect(context.viewState.dmRecipientInfo?.member == RoomMemberDetails(withProxy: recipient))
|
#expect(context.viewState.dmRecipientInfo?.member == RoomMemberDetails(withProxy: recipient))
|
||||||
|
|
||||||
#expect(!context.viewState.isProcessingIgnoreRequest)
|
#expect(!context.viewState.isProcessingIgnoreRequest)
|
||||||
// Waiting on the transient isProcessingIgnoreRequest transition races the view model's task,
|
|
||||||
// which can complete before the observation starts. Wait on the alert instead.
|
|
||||||
let deferredAlert = deferFulfillment(context.observe(\.alertInfo)) { $0 != nil }
|
let deferredAlert = deferFulfillment(context.observe(\.alertInfo)) { $0 != nil }
|
||||||
|
|
||||||
context.send(viewAction: .unignoreConfirmed)
|
context.send(viewAction: .unignoreConfirmed)
|
||||||
|
|||||||
Reference in New Issue
Block a user