diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ef008bb..7504637 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,16 +43,16 @@ jobs: run: | set -euo pipefail swift package --allow-writing-to-directory ./public generate-documentation \ - --target ImageForgeKit \ + --target ImagePlaygroundBridge \ --disable-indexing \ --output-path ./public \ --transform-for-static-hosting \ - --hosting-base-path imageforgekit + --hosting-base-path image-playground-bridge cat > ./public/index.html <<'INDEX' - - ImageForgeKit Documentation + + ImagePlaygroundBridge Documentation INDEX - name: Upload Pages Artifact diff --git a/AGENTS.md b/AGENTS.md index e20d0ea..35fc3af 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,8 +1,8 @@ -# ImageForgeKit +# ImagePlaygroundBridge ## Context -ImageForgeKit integrates Apple's system-managed Image Playground experience. Read [README.md](README.md) and the DocC catalog before changing public behavior. +ImagePlaygroundBridge integrates Apple's system-managed Image Playground experience. Read [README.md](README.md) and the DocC catalog before changing public behavior. Keep application persistence, host media storage, and product-specific UI outside the package. Limit main-actor isolation to framework presentation boundaries and keep portable values `Sendable`. @@ -96,9 +96,9 @@ Replace these examples with exact repository paths: | Role | Physical folder | |---|---| -| Package sources | `Sources/ImageForgeKit/` | -| DocC catalog | `Sources/ImageForgeKit/ImageForgeKit.docc/` | -| Unit tests | `Tests/ImageForgeKitTests/` | +| Package sources | `Sources/ImagePlaygroundBridge/` | +| DocC catalog | `Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.docc/` | +| Unit tests | `Tests/ImagePlaygroundBridgeTests/` | ## Stack diff --git a/CHANGELOG.md b/CHANGELOG.md index e4f0019..445690d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,13 @@ # Changelog -All notable changes to ImageForgeKit are documented here. +All notable changes to ImagePlaygroundBridge are documented here. ## Unreleased +### Changed + +- Rename the package, product, module, public API, documentation, and repository-facing links to ImagePlaygroundBridge. + ### Added - Bootstrapped the Swift package, DocC catalog, CI/CD workflows, shared AgentGuidelines integration, and repository policy. diff --git a/Package.swift b/Package.swift index 603e445..6130bda 100644 --- a/Package.swift +++ b/Package.swift @@ -3,7 +3,7 @@ import PackageDescription let package = Package( - name: "ImageForgeKit", + name: "ImagePlaygroundBridge", platforms: [ .iOS(.v26), .macOS(.v26), @@ -12,8 +12,8 @@ let package = Package( ], products: [ .library( - name: "ImageForgeKit", - targets: ["ImageForgeKit"] + name: "ImagePlaygroundBridge", + targets: ["ImagePlaygroundBridge"] ) ], dependencies: [ @@ -22,14 +22,14 @@ let package = Package( ], targets: [ .target( - name: "ImageForgeKit", + name: "ImagePlaygroundBridge", dependencies: [ .product(name: "AppLogger", package: "applogger") ] ), .testTarget( - name: "ImageForgeKitTests", - dependencies: ["ImageForgeKit"] + name: "ImagePlaygroundBridgeTests", + dependencies: ["ImagePlaygroundBridge"] ), ] ) diff --git a/README.md b/README.md index 046cd37..b8058f5 100644 --- a/README.md +++ b/README.md @@ -3,21 +3,21 @@ Xcode Version Platforms SPM - DocC + DocC License - CI - Release + CI + Release

-# ImageForgeKit +# ImagePlaygroundBridge -ImageForgeKit is a reusable Apple-platform integration layer for the system-managed Image Playground experience. It centralizes availability checks, concept setup, SwiftUI presentation wiring, cancellation, and temporary result handling while leaving persistence to the host application. +ImagePlaygroundBridge is a reusable Apple-platform integration layer for the system-managed Image Playground experience. It centralizes availability checks, concept setup, SwiftUI presentation wiring, cancellation, and temporary result handling while leaving persistence to the host application. ```swift -let request = ImageForgeRequest(concepts: [.text("a small red house")]) +let request = ImagePlaygroundBridgeRequest(concepts: [.text("a small red house")]) content - .imageForgeSheet( + .imagePlaygroundBridgeSheet( isPresented: $isPresented, request: request, onCompletion: { result in @@ -26,11 +26,11 @@ content ) ``` -The presentation API is available on Apple platforms that support Image Playground. The package also compiles on tvOS so shared multiplatform application targets can resolve it, while ``ImageForgeAvailability/current`` reports unavailable there. +The presentation API is available on Apple platforms that support Image Playground. The package also compiles on tvOS so shared multiplatform application targets can resolve it, while ``ImagePlaygroundBridgeAvailability/current`` reports unavailable there. ## Documentation -API documentation is published with DocC after a GitHub release. See the [ImageForgeKit documentation](https://thatfactory.github.io/imageforgekit/documentation/imageforgekit/). +API documentation is published with DocC after a GitHub release. See the [ImagePlaygroundBridge documentation](https://thatfactory.github.io/image-playground-bridge/documentation/imageplaygroundbridge/). ## Requirements diff --git a/Sources/ImageForgeKit/ImageForgeKit.docc/ImageForgeKit.md b/Sources/ImageForgeKit/ImageForgeKit.docc/ImageForgeKit.md deleted file mode 100644 index 0071c3e..0000000 --- a/Sources/ImageForgeKit/ImageForgeKit.docc/ImageForgeKit.md +++ /dev/null @@ -1,21 +0,0 @@ -# ``ImageForgeKit`` - -Integrate Apple's system-managed Image Playground experience while keeping generated-image persistence in the host application. - -## Overview - -Use ``ImageForgeAvailability/current`` to decide whether to offer generation, build an ``ImageForgeRequest`` from portable ``ImageForgeConcept`` values, and apply `SwiftUI/View/imageForgeSheet(isPresented:request:onCompletion:onCancellation:)` to a host view. - -Image Playground supplies ``ImageForgeResult/temporaryURL`` only as temporary output. The completion callback is the host application's ownership boundary: copy the file into durable, application-owned storage before returning. ImageForgeKit never persists images, reads a photo library, or synchronizes media. - -## Topics - -### Availability and requests - -- ``ImageForgeAvailability`` -- ``ImageForgeConcept`` -- ``ImageForgeRequest`` - -### Presentation results - -- ``ImageForgeResult`` diff --git a/Sources/ImageForgeKit/ImageForgeKit.swift b/Sources/ImageForgeKit/ImageForgeKit.swift deleted file mode 100644 index 6b131bb..0000000 --- a/Sources/ImageForgeKit/ImageForgeKit.swift +++ /dev/null @@ -1,2 +0,0 @@ -/// A namespace for ImageForgeKit capabilities and package identity. -public enum ImageForgeKit {} diff --git a/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.docc/ImagePlaygroundBridge.md b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.docc/ImagePlaygroundBridge.md new file mode 100644 index 0000000..3418178 --- /dev/null +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.docc/ImagePlaygroundBridge.md @@ -0,0 +1,21 @@ +# ``ImagePlaygroundBridge`` + +Integrate Apple's system-managed Image Playground experience while keeping generated-image persistence in the host application. + +## Overview + +Use ``ImagePlaygroundBridgeAvailability/current`` to decide whether to offer generation, build an ``ImagePlaygroundBridgeRequest`` from portable ``ImagePlaygroundBridgeConcept`` values, and apply `SwiftUI/View/imagePlaygroundBridgeSheet(isPresented:request:onCompletion:onCancellation:)` to a host view. + +Image Playground supplies ``ImagePlaygroundBridgeResult/temporaryURL`` only as temporary output. The completion callback is the host application's ownership boundary: copy the file into durable, application-owned storage before returning. ImagePlaygroundBridge never persists images, reads a photo library, or synchronizes media. + +## Topics + +### Availability and requests + +- ``ImagePlaygroundBridgeAvailability`` +- ``ImagePlaygroundBridgeConcept`` +- ``ImagePlaygroundBridgeRequest`` + +### Presentation results + +- ``ImagePlaygroundBridgeResult`` diff --git a/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.swift new file mode 100644 index 0000000..fc0e0ae --- /dev/null +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridge.swift @@ -0,0 +1,2 @@ +/// A namespace for ImagePlaygroundBridge capabilities and package identity. +public enum ImagePlaygroundBridge {} diff --git a/Sources/ImageForgeKit/ImageForgeAvailability.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeAvailability.swift similarity index 89% rename from Sources/ImageForgeKit/ImageForgeAvailability.swift rename to Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeAvailability.swift index 4d3532e..636f551 100644 --- a/Sources/ImageForgeKit/ImageForgeAvailability.swift +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeAvailability.swift @@ -5,7 +5,7 @@ import Foundation #endif /// Describes whether the current device can present Image Playground. -public enum ImageForgeAvailability: Equatable, Sendable { +public enum ImagePlaygroundBridgeAvailability: Equatable, Sendable { /// Image Playground can be presented. case available diff --git a/Sources/ImageForgeKit/ImageForgeConcept.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeConcept.swift similarity index 81% rename from Sources/ImageForgeKit/ImageForgeConcept.swift rename to Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeConcept.swift index bf8b537..3799bcd 100644 --- a/Sources/ImageForgeKit/ImageForgeConcept.swift +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeConcept.swift @@ -1,7 +1,7 @@ import Foundation /// A portable concept used to seed the system Image Playground experience. -public enum ImageForgeConcept: Equatable, Sendable { +public enum ImagePlaygroundBridgeConcept: Equatable, Sendable { /// Lets Image Playground extract useful concepts from prose. case extracted(text: String, title: String? = nil) diff --git a/Sources/ImageForgeKit/ImageForgeLogging.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeLogging.swift similarity index 84% rename from Sources/ImageForgeKit/ImageForgeLogging.swift rename to Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeLogging.swift index 8320d31..d1a78b2 100644 --- a/Sources/ImageForgeKit/ImageForgeLogging.swift +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeLogging.swift @@ -1,8 +1,8 @@ import AppLogger -enum ImageForgeLogging { +enum ImagePlaygroundBridgeLogging { static let emoji = "🎨" - static let subsystem = "com.thatfactory.imageforgekit" + static let subsystem = "com.thatfactory.imageplaygroundbridge" enum Event: Equatable { case cancelled diff --git a/Sources/ImageForgeKit/ImageForgeRequest.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeRequest.swift similarity index 56% rename from Sources/ImageForgeKit/ImageForgeRequest.swift rename to Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeRequest.swift index 2a4ecb1..3986055 100644 --- a/Sources/ImageForgeKit/ImageForgeRequest.swift +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeRequest.swift @@ -1,12 +1,12 @@ import Foundation /// Input for an interactive Image Playground presentation. -public struct ImageForgeRequest: Equatable, Sendable { +public struct ImagePlaygroundBridgeRequest: Equatable, Sendable { /// Concepts that seed the system-managed experience. - public var concepts: [ImageForgeConcept] + public var concepts: [ImagePlaygroundBridgeConcept] /// Creates a request from one or more concepts. - public init(concepts: [ImageForgeConcept]) { + public init(concepts: [ImagePlaygroundBridgeConcept]) { self.concepts = concepts } } diff --git a/Sources/ImageForgeKit/ImageForgeResult.swift b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeResult.swift similarity index 83% rename from Sources/ImageForgeKit/ImageForgeResult.swift rename to Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeResult.swift index 146338f..29d6893 100644 --- a/Sources/ImageForgeKit/ImageForgeResult.swift +++ b/Sources/ImagePlaygroundBridge/ImagePlaygroundBridgeResult.swift @@ -1,7 +1,7 @@ import Foundation /// A generated image accepted by the user. -public struct ImageForgeResult: Equatable, Sendable { +public struct ImagePlaygroundBridgeResult: Equatable, Sendable { /// A temporary file URL that the host must copy before returning from its callback. public let temporaryURL: URL diff --git a/Sources/ImageForgeKit/View+ImageForge.swift b/Sources/ImagePlaygroundBridge/View+ImagePlaygroundBridge.swift similarity index 63% rename from Sources/ImageForgeKit/View+ImageForge.swift rename to Sources/ImagePlaygroundBridge/View+ImagePlaygroundBridge.swift index 8fe9203..54c9155 100644 --- a/Sources/ImageForgeKit/View+ImageForge.swift +++ b/Sources/ImagePlaygroundBridge/View+ImagePlaygroundBridge.swift @@ -3,32 +3,32 @@ import SwiftUI extension View { - /// Presents Image Playground and maps its temporary result into ImageForgeKit values. + /// Presents Image Playground and maps its temporary result into ImagePlaygroundBridge values. /// - /// Copy ``ImageForgeResult/temporaryURL`` into host-owned storage synchronously from + /// Copy ``ImagePlaygroundBridgeResult/temporaryURL`` into host-owned storage synchronously from /// `onCompletion`. The system may remove the temporary file after the callback returns. - public func imageForgeSheet( + public func imagePlaygroundBridgeSheet( isPresented: Binding, - request: ImageForgeRequest, - onCompletion: @escaping (ImageForgeResult) -> Void, + request: ImagePlaygroundBridgeRequest, + onCompletion: @escaping (ImagePlaygroundBridgeResult) -> Void, onCancellation: (() -> Void)? = nil ) -> some View { imagePlaygroundSheet( isPresented: isPresented, concepts: request.concepts.map(\.imagePlaygroundConcept), onCompletion: { temporaryURL in - ImageForgeLogging.emit(.completed) - onCompletion(ImageForgeResult(temporaryURL: temporaryURL)) + ImagePlaygroundBridgeLogging.emit(.completed) + onCompletion(ImagePlaygroundBridgeResult(temporaryURL: temporaryURL)) }, onCancellation: { - ImageForgeLogging.emit(.cancelled) + ImagePlaygroundBridgeLogging.emit(.cancelled) onCancellation?() } ) } } - extension ImageForgeConcept { + extension ImagePlaygroundBridgeConcept { fileprivate var imagePlaygroundConcept: ImagePlaygroundConcept { switch self { case .extracted(let text, let title): diff --git a/Tests/ImageForgeKitTests/ImageForgeKitTests.swift b/Tests/ImagePlaygroundBridgeTests/ImagePlaygroundBridgeTests.swift similarity index 64% rename from Tests/ImageForgeKitTests/ImageForgeKitTests.swift rename to Tests/ImagePlaygroundBridgeTests/ImagePlaygroundBridgeTests.swift index 192c5d3..6a18a00 100644 --- a/Tests/ImageForgeKitTests/ImageForgeKitTests.swift +++ b/Tests/ImagePlaygroundBridgeTests/ImagePlaygroundBridgeTests.swift @@ -1,16 +1,16 @@ import Foundation import Testing -@testable import ImageForgeKit +@testable import ImagePlaygroundBridge @Test("The package namespace is available") func packageNamespaceIsAvailable() { - _ = ImageForgeKit.self + _ = ImagePlaygroundBridge.self } @Test("Requests preserve portable concepts") func requestsPreservePortableConcepts() { - let request = ImageForgeRequest( + let request = ImagePlaygroundBridgeRequest( concepts: [ .text("a small red house"), .extracted(text: "A welcoming home", title: "House"), @@ -29,11 +29,11 @@ func requestsPreservePortableConcepts() { func resultsPreserveTemporaryURL() { let url = URL(filePath: "/tmp/generated-image") - #expect(ImageForgeResult(temporaryURL: url).temporaryURL == url) + #expect(ImagePlaygroundBridgeResult(temporaryURL: url).temporaryURL == url) } @Test("Logging messages do not contain generated content") func loggingMessagesArePrivacySafe() { - #expect(ImageForgeLogging.Event.cancelled.message == "🎨 playground | result=cancelled") - #expect(ImageForgeLogging.Event.completed.message == "🎨 playground | result=completed") + #expect(ImagePlaygroundBridgeLogging.Event.cancelled.message == "🎨 playground | result=cancelled") + #expect(ImagePlaygroundBridgeLogging.Event.completed.message == "🎨 playground | result=completed") }