From 7b1554af4b597a08f944a4a5bc4581ee84c0d4ef Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Tue, 4 Aug 2026 21:34:18 +0200 Subject: [PATCH] fix(apple/shots): fill the grid, open Settings on Display, note the iPad orientation limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Six mock hosts rather than three. An iPad-13 portrait grid is three columns wide and 2752 px tall; three cards left ~60% of the capture as black. - Settings opens on Display, not General. Resolution, frame rate, bitrate, HDR and codec are what someone reads a streaming app's settings shot for. - The wake scene is the modal-over-grid variant. The gamepad-UI one is a full-screen takeover over a bare gradient — correct, but four lines of text on an empty aurora; the modal shows the same overlay over the host grid. - `requestGeometryUpdate` now reports a refusal instead of failing silently. It does not help on the simulator (an app's stdout doesn't reach the driver through `simctl launch`) but it will on macOS and on a device. - Documented that `.landscape` does not rotate on iPad: a multitasking-capable iPad app is resizable, so iPadOS ignores the request and simctl cannot rotate a simulated device. The iPad set is portrait throughout. --- .../Screenshots/ScreenshotHost.swift | 7 ++++++- .../Screenshots/ScreenshotScenes.swift | 16 +++++++++++++--- clients/apple/tools/screenshots.sh | 8 +++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotHost.swift b/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotHost.swift index 2e40c40e..94798950 100644 --- a/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotHost.swift +++ b/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotHost.swift @@ -190,7 +190,12 @@ final class ShotOrientationController: UIViewController { let scene = view.window?.windowScene ?? UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first guard let scene else { return } - scene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) + // Report a refusal instead of silently shipping the wrong orientation — that is exactly + // how every landscape scene went out as a portrait PNG for as long as it did. + scene.requestGeometryUpdate(.iOS(interfaceOrientations: mask)) { error in + print("PF_SHOT_ORIENTATION_REFUSED \(error.localizedDescription)") + fflush(stdout) + } setNeedsUpdateOfSupportedInterfaceOrientations() } } diff --git a/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotScenes.swift b/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotScenes.swift index e68ddf08..7c4a4bba 100644 --- a/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotScenes.swift +++ b/clients/apple/Sources/PunktfunkClient/Screenshots/ScreenshotScenes.swift @@ -87,6 +87,8 @@ enum ShotMock { static let livingRoomID = UUID(uuidString: "5B0D1E00-0000-4000-8000-000000000002")! static let workshopID = UUID(uuidString: "5B0D1E00-0000-4000-8000-000000000003")! static let officeID = UUID(uuidString: "5B0D1E00-0000-4000-8000-000000000004")! + static let editingID = UUID(uuidString: "5B0D1E00-0000-4000-8000-000000000005")! + static let bedroomID = UUID(uuidString: "5B0D1E00-0000-4000-8000-000000000006")! static let hdrProfileID = "a71c4e0d9f22" static let couchProfileID = "3e88b107c4da" @@ -133,6 +135,14 @@ enum ShotMock { id: workshopID, name: "Workshop", address: "10.0.0.7", port: 9777, pinnedSHA256: hostFingerprint(2), macAddresses: ["de:ad:be:ef:00:07"], osChain: "linux/arch"), + StoredHost( + id: editingID, name: "Editing Rig", address: "192.168.1.62", port: 9777, + pinnedSHA256: hostFingerprint(5), lastConnected: Date().addingTimeInterval(-604_800), + osChain: "linux/nobara"), + StoredHost( + id: bedroomID, name: "Bedroom Mini", address: "192.168.1.77", port: 9777, + pinnedSHA256: hostFingerprint(6), macAddresses: ["00:1a:2b:3c:4d:5e"], + osChain: "windows/11"), ] return store } @@ -335,9 +345,9 @@ private struct ShotSettings: View { #elseif os(iOS) // SettingsView owns its NavigationSplitView (sidebar + detail) and Done button, so it is // rendered directly — a wrapping NavigationStack would nest a split view in a stack. Open - // on General so the shot lands on real controls (iPad: sidebar + General detail; iPhone: - // the General page) instead of the bare category list. - SettingsView(initialCategory: .general) + // on Display rather than the bare category list: resolution, frame rate, bitrate, HDR and + // codec are what someone reads a streaming app's settings shot to find out. + SettingsView(initialCategory: .display) #else NavigationStack { SettingsView() } #endif diff --git a/clients/apple/tools/screenshots.sh b/clients/apple/tools/screenshots.sh index 694de44d..3eb88a9c 100755 --- a/clients/apple/tools/screenshots.sh +++ b/clients/apple/tools/screenshots.sh @@ -11,9 +11,15 @@ # The captured pixels are exactly App Store Connect's required sizes: # mac 2880×1800 (a 1× display yields 1440×900 — also accepted) # iphone-6.9 1320×2868 (portrait) / 2868×1320 (the landscape hero) -# ipad-13 2064×2752 (portrait) / 2752×2064 (the landscape hero) +# ipad-13 2064×2752 (portrait) # appletv 1920×1080 # +# A `.landscape` scene rotates on iPhone but NOT on iPad: an iPad app that supports multitasking +# is resizable, and iPadOS ignores `requestGeometryUpdate` orientation requests for it — the app +# follows the device, and simctl cannot rotate a simulated device. The iPad set is therefore +# portrait throughout (a valid App Store size, and uniform, which the gallery prefers). To get a +# landscape iPad hero, rotate the Simulator by hand (⌘←) and re-run just that scene. +# # Requirements: # • macOS target: just the Swift toolchain (`swift build`) + a one-time Screen Recording grant # for your terminal (System Settings → Privacy & Security → Screen Recording).