diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json b/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json index 3f00db4..64dc11e 100644 --- a/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,51 +1,61 @@ { "images" : [ { + "filename" : "icon_16x16.png", "idiom" : "mac", "scale" : "1x", "size" : "16x16" }, { + "filename" : "icon_16x16@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "16x16" }, { + "filename" : "icon_32x32.png", "idiom" : "mac", "scale" : "1x", "size" : "32x32" }, { + "filename" : "icon_32x32@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "32x32" }, { + "filename" : "icon_128x128.png", "idiom" : "mac", "scale" : "1x", "size" : "128x128" }, { + "filename" : "icon_128x128@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "128x128" }, { + "filename" : "icon_256x256.png", "idiom" : "mac", "scale" : "1x", "size" : "256x256" }, { + "filename" : "icon_256x256@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "256x256" }, { + "filename" : "icon_512x512.png", "idiom" : "mac", "scale" : "1x", "size" : "512x512" }, { + "filename" : "icon_512x512@2x.png", "idiom" : "mac", "scale" : "2x", "size" : "512x512" diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png new file mode 100644 index 0000000..84a366e Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png new file mode 100644 index 0000000..0693bd9 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png new file mode 100644 index 0000000..e684ea4 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png new file mode 100644 index 0000000..a778fe1 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png new file mode 100644 index 0000000..0693bd9 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png new file mode 100644 index 0000000..ea56053 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png new file mode 100644 index 0000000..a778fe1 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png new file mode 100644 index 0000000..dd06966 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png new file mode 100644 index 0000000..ea56053 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512.png differ diff --git a/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png b/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png new file mode 100644 index 0000000..28e8f13 Binary files /dev/null and b/Resources/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png differ diff --git a/Resources/dmg-background.png b/Resources/dmg-background.png new file mode 100644 index 0000000..f930d40 Binary files /dev/null and b/Resources/dmg-background.png differ diff --git a/Resources/dmg-background@2x.png b/Resources/dmg-background@2x.png new file mode 100644 index 0000000..732ce99 Binary files /dev/null and b/Resources/dmg-background@2x.png differ diff --git a/Sources/ICCery/AboutView.swift b/Sources/ICCery/AboutView.swift index 2960f8b..a24a8e5 100644 --- a/Sources/ICCery/AboutView.swift +++ b/Sources/ICCery/AboutView.swift @@ -1,3 +1,4 @@ +import AppKit import SwiftUI import ICCeryCore @@ -9,10 +10,12 @@ struct AboutView: View { var body: some View { VStack(spacing: 20) { - Image("ICCery-logo") - .resizable() - .scaledToFit() - .frame(height: 64) + if let icon = NSImage(named: NSImage.applicationIconName) { + Image(nsImage: icon) + .resizable() + .scaledToFit() + .frame(height: 64) + } Text("ICCery") .font(.title) diff --git a/Sources/ICCery/CalibrationViewModel.swift b/Sources/ICCery/CalibrationViewModel.swift index f07b7db..8ed2f17 100644 --- a/Sources/ICCery/CalibrationViewModel.swift +++ b/Sources/ICCery/CalibrationViewModel.swift @@ -91,8 +91,7 @@ final class CalibrationViewModel { workingDirectory: cwd ) - Task { @MainActor [weak self] in - guard let self else { return } + Task { @MainActor in defer { self.isGenerating = false } do { @@ -160,8 +159,7 @@ final class CalibrationViewModel { channelLimits: [] ) - Task { @MainActor [weak self] in - guard let self else { return } + Task { @MainActor in defer { self.isComputing = false } do { diff --git a/Sources/ICCery/RootView.swift b/Sources/ICCery/RootView.swift index 002a729..b38345e 100644 --- a/Sources/ICCery/RootView.swift +++ b/Sources/ICCery/RootView.swift @@ -29,7 +29,7 @@ struct RootView: View { if let notice = model.notice { NoticeBanner(notice: notice, onClose: model.dismissNotice) } - stageContent + WizardStageContent(model: model, workflow: workflow) } } .frame(minWidth: 1100, minHeight: 700) @@ -61,8 +61,16 @@ struct RootView: View { } } - @ViewBuilder - private var stageContent: some View { +} + +/// Content for the active wizard stage. Isolated into its own view so that +/// `WizardViewModel` is tracked via `@Bindable` instead of the parent's +/// `TargetWorkflowViewModel`, which does not observe nested `wizard` mutations. +private struct WizardStageContent: View { + @Bindable var model: WizardViewModel + var workflow: TargetWorkflowViewModel + + var body: some View { switch model.stage { case .generate: Stage1View(workflow: workflow) diff --git a/brand/dmg-background.svg b/brand/dmg-background.svg new file mode 100644 index 0000000..ba4887f --- /dev/null +++ b/brand/dmg-background.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ICCery + + + + + + + diff --git a/scripts/dmgbuild-settings.py b/scripts/dmgbuild-settings.py index 94f1081..be4e87c 100755 --- a/scripts/dmgbuild-settings.py +++ b/scripts/dmgbuild-settings.py @@ -32,7 +32,7 @@ if background and not os.path.exists(background): icon = None # Window size is enough for the app icon and the Applications alias. -window_rect = ((100, 100), (640, 480)) +window_rect = ((100, 100), (660, 400)) # Use icon view without extra chrome. default_view = 'icon-view' @@ -45,8 +45,8 @@ sidebar_width = 180 # Position the .app on the left and the Applications alias on the right. icon_locations = { - 'ICCery.app': (140, 240), - 'Applications': (500, 240), + 'ICCery.app': (180, 220), + 'Applications': (480, 220), } # Symlink to /Applications for drag-and-drop install.