11import Foundation
2- import Combine
2+ import Observation
33import enum Yosemite. POSItem
44import protocol Yosemite. PointOfSaleItemServiceProtocol
55import struct Yosemite. POSVariableParentProduct
66import class Yosemite. Store
77
8+ @available ( iOS 17 . 0 , * )
89protocol PointOfSaleItemsControllerProtocol {
9- var itemsViewStatePublisher : any Publisher < ItemsViewState , Never > { get }
10+ var itemsViewState : ItemsViewState { get }
1011 /// Loads the first page of items for a given base item.
1112 func loadItems( base: ItemListBaseItem ) async
1213 /// Loads the next page of items for a given base item.
1314 func loadNextItems( base: ItemListBaseItem ) async
1415}
1516
16- class PointOfSaleItemsController : PointOfSaleItemsControllerProtocol {
17- var itemsViewStatePublisher : any Publisher < ItemsViewState , Never > {
18- $itemsViewState. eraseToAnyPublisher ( )
19- }
20- @Published private var itemsViewState : ItemsViewState =
21- ItemsViewState ( containerState: . loading,
22- itemsStack: ItemsStackState ( root: . loading( [ ] ) ,
23- itemStates: [ : ] ) )
17+ @available ( iOS 17 . 0 , * )
18+ @Observable final class PointOfSaleItemsController : PointOfSaleItemsControllerProtocol {
19+ var itemsViewState : ItemsViewState = ItemsViewState ( containerState: . loading,
20+ itemsStack: ItemsStackState ( root: . loading( [ ] ) ,
21+ itemStates: [ : ] ) )
2422 private let paginationTracker : AsyncPaginationTracker
2523 private var childPaginationTrackers : [ POSItem : AsyncPaginationTracker ] = [ : ]
2624 private let itemProvider : PointOfSaleItemServiceProtocol
@@ -42,22 +40,22 @@ class PointOfSaleItemsController: PointOfSaleItemsControllerProtocol {
4240
4341 @MainActor
4442 private func loadRootItems( ) async {
45- let currentItems = itemsViewState. itemsStack. root. items
46- let currentItemStates = itemsViewState . itemsStack . itemStates
47- let containerState : ItemsContainerState = currentItems . isEmpty ? . loading : . content
48- itemsViewState = . init ( containerState : containerState ,
49- itemsStack: ItemsStackState ( root: . loading( currentItems ) ,
50- itemStates : currentItemStates ) )
43+ let items = itemsViewState. itemsStack. root. items
44+ if items . isEmpty {
45+ itemsViewState . containerState = . loading
46+ } else {
47+ itemsViewState . itemsStack. root = . loading( items )
48+ }
5149
5250 do {
5351 try await paginationTracker. resync { [ weak self] pageNumber in
5452 guard let self else { return true }
5553 return try await fetchItems ( pageNumber: pageNumber, appendToExistingItems: false )
5654 }
5755 } catch {
58- itemsViewState = . init ( containerState : . error( PointOfSaleErrorState . errorOnLoadingProducts ( ) ) ,
59- itemsStack: ItemsStackState ( root: . loaded( [ ] , hasMoreItems: false ) ,
60- itemStates: [ : ] ) )
56+ itemsViewState. containerState = . error( PointOfSaleErrorState . errorOnLoadingProducts ( ) )
57+ itemsViewState . itemsStack = ItemsStackState ( root: . loaded( [ ] , hasMoreItems: false ) ,
58+ itemStates: [ : ] )
6159 }
6260 }
6361
@@ -78,18 +76,19 @@ class PointOfSaleItemsController: PointOfSaleItemsControllerProtocol {
7876 }
7977 let currentItems = itemsViewState. itemsStack. root. items
8078 let currentItemStates = itemsViewState. itemsStack. itemStates
81- itemsViewState = . init( containerState: . content, itemsStack: ItemsStackState ( root: . loading( currentItems) ,
82- itemStates: currentItemStates) )
79+ itemsViewState. containerState = . content
80+ itemsViewState. itemsStack = ItemsStackState ( root: . loading( currentItems) ,
81+ itemStates: currentItemStates)
8382 do {
8483 _ = try await paginationTracker. ensureNextPageIsSynced { [ weak self] pageNumber in
8584 guard let self else { return true }
8685 return try await fetchItems ( pageNumber: pageNumber)
8786 }
8887 } catch {
89- itemsViewState = . init ( containerState : . content,
90- itemsStack: ItemsStackState ( root: . inlineError( currentItems,
91- error: . errorOnLoadingProductsNextPage( ) ) ,
92- itemStates: currentItemStates) )
88+ itemsViewState. containerState = . content
89+ itemsViewState . itemsStack = ItemsStackState ( root: . inlineError( currentItems,
90+ error: . errorOnLoadingProductsNextPage( ) ) ,
91+ itemStates: currentItemStates)
9392 }
9493 }
9594
@@ -155,6 +154,7 @@ class PointOfSaleItemsController: PointOfSaleItemsControllerProtocol {
155154 }
156155}
157156
157+ @available ( iOS 17 . 0 , * )
158158private extension PointOfSaleItemsController {
159159 /// Fetches items given a page number and appends new unique items to the `allItems` array.
160160 /// - Parameter pageNumber: Page number to fetch items from.
@@ -171,15 +171,15 @@ private extension PointOfSaleItemsController {
171171 }
172172 allItems. append ( contentsOf: uniqueNewItems)
173173 if allItems. isEmpty {
174- itemsViewState = . init ( containerState : . empty,
175- itemsStack: ItemsStackState ( root: . loaded( [ ] , hasMoreItems: false ) ,
176- itemStates: [ : ] ) )
174+ itemsViewState. containerState = . empty
175+ itemsViewState . itemsStack = ItemsStackState ( root: . loaded( [ ] , hasMoreItems: false ) ,
176+ itemStates: [ : ] )
177177 } else {
178178 let itemStates = itemsViewState. itemsStack. itemStates
179179 . filter { allItems. contains ( $0. key) }
180- itemsViewState = . init ( containerState : . content,
181- itemsStack: ItemsStackState ( root: . loaded( allItems, hasMoreItems: pagedItems. hasMorePages) ,
182- itemStates: itemStates) )
180+ itemsViewState. containerState = . content
181+ itemsViewState . itemsStack = ItemsStackState ( root: . loaded( allItems, hasMoreItems: pagedItems. hasMorePages) ,
182+ itemStates: itemStates)
183183 }
184184 return pagedItems. hasMorePages
185185 }
@@ -210,7 +210,7 @@ private extension PointOfSaleItemsController {
210210}
211211
212212// MARK: - ItemsViewState Updates
213-
213+ @ available ( iOS 17 . 0 , * )
214214private extension PointOfSaleItemsController {
215215 func updateState( for parent: POSItem , to state: ItemListState ) {
216216 let viewState = itemsViewState
@@ -219,6 +219,6 @@ private extension PointOfSaleItemsController {
219219 states [ parent] = state
220220 return states
221221 } ( )
222- itemsViewState = viewState . copy ( itemsStack: viewState . itemsStack . copy ( itemStates: itemStates) )
222+ itemsViewState. itemsStack. itemStates = itemStates
223223 }
224224}
0 commit comments