From 0f85b592374fe9ff24d5e809a723d214a334c88c Mon Sep 17 00:00:00 2001 From: portersky Date: Mon, 17 Aug 2026 15:04:59 +0200 Subject: [PATCH] feat: add SwiftUI app shell Replace the command-line entry point with a windowed SwiftUI app showing live dongle status, a controller placeholder, and a pair button. The app runs as a regular foreground app even when launched directly from the build directory. Co-Authored-By: deepseek (deepseek/deepseek-v4-pro-0813): built SwiftUI app shell --- CMakeLists.txt | 2 +- src/app/main.swift | 96 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 88 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d272ef5..a593039 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ if(NOT CMAKE_GENERATOR MATCHES "^(Ninja|Xcode)$") endif() cmake_minimum_required(VERSION 3.21) -project(xone_macos VERSION 0.1.1 LANGUAGES CXX Swift) +project(xone_macos VERSION 0.1.2 LANGUAGES CXX Swift) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) diff --git a/src/app/main.swift b/src/app/main.swift index e940691..ad270d8 100644 --- a/src/app/main.swift +++ b/src/app/main.swift @@ -1,13 +1,91 @@ -// xone_macos — macOS app entry point (Swift) -// TODO(phase 5): device discovery, pairing UI, status display, menubar icon. +// xone_macos — macOS app entry point (SwiftUI) +// TODO(phase 5): device discovery (IOKit notifications), pairing UI, +// status display, preferences, menubar icon. -import Foundation +import AppKit +import Combine +import SwiftUI -let version = String(cString: xone_version()) -print("xone_macos \(version)") +struct XoneApp: App { + @NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate -if xone_dongle_present() { - print("Xbox Wireless Dongle detected") -} else { - print("No Xbox Wireless Dongle detected (plug in the dongle and retry)") + var body: some Scene { + WindowGroup { + ContentView() + } + } } +final class AppDelegate: NSObject, NSApplicationDelegate { + func applicationDidFinishLaunching(_ notification: Notification) { + // Present as a regular app (foreground window) even when launched + // directly from the build directory instead of an .app bundle. + NSApp.setActivationPolicy(.regular) + NSApp.activate(ignoringOtherApps: true) + } +} + +struct ContentView: View { + @State private var donglePresent = false + + private let timer = Timer.publish(every: 1.0, on: .main, in: .common) + .autoconnect() + + var body: some View { + VStack(alignment: .leading, spacing: 16) { + HStack(spacing: 8) { + Image(systemName: "gamecontroller.fill") + .font(.largeTitle) + Text("xone_macos") + .font(.title) + .bold() + } + + statusView + + Divider() + + controllersView + + HStack { + Button("Pair Controller") { + // TODO(phase 5): pairing UI (LED blink + controller press) + } + .disabled(!donglePresent) + + Spacer() + + Text("v\(String(cString: xone_version()))") + .foregroundStyle(.secondary) + } + } + .padding(24) + .frame(width: 420) + .frame(minHeight: 320) + .onReceive(timer) { _ in + donglePresent = xone_dongle_present() + } + } + + private var statusView: some View { + HStack(spacing: 8) { + Circle() + .fill(donglePresent ? Color.green : Color.red) + .frame(width: 10, height: 10) + Text(donglePresent ? "Dongle connected" : "No dongle detected") + .font(.headline) + } + } + + private var controllersView: some View { + VStack(alignment: .leading, spacing: 8) { + Text("Controllers") + .font(.headline) + Text("No controllers connected.") + .foregroundStyle(.secondary) + } + } +} + +// Entry point: SwiftUI App provides a static main() (top-level code lives in +// main.swift, which CMake's Swift driver expects for executables). +XoneApp.main()