feat(apple): wake-until-up overlay + host edit with MAC prefill
apple / swift (push) Successful in 1m10s
arch / build-publish (push) Successful in 5m17s
android / android (push) Successful in 7m30s
ci / web (push) Successful in 1m7s
ci / docs-site (push) Successful in 1m11s
release / apple (push) Successful in 8m39s
ci / rust (push) Successful in 4m53s
deb / build-publish (push) Successful in 2m58s
decky / build-publish (push) Successful in 16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 4s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 4s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 5s
ci / bench (push) Successful in 4m50s
apple / screenshots (push) Successful in 5m44s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 10m9s
docker / deploy-docs (push) Successful in 18s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 9m52s

- HostWaker + WakeOverlay: after sending the Wake-on-LAN packet, wait until the host
  is really back (resend + mDNS poll, timeout, cancel/retry) before connecting.
  macOS-only in practice — WoL stays gated off on iOS/tvOS pending the multicast
  entitlement.
- Add/Edit host sheet gains a Wake-on-LAN MAC field, prefilled from the stored MAC
  or the live mDNS advert; parseMacs validates aa:bb:cc:dd:ee:ff.
- Gamepad chrome/home and glass-style polish.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-05 20:04:47 +02:00
parent 4a87cef98c
commit 88348153f3
14 changed files with 759 additions and 245 deletions
@@ -58,16 +58,19 @@ struct GamepadAddHostView: View {
.padding(.top, gamepadTitleTopPadding(compact: compact))
.padding(.bottom, compact ? 4 : 8)
.frame(maxWidth: .infinity)
.overlay(alignment: .topTrailing) { closeButton.padding(.trailing, 20) }
.overlay(alignment: .topTrailing) { closeButton.padding(.top, 20).padding(.trailing, 20) }
.background { GamepadTrayScrim(edge: .top) }
}
.safeAreaInset(edge: .bottom, spacing: 0) {
bottomTray
.padding(.horizontal, 22)
.padding(.vertical, compact ? 6 : 10)
// Equal distance from the left and bottom edges for the legend pill (see GamepadHomeView).
.padding(.horizontal, compact ? 12 : 18)
.padding(.bottom, compact ? 12 : 18)
.padding(.top, compact ? 6 : 10)
.background { GamepadTrayScrim(edge: .bottom) }
}
.background { GamepadScreenBackground() }
// No aurora the same clean Liquid-Glass-over-dark base as the gamepad settings screen.
.background { GamepadFormBackground() }
// A port can't exceed 5 digits cap while typing so the row can't grow absurd.
.onChange(of: port) { _, value in
if value.count > 5 { port = String(value.prefix(5)) }
@@ -165,14 +168,16 @@ struct GamepadAddHostView: View {
}
.padding(.horizontal, 16)
.padding(.vertical, 13)
.background {
RoundedRectangle(cornerRadius: 14, style: .continuous)
.fill(.white.opacity(focused || editing == row.id ? 0.1 : 0))
}
// Liquid Glass rows, matching the settings screen; the focused (or actively edited) row
// takes the brand wash, and the edited row keeps its brand caret border.
.consoleGlass(
RoundedRectangle(cornerRadius: 14, style: .continuous),
tint: (focused || editing == row.id) ? Color.brand.opacity(0.30) : nil,
interactive: focused)
.overlay {
RoundedRectangle(cornerRadius: 14, style: .continuous)
.strokeBorder(
editing == row.id ? Color.brand.opacity(0.7) : .white.opacity(focused ? 0.22 : 0),
editing == row.id ? Color.brand.opacity(0.7) : .white.opacity(focused ? 0.28 : 0.06),
lineWidth: 1)
}
.scaleEffect(focused ? 1.0 : 0.98)