Slice 4 (Phases 3 & 4) of the M9 macOS 12 retarget.
State management (Observation → Combine)
All 8 view models (TargetWorkflow, ProfileWorkflow, Calibration, MeasurementWorkflow, PrintSession, Wizard, Gamut, Settings) migrated from @Observable/import Observation to ObservableObject + import Combine.
Every observed mutable property is now @Published (incl. @Published private(set)); @MainActor isolation and didSet observers retained.
Views: @State on view models → @StateObject (ICCeryApp, SettingsView, GamutView); all @Bindable occurrences → @ObservedObject; plain ViewModel parameters converted to @ObservedObject (RootView.WizardStageContent, Stage2View.GalleryPageView, SidebarView).
Child-VM observation: SwiftUI does not propagate nested ObservableObject changes through a parent, so views reading workflow.wizard.*, workflow.print.*, or workflow.profile.* now hold the child as an explicit @ObservedObject (SidebarView observes wizard+profile; Stage2View/GalleryPageView observe print+wizard; Stage3/4/5 observe wizard; RootView observes wizard).
Window lifecycle (macOS 12)
Window scene → WindowGroup; secondary-window creation suppressed via CommandGroup(replacing: .newItem) {}.
AppDelegate sets initial content size 1280×800, contentMinSize 1100×700, and centres the window; applicationShouldHandleReopen(_:hasVisibleWindows:) returns true so the Dock icon re-shows/recreates the window.
Stage2View: .task(id:) → .onAppear + .onChange(of:) with an explicit @State private var printGenerationTask cancelled before each relaunch; two-parameter .onChange → single-parameter macOS 12 form.
GamutView: .onKeyPress/focusEffectDisabled removed; R-key camera reset now handled by an NSEvent.addLocalMonitorForEvents(.keyDown) in GamutSceneView.Coordinator, removed in dismantleNSView.
SettingsView: .formStyle(.grouped) removed.
Test alignment
CupsOptionsFilterTests: the @convention(c) mode-resolver closure now spells ColorSyncSuppressorTests. instead of Self. — dynamic-Self capture is illegal in a C function pointer. Previously unreachable: the file only parses/typechecks now that the app target compiles.
Verification
git grep for @Observable, import Observation, @Bindable, formStyle, focusEffectDisabled, onKeyPress over Sources/ → zero occurrences.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Slice 4 (Phases 3 & 4) of the M9 macOS 12 retarget.
State management (Observation → Combine)
TargetWorkflow,ProfileWorkflow,Calibration,MeasurementWorkflow,PrintSession,Wizard,Gamut,Settings) migrated from@Observable/import ObservationtoObservableObject+import Combine.@Published(incl.@Published private(set));@MainActorisolation anddidSetobservers retained.@Stateon view models →@StateObject(ICCeryApp, SettingsView, GamutView); all@Bindableoccurrences →@ObservedObject; plain ViewModel parameters converted to@ObservedObject(RootView.WizardStageContent, Stage2View.GalleryPageView, SidebarView).ObservableObjectchanges through a parent, so views readingworkflow.wizard.*,workflow.print.*, orworkflow.profile.*now hold the child as an explicit@ObservedObject(SidebarView observes wizard+profile; Stage2View/GalleryPageView observe print+wizard; Stage3/4/5 observe wizard; RootView observes wizard).Window lifecycle (macOS 12)
Windowscene →WindowGroup; secondary-window creation suppressed viaCommandGroup(replacing: .newItem) {}.AppDelegatesets initial content size 1280×800,contentMinSize1100×700, and centres the window;applicationShouldHandleReopen(_:hasVisibleWindows:)returnstrueso the Dock icon re-shows/recreates the window.#147/#149termination/killAllbehaviour unchanged.View demotions
.task(id:)→.onAppear+.onChange(of:)with an explicit@State private var printGenerationTaskcancelled before each relaunch; two-parameter.onChange→ single-parameter macOS 12 form..onChange→ single-parameter form;.formStyle(.grouped)removed..onKeyPress/focusEffectDisabledremoved; R-key camera reset now handled by anNSEvent.addLocalMonitorForEvents(.keyDown)inGamutSceneView.Coordinator, removed indismantleNSView..formStyle(.grouped)removed.Test alignment
CupsOptionsFilterTests: the@convention(c)mode-resolver closure now spellsColorSyncSuppressorTests.instead ofSelf.— dynamic-Self capture is illegal in a C function pointer. Previously unreachable: the file only parses/typechecks now that the app target compiles.Verification
git grepfor@Observable,import Observation,@Bindable,formStyle,focusEffectDisabled,onKeyPressoverSources/→ zero occurrences.xcodegen generate --spec project.ymlregenerated cleanly.xcodebuild build-for-testing -scheme ICCery -destination 'platform=macOS' ARCHS='arm64 x86_64' ONLY_ACTIVE_ARCH=NO→ TEST BUILD SUCCEEDED (universal build).git status --porcelainclean;docs/megaplans/untouched.Assignee: gronod