mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-09-10 03:41:53 +02:00
WIP
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
// Demo
|
||||
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||
|
||||
import Combine
|
||||
import CoreStore
|
||||
import SwiftUI
|
||||
|
||||
@@ -22,19 +21,19 @@ extension Classic.ColorsDemo {
|
||||
}
|
||||
|
||||
// MARK: UIViewControllerRepresentable
|
||||
|
||||
|
||||
typealias UIViewControllerType = Classic.ColorsDemo.DetailViewController
|
||||
|
||||
|
||||
func makeUIViewController(context: Self.Context) -> UIViewControllerType {
|
||||
|
||||
return UIViewControllerType(self.palette)
|
||||
}
|
||||
|
||||
|
||||
func updateUIViewController(_ uiViewController: UIViewControllerType, context: Self.Context) {
|
||||
|
||||
uiViewController.palette = self.palette
|
||||
}
|
||||
|
||||
|
||||
static func dismantleUIViewController(_ uiViewController: UIViewControllerType, coordinator: Void) {}
|
||||
|
||||
func makeCoordinator() -> ObjectMonitor<Classic.ColorsDemo.Palette> {
|
||||
@@ -48,32 +47,3 @@ extension Classic.ColorsDemo {
|
||||
private let palette: ObjectMonitor<Classic.ColorsDemo.Palette>
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct _Demo_Classic_ColorsDemo_DetailView_Preview: PreviewProvider {
|
||||
|
||||
// MARK: PreviewProvider
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
try! Classic.ColorsDemo.dataStack.perform(
|
||||
synchronous: { transaction in
|
||||
|
||||
guard (try transaction.fetchCount(From<Modern.ColorsDemo.Palette>())) <= 0 else {
|
||||
return
|
||||
}
|
||||
let palette = transaction.create(Into<Modern.ColorsDemo.Palette>())
|
||||
palette.setRandomHue()
|
||||
}
|
||||
)
|
||||
|
||||
return Classic.ColorsDemo.DetailView(
|
||||
Classic.ColorsDemo.dataStack.monitorObject(
|
||||
Classic.ColorsDemo.palettesMonitor[0, 0]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,35 +55,29 @@ extension Classic.ColorsDemo {
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct _Demo_Classic_ColorsDemo_ListView_Preview: PreviewProvider {
|
||||
|
||||
// MARK: PreviewProvider
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
let minimumSamples = 10
|
||||
try! Classic.ColorsDemo.dataStack.perform(
|
||||
synchronous: { transaction in
|
||||
// MARK: - Preview
|
||||
|
||||
let missing = minimumSamples
|
||||
- (try transaction.fetchCount(From<Classic.ColorsDemo.Palette>()))
|
||||
guard missing > 0 else {
|
||||
return
|
||||
}
|
||||
for _ in 0..<missing {
|
||||
|
||||
let palette = transaction.create(Into<Classic.ColorsDemo.Palette>())
|
||||
palette.setRandomHue()
|
||||
}
|
||||
#Preview {
|
||||
|
||||
let minimumSamples = 10
|
||||
try! Classic.ColorsDemo.dataStack.perform(
|
||||
synchronous: { transaction in
|
||||
|
||||
let missing = minimumSamples
|
||||
- (try transaction.fetchCount(From<Classic.ColorsDemo.Palette>()))
|
||||
guard missing > 0 else {
|
||||
return
|
||||
}
|
||||
)
|
||||
return Classic.ColorsDemo.ListView(
|
||||
listMonitor: Classic.ColorsDemo.palettesMonitor,
|
||||
onPaletteTapped: { _ in }
|
||||
)
|
||||
}
|
||||
}
|
||||
for _ in 0..<missing {
|
||||
|
||||
#endif
|
||||
let palette = transaction.create(Into<Classic.ColorsDemo.Palette>())
|
||||
palette.setRandomHue()
|
||||
}
|
||||
}
|
||||
)
|
||||
return Classic.ColorsDemo.ListView(
|
||||
listMonitor: Classic.ColorsDemo.palettesMonitor,
|
||||
onPaletteTapped: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// Copyright © 2020 John Rommel Estropia, Inc. All rights reserved.
|
||||
|
||||
import CoreStore
|
||||
import Observation
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Classic.ColorsDemo
|
||||
@@ -12,97 +13,85 @@ extension Classic.ColorsDemo {
|
||||
// MARK: - Classic.ColorsDemo.MainView
|
||||
|
||||
struct MainView: View {
|
||||
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
|
||||
init() {
|
||||
|
||||
|
||||
let listMonitor = Classic.ColorsDemo.palettesMonitor
|
||||
self.listMonitor = listMonitor
|
||||
self.listHelper = .init(listMonitor: listMonitor)
|
||||
self._listHelper = State(initialValue: .init(listMonitor: listMonitor))
|
||||
self._filter = Binding(
|
||||
get: { Classic.ColorsDemo.filter },
|
||||
set: { Classic.ColorsDemo.filter = $0 }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: View
|
||||
|
||||
|
||||
var body: some View {
|
||||
let detailView: AnyView
|
||||
if let selectedObject = self.listHelper.selectedObject() {
|
||||
|
||||
detailView = AnyView(
|
||||
Classic.ColorsDemo.DetailView(selectedObject)
|
||||
VStack(spacing: 0) {
|
||||
Classic.ColorsDemo.ListView(
|
||||
listMonitor: self.listMonitor,
|
||||
onPaletteTapped: {
|
||||
|
||||
self.listHelper.setSelectedPalette($0)
|
||||
}
|
||||
)
|
||||
}
|
||||
else {
|
||||
|
||||
detailView = AnyView(EmptyView())
|
||||
}
|
||||
let listMonitor = self.listMonitor
|
||||
return VStack(spacing: 0) {
|
||||
Classic.ColorsDemo.ListView
|
||||
.init(
|
||||
listMonitor: listMonitor,
|
||||
onPaletteTapped: {
|
||||
|
||||
self.listHelper.setSelectedPalette($0)
|
||||
}
|
||||
)
|
||||
.navigationBarTitle(
|
||||
Text("Colors (\(self.listHelper.count) objects)")
|
||||
)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
.edgesIgnoringSafeArea(.vertical)
|
||||
detailView
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
}
|
||||
.navigationBarItems(
|
||||
leading: HStack {
|
||||
EditButton()
|
||||
Button(
|
||||
action: { self.clearColors() },
|
||||
label: { Text("Clear") }
|
||||
)
|
||||
},
|
||||
trailing: HStack {
|
||||
Button(
|
||||
action: { self.changeFilter() },
|
||||
label: { Text(self.filter.rawValue) }
|
||||
)
|
||||
Button(
|
||||
action: { self.shuffleColors() },
|
||||
label: { Text("Shuffle") }
|
||||
)
|
||||
Button(
|
||||
action: { self.addColor() },
|
||||
label: { Text("Add") }
|
||||
)
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
.ignoresSafeArea(.container, edges: .vertical)
|
||||
|
||||
if let selectedObject = self.listHelper.selectedObject() {
|
||||
Classic.ColorsDemo.DetailView(selectedObject)
|
||||
.ignoresSafeArea()
|
||||
.frame(minHeight: 0, maxHeight: .infinity)
|
||||
}
|
||||
)
|
||||
}
|
||||
.navigationTitle("Colors (\(self.listHelper.count) objects)")
|
||||
.toolbar {
|
||||
ToolbarItemGroup(placement: .topBarLeading) {
|
||||
EditButton()
|
||||
Button("Clear") {
|
||||
|
||||
self.clearColors()
|
||||
}
|
||||
}
|
||||
ToolbarItemGroup(placement: .topBarTrailing) {
|
||||
Button(self.filter.rawValue) {
|
||||
|
||||
self.changeFilter()
|
||||
}
|
||||
Button("Shuffle") {
|
||||
|
||||
self.shuffleColors()
|
||||
}
|
||||
Button("Add") {
|
||||
|
||||
self.addColor()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
|
||||
private let listMonitor: ListMonitor<Classic.ColorsDemo.Palette>
|
||||
|
||||
@ObservedObject
|
||||
|
||||
@State
|
||||
private var listHelper: ListHelper
|
||||
|
||||
|
||||
@Binding
|
||||
private var filter: Classic.ColorsDemo.Filter
|
||||
|
||||
|
||||
private func changeFilter() {
|
||||
|
||||
|
||||
Classic.ColorsDemo.filter = Classic.ColorsDemo.filter.next()
|
||||
}
|
||||
|
||||
|
||||
private func clearColors() {
|
||||
|
||||
|
||||
Classic.ColorsDemo.dataStack.perform(
|
||||
asynchronous: { transaction in
|
||||
|
||||
@@ -111,7 +100,7 @@ extension Classic.ColorsDemo {
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private func addColor() {
|
||||
|
||||
Classic.ColorsDemo.dataStack.perform(
|
||||
@@ -122,7 +111,7 @@ extension Classic.ColorsDemo {
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private func shuffleColors() {
|
||||
|
||||
Classic.ColorsDemo.dataStack.perform(
|
||||
@@ -136,112 +125,93 @@ extension Classic.ColorsDemo {
|
||||
completion: { _ in }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MARK: - Classic.ColorsDemo.MainView.ListHelper
|
||||
|
||||
fileprivate final class ListHelper: ObservableObject, ListObjectObserver {
|
||||
|
||||
|
||||
@MainActor
|
||||
@Observable
|
||||
fileprivate final class ListHelper: ListObjectObserver {
|
||||
|
||||
// MARK: FilePrivate
|
||||
|
||||
|
||||
fileprivate private(set) var count: Int = 0
|
||||
|
||||
|
||||
fileprivate init(listMonitor: ListMonitor<Classic.ColorsDemo.Palette>) {
|
||||
|
||||
|
||||
listMonitor.addObserver(self)
|
||||
self.count = listMonitor.numberOfObjects()
|
||||
}
|
||||
|
||||
|
||||
fileprivate func selectedObject() -> ObjectMonitor<Classic.ColorsDemo.Palette>? {
|
||||
|
||||
return self.selectedPalette.flatMap {
|
||||
|
||||
|
||||
self.selectedPalette.flatMap {
|
||||
guard !$0.isDeleted else {
|
||||
|
||||
|
||||
return nil
|
||||
}
|
||||
return Classic.ColorsDemo.dataStack.monitorObject($0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fileprivate func setSelectedPalette(_ palette: Classic.ColorsDemo.Palette?) {
|
||||
|
||||
|
||||
guard self.selectedPalette != palette else {
|
||||
|
||||
|
||||
return
|
||||
}
|
||||
self.objectWillChange.send()
|
||||
if let palette = palette, !palette.isDeleted {
|
||||
|
||||
if let palette, !palette.isDeleted {
|
||||
|
||||
self.selectedPalette = palette
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
self.selectedPalette = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: ListObserver
|
||||
|
||||
typealias ListEntityType = Classic.ColorsDemo.Palette
|
||||
|
||||
func listMonitorDidChange(_ monitor: ListMonitor<Classic.ColorsDemo.Palette>) {
|
||||
|
||||
self.objectWillChange.send()
|
||||
self.count = monitor.numberOfObjects()
|
||||
}
|
||||
|
||||
func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>) {
|
||||
|
||||
self.objectWillChange.send()
|
||||
self.count = monitor.numberOfObjects()
|
||||
}
|
||||
|
||||
// MARK: ListObjectObserver
|
||||
|
||||
func listMonitor(_ monitor: ListMonitor<Classic.ColorsDemo.Palette>, didDeleteObject object: Classic.ColorsDemo.Palette, fromIndexPath indexPath: IndexPath) {
|
||||
|
||||
if self.selectedPalette == object {
|
||||
|
||||
self.setSelectedPalette(nil)
|
||||
|
||||
// MARK: ListObserver
|
||||
|
||||
typealias ListEntityType = Classic.ColorsDemo.Palette
|
||||
|
||||
nonisolated func listMonitorDidChange(_ monitor: ListMonitor<Classic.ColorsDemo.Palette>) {
|
||||
let count = monitor.numberOfObjects()
|
||||
|
||||
Task { @MainActor in
|
||||
self.count = count
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
nonisolated func listMonitorDidRefetch(_ monitor: ListMonitor<ListEntityType>) {
|
||||
let count = monitor.numberOfObjects()
|
||||
|
||||
Task { @MainActor in
|
||||
self.count = count
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: ListObjectObserver
|
||||
|
||||
nonisolated func listMonitor(
|
||||
_ monitor: ListMonitor<Classic.ColorsDemo.Palette>,
|
||||
didDeleteObject object: Classic.ColorsDemo.Palette,
|
||||
fromIndexPath indexPath: IndexPath
|
||||
) {
|
||||
let deletedObjectURI = object.objectID.uriRepresentation()
|
||||
|
||||
Task { @MainActor in
|
||||
if self.selectedPalette?.objectID.uriRepresentation() == deletedObjectURI {
|
||||
|
||||
self.setSelectedPalette(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: Private
|
||||
|
||||
|
||||
private var selectedPalette: Classic.ColorsDemo.Palette?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
|
||||
struct _Demo_Classic_ColorsDemo_MainView_Preview: PreviewProvider {
|
||||
|
||||
// MARK: PreviewProvider
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
let minimumSamples = 10
|
||||
try! Classic.ColorsDemo.dataStack.perform(
|
||||
synchronous: { transaction in
|
||||
|
||||
let missing = minimumSamples
|
||||
- (try transaction.fetchCount(From<Classic.ColorsDemo.Palette>()))
|
||||
guard missing > 0 else {
|
||||
return
|
||||
}
|
||||
for _ in 0..<missing {
|
||||
|
||||
let palette = transaction.create(Into<Classic.ColorsDemo.Palette>())
|
||||
palette.setRandomHue()
|
||||
}
|
||||
}
|
||||
)
|
||||
return Classic.ColorsDemo.MainView()
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,7 @@ extension Classic {
|
||||
return dataStack
|
||||
}()
|
||||
|
||||
@MainActor
|
||||
static let palettesMonitor: ListMonitor<Classic.ColorsDemo.Palette> = Classic.ColorsDemo.dataStack.monitorSectionedList(
|
||||
From<Classic.ColorsDemo.Palette>()
|
||||
.sectionBy(\.colorGroup)
|
||||
@@ -45,6 +46,7 @@ extension Classic {
|
||||
.orderBy(.ascending(\.hue))
|
||||
)
|
||||
|
||||
@MainActor
|
||||
static var filter: Classic.ColorsDemo.Filter = .all {
|
||||
|
||||
didSet {
|
||||
|
||||
Reference in New Issue
Block a user