Skip to content

v0.3.0 — PhotoPicker SwiftUI wrapper

Choose a tag to compare

@SteliyanH SteliyanH released this 30 Apr 08:56
· 19 commits to main since this release

The PhotosUI bridge. Cross-platform SwiftUI wrapper around `PHPickerViewController` that returns directly into kadr clip types — bypasses the manual `PHAsset` round-trip for the common "user picks N items, build a video" flow.

What's new

import SwiftUI
import Kadr
import KadrPhotos

struct ContentView: View {
    @State private var picked: [PhotoPickerResult] = []
    @State private var showPicker = false
    @State private var clips: [any Clip] = []

    var body: some View {
        Button(\"Pick from Photos\") { showPicker = true }
            .sheet(isPresented: \$showPicker) {
                PhotoPicker(
                    selection: \$picked,
                    configuration: .init(selectionLimit: 5, filter: .any)
                )
            }
            .task(id: picked.map(\\.assetIdentifier)) {
                clips = (try? await PhotosClipResolver.clips(from: picked)) ?? []
            }
    }
}
  • `PhotoPicker(selection:configuration:)` — UIKit on iOS / visionOS, AppKit on macOS via `UIViewControllerRepresentable` / `NSViewControllerRepresentable`.
  • `PhotoPickerResult` — `Sendable` + `Equatable` + `Identifiable`. Wraps `assetIdentifier`; `@MainActor resolveAsset()` returns the `PHAsset`.
  • `PhotoPicker.Configuration` — selectionLimit, filter, preferredAssetRepresentationMode. Sensible defaults.
  • `PhotoPicker.Filter` — `.images` / `.videos` / `.livePhotos` / `.any`.
  • `PhotoPicker.AssetRepresentationMode` — `.automatic` / `.current` / `.compatible`.
  • `PhotosClipResolver.clip(from:)` + `clips(from:)` — convenience that dispatches on `PHAsset.mediaType` and returns `any Clip`. `CMTime` and `TimeInterval` overloads.

Compatibility

  • Requires kadr ≥ 0.9.2 (unchanged).
  • iOS 16+ / macOS 13+ / visionOS 1+. tvOS still excluded.
  • Pure additive — every v0.2 call site compiles unchanged.
  • The picker doesn't require library authorization to display — but `resolveAsset()` and `clip(from:)` do (same v0.1 contract).

Tests

Suite: 21 → 36 (+15).

What's next

  • v0.4.0 — PHAsset metadata exposure (creation date / location / EXIF) + direct asset → `ImageOverlay` / `StickerOverlay` helpers

Full notes in CHANGELOG.md.