Files
punktfunk/clients/apple/Sources/PunktfunkKit/OsIcon.swift
T
enricobuehlerandClaude Fable 5 88c8688b47 feat(client/apple): host cards wear the OS mark, and the store learns it
`DiscoveredHost` reads the new `os=` TXT (sanitized in PunktfunkShared's
OsChain.swift — the pure grammar + walk, mirrored from pf-client-core so every
platform resolves identically, and dependency-free so the widget could use it);
`StoredHost` appends optional `osChain` per the frozen app↔widget contract
(optional + appended last; legacy JSON still decodes, pinned by the round-trip
tests), and `HostStore.updateOsChain` learns it beside the MACs.

The art rides PunktfunkKit's proven resource path (the fonts precedent): ten
template vector imagesets in Resources/OsIcons.xcassets, compiled by the Xcode
build into the Kit bundle's Assets.car (verified: all ten resolve in the built
app) and tinting via foregroundStyle like an SF Symbol. Saved and discovered
cards lead their status line with the mark; a host that advertises nothing
renders exactly as before. GamepadHome tile + widget marks are follow-ups.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-29 17:58:33 +02:00

25 lines
1.2 KiB
Swift

// The host cards' OS marks: template vector imagesets in Resources/OsIcons.xcassets
// (derived from the repo's assets/os-icons masters — Font Awesome Free brands CC BY 4.0 +
// Simple Icons CC0; provenance in that directory's README), resolved from the host's
// OS-identity chain via PunktfunkShared's `osIconTokens` walk. Template rendering means
// they tint with `foregroundStyle` like an SF Symbol.
import PunktfunkShared
import SwiftUI
/// The icon tokens this client ships art for. A distro without its own mark (Bazzite,
/// CachyOS, ...) degrades to its family's and finally to Tux via the chain walk.
private let osIconTokensShipped: Set<String> = [
"windows", "apple", "linux", "steam", "ubuntu", "fedora", "arch", "debian", "nixos",
"opensuse",
]
/// The mark for an OS-identity chain (`linux/fedora/bazzite`, ...), or nil — no view at
/// all — when the host doesn't advertise one / nothing in the chain is recognized, so
/// those cards render exactly as they did before the field existed.
public func osIconImage(for chain: String?) -> Image? {
osIconTokens(chain)
.first(where: osIconTokensShipped.contains)
.map { Image("os-\($0)", bundle: .module) }
}