Clean up data flow so that the list view doesn't refresh on every store change.

This commit is contained in:
CypherPoet 2020-01-31 07:29:00 -06:00
parent 7f293d8efa
commit 1fc29fc8a1
8 changed files with 86 additions and 61 deletions

View File

@ -7,7 +7,6 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
F32ED61823DF69E6006A5195 /* PadsListContainerView+WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61723DF69E6006A5195 /* PadsListContainerView+WelcomeView.swift */; };
F32ED61A23DF91C1006A5195 /* Pad+PadType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61923DF91C1006A5195 /* Pad+PadType.swift */; }; F32ED61A23DF91C1006A5195 /* Pad+PadType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61923DF91C1006A5195 /* Pad+PadType.swift */; };
F32ED61D23DF9B46006A5195 /* PadDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61C23DF9B46006A5195 /* PadDetailsView.swift */; }; F32ED61D23DF9B46006A5195 /* PadDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61C23DF9B46006A5195 /* PadDetailsView.swift */; };
F32ED61F23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61E23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift */; }; F32ED61F23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32ED61E23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift */; };
@ -40,10 +39,11 @@
F3596BC423E3EE6800FA2C66 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC323E3EE6800FA2C66 /* Cache.swift */; }; F3596BC423E3EE6800FA2C66 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC323E3EE6800FA2C66 /* Cache.swift */; };
F3596BC723E3F71500FA2C66 /* Cache+WrappedKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC623E3F71500FA2C66 /* Cache+WrappedKey.swift */; }; F3596BC723E3F71500FA2C66 /* Cache+WrappedKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC623E3F71500FA2C66 /* Cache+WrappedKey.swift */; };
F3596BC923E3F72200FA2C66 /* Cache+Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC823E3F72200FA2C66 /* Cache+Entry.swift */; }; F3596BC923E3F72200FA2C66 /* Cache+Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BC823E3F72200FA2C66 /* Cache+Entry.swift */; };
F3596BCB23E4298300FA2C66 /* RootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BCA23E4298300FA2C66 /* RootView.swift */; };
F3596BCD23E42BED00FA2C66 /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3596BCC23E42BEC00FA2C66 /* WelcomeView.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
F32ED61723DF69E6006A5195 /* PadsListContainerView+WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PadsListContainerView+WelcomeView.swift"; sourceTree = "<group>"; };
F32ED61923DF91C1006A5195 /* Pad+PadType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Pad+PadType.swift"; sourceTree = "<group>"; }; F32ED61923DF91C1006A5195 /* Pad+PadType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Pad+PadType.swift"; sourceTree = "<group>"; };
F32ED61C23DF9B46006A5195 /* PadDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadDetailsView.swift; sourceTree = "<group>"; }; F32ED61C23DF9B46006A5195 /* PadDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PadDetailsView.swift; sourceTree = "<group>"; };
F32ED61E23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PadDetailsView+ViewModel.swift"; sourceTree = "<group>"; }; F32ED61E23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PadDetailsView+ViewModel.swift"; sourceTree = "<group>"; };
@ -75,6 +75,8 @@
F3596BC323E3EE6800FA2C66 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; }; F3596BC323E3EE6800FA2C66 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; };
F3596BC623E3F71500FA2C66 /* Cache+WrappedKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cache+WrappedKey.swift"; sourceTree = "<group>"; }; F3596BC623E3F71500FA2C66 /* Cache+WrappedKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cache+WrappedKey.swift"; sourceTree = "<group>"; };
F3596BC823E3F72200FA2C66 /* Cache+Entry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cache+Entry.swift"; sourceTree = "<group>"; }; F3596BC823E3F72200FA2C66 /* Cache+Entry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Cache+Entry.swift"; sourceTree = "<group>"; };
F3596BCA23E4298300FA2C66 /* RootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootView.swift; sourceTree = "<group>"; };
F3596BCC23E42BEC00FA2C66 /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -162,6 +164,8 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F331C47823DDB1430061925E /* Pads */, F331C47823DDB1430061925E /* Pads */,
F3596BCA23E4298300FA2C66 /* RootView.swift */,
F3596BCC23E42BEC00FA2C66 /* WelcomeView.swift */,
); );
path = Scenes; path = Scenes;
sourceTree = "<group>"; sourceTree = "<group>";
@ -219,7 +223,6 @@
children = ( children = (
F331C47B23DDB1710061925E /* PadsListContainerView.swift */, F331C47B23DDB1710061925E /* PadsListContainerView.swift */,
F32ED61B23DF9B36006A5195 /* Pad Details */, F32ED61B23DF9B36006A5195 /* Pad Details */,
F32ED61723DF69E6006A5195 /* PadsListContainerView+WelcomeView.swift */,
F331C49B23DE18650061925E /* PadsListView.swift */, F331C49B23DE18650061925E /* PadsListView.swift */,
F331C49D23DE187A0061925E /* PadsListView+ViewModel.swift */, F331C49D23DE187A0061925E /* PadsListView+ViewModel.swift */,
); );
@ -358,15 +361,16 @@
F356E61E23E25E7A008553B0 /* PadDetailsContainerView.swift in Sources */, F356E61E23E25E7A008553B0 /* PadDetailsContainerView.swift in Sources */,
F331C48523DDDE710061925E /* AppState.swift in Sources */, F331C48523DDDE710061925E /* AppState.swift in Sources */,
F32ED62923E0F0C6006A5195 /* MapSnapshottingService.swift in Sources */, F32ED62923E0F0C6006A5195 /* MapSnapshottingService.swift in Sources */,
F3596BCB23E4298300FA2C66 /* RootView.swift in Sources */,
F32ED61F23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift in Sources */, F32ED61F23DF9B7C006A5195 /* PadDetailsView+ViewModel.swift in Sources */,
F331C49C23DE18650061925E /* PadsListView.swift in Sources */, F331C49C23DE18650061925E /* PadsListView.swift in Sources */,
F3596BC723E3F71500FA2C66 /* Cache+WrappedKey.swift in Sources */, F3596BC723E3F71500FA2C66 /* Cache+WrappedKey.swift in Sources */,
F32ED61823DF69E6006A5195 /* PadsListContainerView+WelcomeView.swift in Sources */,
F331C48923DDDF0E0061925E /* Pad.swift in Sources */, F331C48923DDDF0E0061925E /* Pad.swift in Sources */,
F331C49623DE0FED0061925E /* PreviewData.swift in Sources */, F331C49623DE0FED0061925E /* PreviewData.swift in Sources */,
F32ED62423DFC7D5006A5195 /* Pad+SnapshotUtils.swift in Sources */, F32ED62423DFC7D5006A5195 /* Pad+SnapshotUtils.swift in Sources */,
F331C48C23DDE6A90061925E /* LaunchLibraryAPIService.swift in Sources */, F331C48C23DDE6A90061925E /* LaunchLibraryAPIService.swift in Sources */,
F32ED62B23E0F0F1006A5195 /* MapSnapshotServicing.swift in Sources */, F32ED62B23E0F0F1006A5195 /* MapSnapshotServicing.swift in Sources */,
F3596BCD23E42BED00FA2C66 /* WelcomeView.swift in Sources */,
F32ED62623E0D525006A5195 /* Pad+Computeds.swift in Sources */, F32ED62623E0D525006A5195 /* Pad+Computeds.swift in Sources */,
F32ED62223DFB836006A5195 /* NumberFormatters.swift in Sources */, F32ED62223DFB836006A5195 /* NumberFormatters.swift in Sources */,
F331C49E23DE187A0061925E /* PadsListView+ViewModel.swift in Sources */, F331C49E23DE187A0061925E /* PadsListView+ViewModel.swift in Sources */,

View File

@ -25,7 +25,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
let store = AppStore(initialState: .init(), appReducer: appReducer) let store = AppStore(initialState: .init(), appReducer: appReducer)
// Create the SwiftUI view that provides the window contents. // Create the SwiftUI view that provides the window contents.
let entryView = PadsListContainerView() let entryView = RootView()
.environmentObject(store) .environmentObject(store)
.accentColor(.pink) .accentColor(.pink)

View File

@ -109,7 +109,7 @@ extension PadDetailsView.ViewModel {
snapshotService snapshotService
.takeSnapshot(cacheKey: cacheKey, size: size, coordinate: pad.coordinate) .takeSnapshot(cacheKey: cacheKey, size: size, coordinate: pad.coordinate)
.assertNoFailure() .assertNoFailure()
.print("takeMapSnapshot") // .print("takeMapSnapshot")
.map(\.image) .map(\.image)
.receive(on: DispatchQueue.main) .receive(on: DispatchQueue.main)
.sink( .sink(

View File

@ -19,16 +19,12 @@ struct PadsListContainerView {
extension PadsListContainerView: View { extension PadsListContainerView: View {
var body: some View { var body: some View {
NavigationView {
PadsListView( PadsListView(
viewModel: .init(padsState: padsState), viewModel: .init(padsState: padsState),
buildDestination: buildDestination(forPad:) buildDestination: buildDestination(forPad:)
) )
.navigationBarTitle("Launch Pads") .navigationBarTitle("Launch Pads")
.environmentObject(store) .environmentObject(store)
WelcomeView()
}
.onAppear(perform: fetchPads) .onAppear(perform: fetchPads)
} }
} }

View File

@ -17,9 +17,7 @@ extension PadsListView {
private let padsState: PadsState private let padsState: PadsState
// MARK: - Published Outputs // MARK: - Published Outputs
@Published var pads: [Pad] = []
// MARK: - Init // MARK: - Init
@ -36,26 +34,19 @@ extension PadsListView {
// MARK: - Publishers // MARK: - Publishers
extension PadsListView.ViewModel { extension PadsListView.ViewModel {
private var padsStatePublisher: Publishers.Share<AnyPublisher<PadsState, Never>> {
CurrentValueSubject(padsState)
// .print("padsStatePublisher")
.eraseToAnyPublisher()
.share()
}
private var padsFetchingStatePublisher: Publishers.Share<AnyPublisher<PadsState.DataFetchingState, Never>> {
padsStatePublisher
.map(\.dataFetchingState)
.eraseToAnyPublisher()
.share()
}
} }
// MARK: - Computeds // MARK: - Computeds
extension PadsListView.ViewModel { extension PadsListView.ViewModel {
var pads: [Pad] {
if case let .fetched(pads) = padsState.dataFetchingState {
return pads
} else {
return []
}
}
} }
@ -69,20 +60,5 @@ extension PadsListView.ViewModel {
private extension PadsListView.ViewModel { private extension PadsListView.ViewModel {
func setupSubscribers() { func setupSubscribers() {
padsFetchingStatePublisher
.receive(on: DispatchQueue.main)
.sink(receiveValue: { (fetchingState: PadsState.DataFetchingState) in
switch fetchingState {
case .inactive:
self.pads = []
case .fetching:
self.pads = []
case .fetched(let pads):
self.pads = pads
case .errored(_):
fatalError()
}
})
.store(in: &subscriptions)
} }
} }

View File

@ -10,8 +10,6 @@ import SwiftUI
struct PadsListView<Destination: View> { struct PadsListView<Destination: View> {
@EnvironmentObject private var store: AppStore
@ObservedObject var viewModel: ViewModel @ObservedObject var viewModel: ViewModel
let buildDestination: ((Pad) -> Destination) let buildDestination: ((Pad) -> Destination)
} }

View File

@ -0,0 +1,53 @@
//
// RootView.swift
// PadFinder
//
// Created by CypherPoet on 1/31/20.
//
//
import SwiftUI
struct RootView {
@EnvironmentObject private var store: AppStore
}
// MARK: - View
extension RootView: View {
var body: some View {
NavigationView {
PadsListContainerView()
WelcomeView()
}
}
}
// MARK: - Computeds
extension RootView {
}
// MARK: - View Variables
extension RootView {
}
// MARK: - Private Helpers
private extension RootView {
}
// MARK: - Preview
struct RootView_Previews: PreviewProvider {
static var previews: some View {
RootView()
}
}

View File

@ -2,22 +2,20 @@
// WelcomeView.swift // WelcomeView.swift
// PadFinder // PadFinder
// //
// Created by CypherPoet on 1/27/20. // Created by CypherPoet on 1/31/20.
// //
// //
import SwiftUI import SwiftUI
extension PadsListContainerView {
struct WelcomeView { struct WelcomeView {
} }
}
// MARK: - View // MARK: - View
extension PadsListContainerView.WelcomeView: View { extension WelcomeView: View {
var body: some View { var body: some View {
@ -36,25 +34,25 @@ extension PadsListContainerView.WelcomeView: View {
// MARK: - Computeds // MARK: - Computeds
extension PadsListContainerView.WelcomeView { extension WelcomeView {
} }
// MARK: - View Variables // MARK: - View Variables
extension PadsListContainerView.WelcomeView { extension WelcomeView {
} }
// MARK: - Private Helpers // MARK: - Private Helpers
private extension PadsListContainerView.WelcomeView { private extension WelcomeView {
} }
// MARK: - Preview // MARK: - Preview
struct PadsListContainerView_WelcomeView_Previews: PreviewProvider { struct WelcomeView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
PadsListContainerView.WelcomeView() WelcomeView()
} }
} }