ci / bun-nix (pull_request) Successful in 49s
ci / web (pull_request) Successful in 1m3s
ci / docs-site (pull_request) Successful in 1m16s
apple / swift (pull_request) Successful in 1m33s
apple / screenshots (pull_request) Skipped
ci / rust-arm64 (pull_request) Successful in 4m38s
ci / rust (pull_request) Successful in 16m9s
Four reworks from the first palette-era on-glass review, all iOS-facing: - Surfaces carry the palette now, not just the text on them: ConsoleGlass washes every tier (Liquid Glass tint, pre-26 material, tvOS material) with ink.glass — the same colour the desktop console fills its panels with — and the close buttons move to an ink-aware consoleGlassBackground. The pre-26 branch also gains the focus tint it had silently dropped. Stray literals follow: ConnectOverlay text rides ink in the console takeover, card shadows soften on pale fields, the focused keycap reads onAccent. The online pip stays status-green on purpose. - The header breathes: title top padding 4/10 -> 10/18 plus shared header-spacing and title-bottom helpers mapped from the console shell's rhythm, applied to the launcher, settings and add-host alike, with the add-host close X re-anchored to the title row. - Settings, Add Host and the Library present IN PLACE on iOS: one persistent aurora whose calm is chased (the console's bg_mix), screens as transparent layers with the console's 0.26 s ease-out-cubic push/pop, an input drop for the transition, and the controller handed off through isActive — no more opaque bottom-up covers, no backdrop teardown. macOS keeps its sheets, tvOS its focus-engine covers. - The settings select is a real band: choice rows mount GamepadOptionBand, a spring-driven drum (Animatable body, ring-distance wrap, neighbours gated by focus and flight) whose retargeting spring accumulates rapid steps into one continuous spin. Reduce Motion falls back to a plain crossfade; toggles keep the quiet 14 pt slip. Verified: swift build (macOS), swift build --triple arm64-apple-ios17.0, swift test 208 passed / 0 failed. On-glass QA still owed: palette sweep on a pale palette, transition compositing over materials, drum feel on device.
62 lines
2.8 KiB
Swift
62 lines
2.8 KiB
Swift
// The library as one of the gamepad shell's in-place layers (iOS): console chrome — a pinned
|
|
// title and a close ✕ styled like the settings screen's — around the shared LibraryView, whose
|
|
// gamepad branch renders the coverflow. The cover presentation used to get its title and Close
|
|
// from the wrapping NavigationStack's bar; a shell layer has no bar, so this restores both in
|
|
// the console's own grammar. Everything data-shaped (the fetch, the loading/error/empty states,
|
|
// the image session lifecycle) stays LibraryView's.
|
|
|
|
import PunktfunkKit
|
|
import SwiftUI
|
|
#if os(iOS)
|
|
|
|
struct GamepadLibraryScreen: View {
|
|
@Environment(\.gamepadInk) private var ink
|
|
@ObservedObject var store: HostStore
|
|
let host: StoredHost
|
|
let onLaunch: (String) -> Void
|
|
let close: () -> Void
|
|
var controllerActive = true
|
|
|
|
/// `.compact` in a landscape phone window — tighter chrome, like every gamepad screen.
|
|
@Environment(\.verticalSizeClass) private var vSizeClass
|
|
|
|
private var compact: Bool { vSizeClass == .compact }
|
|
|
|
var body: some View {
|
|
LibraryView(
|
|
store: store, host: host, onLaunch: onLaunch,
|
|
onClose: close, controllerActive: controllerActive)
|
|
.safeAreaInset(edge: .top, spacing: 0) {
|
|
Text("\(host.displayName) — Library")
|
|
.font(.geist(gamepadTitleSize(compact: compact), .bold, relativeTo: .title))
|
|
.foregroundStyle(ink.fg)
|
|
.lineLimit(1)
|
|
.minimumScaleFactor(0.75)
|
|
.frame(maxWidth: .infinity)
|
|
.overlay(alignment: .trailing) { closeButton.padding(.trailing, 20) }
|
|
.padding(.top, gamepadTitleTopPadding(compact: compact))
|
|
.padding(.bottom, gamepadTitleBottomPadding(compact: compact))
|
|
.background { GamepadTrayScrim(edge: .top) }
|
|
}
|
|
.gamepadPaletteInk()
|
|
}
|
|
|
|
/// Touch/click fallback for closing — the controller path is B (the coverflow's onDismiss),
|
|
/// and it also covers the loading/error/empty states, which the coverflow (and its B) never
|
|
/// mounts under. A hardware keyboard's Esc rides the cancel action.
|
|
private var closeButton: some View {
|
|
Button { close() } label: {
|
|
Image(systemName: "xmark")
|
|
.font(.system(size: GamepadFormMetrics.closeFont, weight: .semibold))
|
|
.foregroundStyle(ink.fg)
|
|
.frame(width: GamepadFormMetrics.closeSide, height: GamepadFormMetrics.closeSide)
|
|
.consoleGlassBackground(Circle(), interactive: true)
|
|
.contentShape(Circle())
|
|
}
|
|
.buttonStyle(.plain)
|
|
.keyboardShortcut(.cancelAction)
|
|
.accessibilityLabel("Close library")
|
|
}
|
|
}
|
|
#endif
|