diff --git a/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Sections.swift b/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Sections.swift index 96ecda72..ea233e61 100644 --- a/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Sections.swift +++ b/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Sections.swift @@ -223,9 +223,7 @@ extension SettingsView { } header: { Text("Audio") } footer: { - Text("Host audio plays through the speaker; the microphone feeds the " - + "host's virtual mic. System default follows macOS device changes. " - + "Applies from the next session.") + Text(Self.audioFooter) .font(.geist(12, relativeTo: .caption)) .foregroundStyle(.secondary) } @@ -257,17 +255,14 @@ extension SettingsView { /// `+` chain (with a ternary) inside the ViewBuilder — that single expression blew Swift's /// type-checker budget and was what actually broke the iOS archive. private var pointerFooterText: String { - var text = "Trackpad: your finger nudges the host cursor like a laptop touchpad — tap to " - text += "click, two-finger tap for a right click, two-finger drag to scroll, " - text += "tap-then-drag to hold the button, three-finger tap for the stats overlay. " - text += "Direct pointer: the cursor jumps to your finger. Touch passthrough: real " - text += "multi-touch reaches the host, for apps that understand touch. Applies from " - text += "the next touch." + var text = "Trackpad: your finger moves the host cursor like a laptop touchpad — tap " + text += "to click, two-finger tap to right-click, two-finger drag to scroll, " + text += "tap-and-drag to hold, three-finger tap for the stats overlay. Direct pointer: " + text += "the cursor jumps to your finger. Touch passthrough: real multi-touch reaches " + text += "the host. Applies from the next touch." if UIDevice.current.userInterfaceIdiom == .pad { - text += " Pointer capture locks a hardware mouse/trackpad for relative movement " - text += "(mouse-look); off keeps the pointer free and sends absolute positions. " - text += "The lock needs the stream full-screen and frontmost, and falls back " - text += "automatically (Stage Manager, Slide Over)." + text += " Pointer capture locks a hardware mouse for relative mouse-look; off sends " + text += "absolute positions. Needs the stream full-screen and frontmost." } return text } @@ -339,12 +334,10 @@ extension SettingsView { } header: { Text("Video presenter · debug") } footer: { - Text("Stage 2 (default) decodes explicitly and presents through Metal with a display " - + "link — it gives the HUD the end-to-end (capture→on-glass) headline with the " - + "host+network/decode/display stage equation and self-recovers from decode " - + "stalls. Stage 1 feeds compressed video straight to the system display layer; " - + "it freezes on a lost HEVC reference frame, so it's a debug fallback only. " - + "Applies from the next session.") + Text("Stage 2 (default): explicit decode + Metal present — full HUD latency " + + "breakdown and self-recovery from decode stalls. Stage 1: compressed video " + + "straight to the system layer; freezes on a lost HEVC reference, so it's a " + + "debug fallback only. Applies from the next session.") .font(.geist(12, relativeTo: .caption)) .foregroundStyle(.secondary) } @@ -363,12 +356,11 @@ extension SettingsView { } header: { Text("Video quality") } footer: { - Text("Codec is a preference — the host falls back if it can't encode the one you pick " - + "(and 10-bit/4:4:4 are HEVC-only). HDR requests a 10-bit BT.2020 PQ (HDR10) stream — " - + "it only engages when the host is sending HDR content AND this display supports HDR. " - + "4:4:4 requests full chroma (sharper text/UI, more bandwidth) — it only engages when " - + "this device can hardware-decode it AND the host opted in. Otherwise the stream stays " - + "8-bit 4:2:0 SDR. Applies from the next session.") + Text("Codec is a preference; the host falls back if it can't encode your choice. " + + "HDR (HDR10) and full chroma (4:4:4) are HEVC-only, and each engages only when " + + "both this device and the host support it — otherwise the stream stays 8-bit " + + "4:2:0 SDR. 4:4:4 sharpens text and UI for extra bandwidth. Applies from the " + + "next session.") .font(.geist(12, relativeTo: .caption)) .foregroundStyle(.secondary) } @@ -399,9 +391,8 @@ extension SettingsView { Text("Experimental") } footer: { Text("Adds a “Browse Library…” action to each host that lists its games " - + "(Steam + custom) via the host's management API; tap a title to launch it. " - + "Works once you've paired with the host — the library is authorized by this " - + "device's certificate, with no extra host setup.") + + "(Steam + custom); tap a title to launch it. Works once you've paired — no " + + "extra host setup.") .font(.geist(12, relativeTo: .caption)) .foregroundStyle(.secondary) } diff --git a/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Support.swift b/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Support.swift index 1530de2b..be9f3d23 100644 --- a/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Support.swift +++ b/clients/apple/Sources/PunktfunkClient/Settings/SettingsView+Support.swift @@ -54,32 +54,41 @@ extension SettingsView { // MARK: - Statistics static var statisticsFooter: String { - let base = "The overlay shows resolution, frame rate, throughput and latency while " - + "streaming, in the chosen corner." + let base = "Shows resolution, frame rate, throughput and latency in the chosen " + + "corner while streaming." #if os(macOS) || os(iOS) - return base + " Toggle it any time with ⌘⇧S." + return base + " Toggle it any time with ⌃⌥⇧S." #else return base #endif } + // MARK: - Audio + + static var audioFooter: String { + #if os(macOS) + return "Host audio plays through the chosen speaker; your microphone feeds the host's " + + "virtual mic. System default follows your Mac's device changes. Applies from the " + + "next session." + #else + return "Host audio plays locally; your microphone feeds the host's virtual mic. " + + "Applies from the next session." + #endif + } + // MARK: - Controllers static let controllersFooter = - "One controller is forwarded to the host, as player 1 — Automatic picks the most " - + "recently connected one. The type is the virtual pad the host creates: Automatic " - + "matches the controller (a DualSense gets adaptive triggers, lightbar, touchpad " - + "and motion; a DualShock 4 the same minus adaptive triggers), and changes apply " - + "from the next session. Two identical controllers may swap a manual selection " - + "after reconnecting." + "One controller is forwarded as player 1 — Automatic picks the most recently " + + "connected. Type is the virtual pad the host creates; Automatic matches your " + + "controller (a DualSense keeps adaptive triggers, lightbar, touchpad and motion). " + + "Applies from the next session." #if !os(tvOS) static let gamepadUIFooter = - "When a controller is connected, the host list and game library switch to a " - + "controller-friendly layout — larger focus targets, controller-navigable settings, " - + "and a swipeable cover browser for the library. Turn this off to always use the " - + "standard layout. (The system may still move basic focus with a controller " - + "connected even with this off — that's outside the app's control.)" + "When a controller connects, the host list and library switch to a controller-" + + "friendly layout — larger focus targets and a swipeable cover browser. Turn this " + + "off to always use the standard layout." #endif /// "Use controller" choices for this view's manager (see `SettingsOptions.controllerOptions`).