feat(apple/clipboard): macOS client half of the shared clipboard (Phase 1 §5)
ci / web (pull_request) Successful in 48s
ci / docs-site (pull_request) Successful in 53s
apple / swift (pull_request) Successful in 1m16s
apple / screenshots (pull_request) Has been skipped
android / android (pull_request) Has been cancelled
ci / rust (pull_request) Has been cancelled
ci / bench (pull_request) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (pull_request) Has been cancelled
ci / web (pull_request) Successful in 48s
ci / docs-site (pull_request) Successful in 53s
apple / swift (pull_request) Successful in 1m16s
apple / screenshots (pull_request) Has been skipped
android / android (pull_request) Has been cancelled
ci / rust (pull_request) Has been cancelled
ci / bench (pull_request) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (pull_request) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (pull_request) Has been cancelled
The NSPasteboard bridge completing Phase 1 (design/clipboard-and-file-transfer.md §5) — with the host backends on this branch, copy/paste now crosses the wire in both directions on macOS. Lazy in both directions: - PunktfunkConnection grows the clipboard plane: its own clipboardLock (close() joins it like the other pullers), hostCaps/hostSupportsClipboard from the Welcome, the typed ClipEvent vocabulary, and the six ABI wrappers (clipControl/clipOffer/clipFetch/clipServe/clipCancel/nextClipboard — borrowed event payloads copied out before the next poll). - ClipboardSync (PunktfunkKit, macOS-only): one drain thread bridging NSPasteboard.general ↔ the QUIC clipboard plane. Local copies announce format lists via a 500 ms changeCount poll (+ immediate on app activation); bytes leave only on a host FetchRequest, answered from the live pasteboard and seq-guarded against staleness. Host copies install one NSPasteboardItem whose data provider fires only when a Mac app actually pastes, then blocks its provider thread (never main) on a 10 s-bounded fetch. Concealed/Transient pasteboards (password managers) are never announced; our own writes are changeCount-suppressed (§3.4). Text/RTF/HTML/PNG; files ride Phase 2. - UI: per-host "Share clipboard with this host" toggle (StoredHost.clipboardSync, optional for saved-JSON forward-compat — wire-format tests extended), a mid-session Share/Stop Sharing Clipboard item in the Stream menu (⌃⌥⇧C, greyed without HOST_CAP_CLIPBOARD), SessionModel owning the lifecycle (start on streaming after the trust gate, drain joined off-main on teardown). swift build + swift test green (macOS). Requires the ABI v8 xcframework (scripts/build-xcframework.sh). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -34,11 +34,16 @@ public struct StoredHost: Identifiable, Codable, Hashable {
|
||||
/// client can send a magic packet to wake the host later (when it's asleep and no longer
|
||||
/// advertising). Optional (same forward-compat reason as `mgmtPort`); nil until first learned.
|
||||
public var macAddresses: [String]?
|
||||
/// Share the clipboard with this host (macOS sessions; design/clipboard-and-file-transfer.md
|
||||
/// §5.3). Opt-in per host: nil/false = off (nil also keeps older saved JSON decoding — same
|
||||
/// forward-compat reason as `mgmtPort`). Honored only when the host advertises
|
||||
/// `HOST_CAP_CLIPBOARD`.
|
||||
public var clipboardSync: Bool?
|
||||
|
||||
public init(
|
||||
id: UUID = UUID(), name: String, address: String, port: UInt16 = 9777,
|
||||
pinnedSHA256: Data? = nil, lastConnected: Date? = nil, mgmtPort: UInt16? = nil,
|
||||
macAddresses: [String]? = nil
|
||||
macAddresses: [String]? = nil, clipboardSync: Bool? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
@@ -48,6 +53,7 @@ public struct StoredHost: Identifiable, Codable, Hashable {
|
||||
self.lastConnected = lastConnected
|
||||
self.mgmtPort = mgmtPort
|
||||
self.macAddresses = macAddresses
|
||||
self.clipboardSync = clipboardSync
|
||||
}
|
||||
|
||||
public var displayName: String { name.isEmpty ? address : name }
|
||||
|
||||
Reference in New Issue
Block a user