Zum Inhalt

apple/PhysarumApp/Sources/TV/TVHUDView.swift

#if os(tvOS)
import SwiftUI
import UIKit
import PhysarumEngine

/// Transient top-center HUD reflecting `AmbientController.hud`: cycle on/off (play/pause)
/// or the new preset name (manual swipe). Non-interactive; the controller owns the ~2s
/// lifetime, this view only fades the current content in and out.
struct TVHUDView: View {
    let controller: AmbientController

    var body: some View {
        VStack {
            if let hud = controller.hud {
                content(for: hud)
                    .padding(.horizontal, 28)
                    .padding(.vertical, 14)
                    .background(.black.opacity(0.55), in: Capsule())
                    .foregroundStyle(.white)
                    .padding(.top, 24)
                    .transition(.opacity)
            }
            Spacer()
        }
        .allowsHitTesting(false)
        .animation(.easeInOut(duration: 0.25), value: controller.hud)
        // The feedback this increment adds was previously silent; mirror it to VoiceOver.
        .onChange(of: controller.hud) { _, hud in
            guard let hud else { return }
            UIAccessibility.post(notification: .announcement, argument: announcement(for: hud))
        }
    }

    private func announcement(for hud: HUDContent) -> String {
        switch hud {
        case .cycle(let on): return on ? "Cycle on" : "Cycle off"
        case .preset(let name): return name
        }
    }

    @ViewBuilder private func content(for hud: HUDContent) -> some View {
        switch hud {
        case .cycle(let on):
            Label(on ? "Cycle On" : "Cycle Off",
                  systemImage: on ? "arrow.triangle.2.circlepath" : "pause.fill")
                .font(.title2.weight(.semibold))
        case .preset(let name):
            Text(name).font(.title2.weight(.semibold))
        }
    }
}
#endif