Files
punktfunk/clients/apple/Sources/PunktfunkClient/Support/LinkClipboard.swift
T
enricobuehlerandClaude Opus 5 25b127803f feat(client/apple): bind a host to a profile, connect with one, pin one as its own card
The host surfaces (design §5.2/§5.2a). A bound host wears a tinted chip that says
what a click will do. The card menu grows "Connect with ▸" — a ONE-OFF that never
rebinds, with a checkmark on the binding and an explicit "Set Default Profile" as
its last item for the users who do want to rebind from there — plus "Pin as Card ▸"
and "Copy Link".

A pinned host+profile combo becomes its own card next to its host: same record,
same live status, the profile as the prominent subtitle, one click to connect. It
is an extra grid ENTRY, never a duplicated host record — duplicating would fork
pairing, Wake-on-LAN and renames. Its menu carries only connect-shaped actions;
edit, pair, forget and remove stay on the primary card, where the thing they act on
lives. On the gamepad carousel and tvOS the same pins are tiles, which is the whole
point: focus-and-press is what those surfaces do well, and menus are not.

The edit sheet binds and pins; both rows vanish when no profiles exist, so a user
who never makes one sees exactly today's sheet. A dangling binding renders as
"Default settings (profile deleted)" and is cleaned up on save.

The speed test finally writes where the tested host reads. Unbound: the global, as
before. Bound to a profile that overrides bitrate: that override. Bound to one that
inherits it: both are offered, because either is defensible and guessing would
silently pick one. Every button names its target, and the probe now runs at the
mode that host would actually stream — the measurement is the streaming path.

Shortcuts gains `ProfileEntity` over the App-Group catalog and a Profile parameter
on Connect, still round-tripping through the URL router rather than opening a second
connect path. Connect and Wake drop their iOS wall — AppIntents is real on macOS and
tvOS, and "Stream Desktop with Work" from Spotlight was the ask; only the phrases
provider stays iOS-gated, since it bundles the LiveActivityIntent. The deep-link
observer moved out with them: an intent that posts to nobody is a shortcut that
silently does nothing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 12:06:41 +02:00

35 lines
1.1 KiB
Swift

// "Copy Link" on a host or pinned card puts a `punktfunk://` URL on the clipboard — the same
// self-emitted form a shortcut or a Playnite entry would carry (design/client-deep-links.md §5):
// stable id first, with the address and pin alongside so it still resolves after the record is
// re-addressed or the store is wiped.
//
// The pasteboard is the one part of that with no cross-platform API, hence this two-line shim.
// tvOS has no clipboard at all, so the affordance simply isn't offered there.
#if os(macOS)
import AppKit
#elseif os(iOS)
import UIKit
#endif
enum LinkClipboard {
/// True where a link can actually be copied — the card menus hide the item elsewhere rather
/// than offering an action that silently does nothing.
static var isAvailable: Bool {
#if os(macOS) || os(iOS)
return true
#else
return false
#endif
}
static func copy(_ text: String) {
#if os(macOS)
NSPasteboard.general.clearContents()
NSPasteboard.general.setString(text, forType: .string)
#elseif os(iOS)
UIPasteboard.general.string = text
#endif
}
}