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