diff --git a/ComputerSolitaire.xcodeproj/project.pbxproj b/ComputerSolitaire.xcodeproj/project.pbxproj index e25fdbf..5163198 100644 --- a/ComputerSolitaire.xcodeproj/project.pbxproj +++ b/ComputerSolitaire.xcodeproj/project.pbxproj @@ -58,6 +58,11 @@ path = ComputerSolitaireUITests; sourceTree = ""; }; + 4B75C2002F1A233600761A12 /* Shared */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Shared; + sourceTree = ""; + }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ @@ -89,6 +94,7 @@ isa = PBXGroup; children = ( 4B75C1D32F1A233400761A12 /* ComputerSolitaire */, + 4B75C2002F1A233600761A12 /* Shared */, 4B75C1E52F1A233500761A12 /* ComputerSolitaireTests */, 4B75C1F22F1A233600761A12 /* ComputerSolitaireUITests */, 4B75C1D22F1A233400761A12 /* Products */, @@ -122,6 +128,7 @@ ); fileSystemSynchronizedGroups = ( 4B75C1D32F1A233400761A12 /* ComputerSolitaire */, + 4B75C2002F1A233600761A12 /* Shared */, ); name = ComputerSolitaire; packageProductDependencies = ( @@ -168,6 +175,7 @@ ); fileSystemSynchronizedGroups = ( 4B75C1F22F1A233600761A12 /* ComputerSolitaireUITests */, + 4B75C2002F1A233600761A12 /* Shared */, ); name = ComputerSolitaireUITests; packageProductDependencies = ( diff --git a/ComputerSolitaire/Fixtures/ScreenshotFixtures.swift b/ComputerSolitaire/Fixtures/ScreenshotFixtures.swift index ec73bb8..1fde9f4 100644 --- a/ComputerSolitaire/Fixtures/ScreenshotFixtures.swift +++ b/ComputerSolitaire/Fixtures/ScreenshotFixtures.swift @@ -1,16 +1,5 @@ import Foundation -/// A staged mid-game board for App Store screenshots. -struct ScreenshotFixture: Identifiable, Hashable { - /// Bundle resource name of the `SavedGamePayload` JSON, and the screenshot - /// file name the capture UI test emits. - let name: String - /// Human-readable description of the board. - let title: String - - var id: String { name } -} - /// Staged boards for App Store screenshots. /// /// Launching with `-screenshotFixture ` restores the named board instead @@ -28,18 +17,7 @@ enum ScreenshotFixtures { /// Boards shipped in the app bundle; validated by `ScreenshotFixtureTests`. /// One entry per App Store screenshot, in store order. - static let bundled: [ScreenshotFixture] = [ - ScreenshotFixture(name: "klondike-draw3", title: "Klondike – Draw 3"), - ScreenshotFixture(name: "freecell", title: "FreeCell – fresh deal"), - ScreenshotFixture(name: "yukon", title: "Yukon – fresh deal"), - ScreenshotFixture(name: "spider", title: "Spider – 2 suits"), - ScreenshotFixture(name: "pyramid", title: "Pyramid – fresh deal"), - ScreenshotFixture(name: "tripeaks", title: "TriPeaks – fresh deal"), - ScreenshotFixture(name: "golf", title: "Golf – fresh deal"), - ScreenshotFixture(name: "fortythieves", title: "Forty Thieves – fresh deal"), - ScreenshotFixture(name: "scorpion", title: "Scorpion – fresh deal"), - ScreenshotFixture(name: "canfield", title: "Canfield – fresh deal") - ] + static let bundled = ScreenshotFixtureCatalog.bundled static func payloadFromLaunchArguments() -> SavedGamePayload? { guard let name = value(after: launchArgument) else { return nil } diff --git a/ComputerSolitaireUITests/ScreenshotCaptureUITests.swift b/ComputerSolitaireUITests/ScreenshotCaptureUITests.swift index 819182f..8278d2d 100644 --- a/ComputerSolitaireUITests/ScreenshotCaptureUITests.swift +++ b/ComputerSolitaireUITests/ScreenshotCaptureUITests.swift @@ -13,15 +13,9 @@ import AppKit /// the capture; the macOS leg (which snapshot doesn't support) runs this same /// test via xcodebuild and collects the attachment instead. final class ScreenshotCaptureUITests: XCTestCase { - /// Kept in sync with `ScreenshotFixtures.bundled` by hand: UI tests run in - /// a separate process and cannot import the app module. One board per App - /// Store screenshot, in store order. - private static let boards = [ - "klondike-draw3", - "freecell", - "yukon", - "spider" - ] + /// One board per App Store screenshot, in store order. The catalog source + /// is compiled into both targets because UI tests cannot import the app. + private static let boards = ScreenshotFixtureCatalog.bundled.map(\.name) /// Appearance for every screenshot, pinned via UserDefaults launch /// arguments so simulator state can't change the look between runs. diff --git a/README.md b/README.md index ff34abf..d75f2f6 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,11 @@ Computer Solitaire is a fully native Solitaire app for iOS, iPadOS, and macOS. ## Features - Fully native apps for iOS, iPadOS, and macOS -- Multiple game variants: **Klondike** (both 1-card and 3-card draw), **Spider** (1, 2, or 4 suits), **FreeCell**, **Pyramid**, **TriPeaks**, **Golf**, **Yukon**, **Scorpion**, **Forty Thieves**, and **Canfield** +- 10 game variants: **Klondike** (both 1-card and 3-card draw), **Spider** (1, 2, or 4 suits), **FreeCell**, **Pyramid**, **TriPeaks**, **Golf**, **Yukon**, **Scorpion**, **Forty Thieves**, and **Canfield** +- Solver-computed hints +- Game statistics for every variant - Automatic game persistence and resume -- Customizable table appearance +- Customizable cards and table appearance - Other things you enjoy ## Game Variants diff --git a/Shared/ScreenshotFixtureCatalog.swift b/Shared/ScreenshotFixtureCatalog.swift new file mode 100644 index 0000000..77d30e5 --- /dev/null +++ b/Shared/ScreenshotFixtureCatalog.swift @@ -0,0 +1,25 @@ +/// A staged board included in the App Store screenshot set. +struct ScreenshotFixture: Identifiable, Hashable { + /// Bundle resource name and emitted screenshot file name. + let name: String + /// Human-readable description of the staged board. + let title: String + + var id: String { name } +} + +/// The single ordered manifest shared by the app and screenshot UI tests. +enum ScreenshotFixtureCatalog { + static let bundled: [ScreenshotFixture] = [ + ScreenshotFixture(name: "klondike-draw3", title: "Klondike – Draw 3"), + ScreenshotFixture(name: "freecell", title: "FreeCell"), + ScreenshotFixture(name: "yukon", title: "Yukon"), + ScreenshotFixture(name: "spider", title: "Spider – 2 suits"), + ScreenshotFixture(name: "pyramid", title: "Pyramid"), + ScreenshotFixture(name: "tripeaks", title: "TriPeaks"), + ScreenshotFixture(name: "golf", title: "Golf"), + ScreenshotFixture(name: "fortythieves", title: "Forty Thieves"), + ScreenshotFixture(name: "scorpion", title: "Scorpion"), + ScreenshotFixture(name: "canfield", title: "Canfield") + ] +} diff --git a/docs/screenshots/screen-grab-ios.png b/docs/screenshots/screen-grab-ios.png index fd5c392..3f8419e 100644 Binary files a/docs/screenshots/screen-grab-ios.png and b/docs/screenshots/screen-grab-ios.png differ diff --git a/docs/screenshots/screen-grab-macos.png b/docs/screenshots/screen-grab-macos.png index 0377563..92d2041 100644 Binary files a/docs/screenshots/screen-grab-macos.png and b/docs/screenshots/screen-grab-macos.png differ