Create BearWave macOS radio-first app

This commit is contained in:
Sebastian Palencsar
2026-06-25 09:21:42 +02:00
commit b47b591e03
42 changed files with 3814 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
import AppKit
import BearWaveCore
import SwiftUI
@main
struct BearWaveApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) private var appDelegate
@State private var model = AppModel()
@State private var isMiniPlayer = false
private static var windowWidth: Double {
let screen = NSScreen.main ?? NSScreen.screens.first
let width = screen?.visibleFrame.width ?? 1440
if width >= 1920 { return 1600 }
return 1255
}
var body: some Scene {
WindowGroup("BearWave", id: "main") {
ContentView(isMiniPlayer: $isMiniPlayer)
.environment(model)
.frame(
minWidth: isMiniPlayer ? 555 : 1255,
minHeight: isMiniPlayer ? 110 : 650
)
.onChange(of: isMiniPlayer) { _, newValue in
resizeWindow(toMini: newValue)
}
.task {
await model.start()
}
}
.defaultSize(width: Self.windowWidth, height: 720)
.commands {
CommandGroup(after: .appTermination) {
Button("Play/Pause") {
model.playback.togglePlayPause()
}
.keyboardShortcut(.space, modifiers: [])
}
CommandGroup(after: .newItem) {
Button(isMiniPlayer ? "Show Full Window" : "Mini Player") {
isMiniPlayer.toggle()
}
.keyboardShortcut("m", modifiers: .command)
}
}
MenuBarExtra("BearWave", systemImage: model.playback.isPlaying ? "radio.fill" : "radio") {
MenuBarContentView()
.environment(model)
}
Settings {
SettingsView()
.environment(model)
.frame(width: 520)
}
}
private func resizeWindow(toMini: Bool) {
let targetSize = toMini ? CGSize(width: 555, height: 110) : CGSize(width: Self.windowWidth, height: 720)
Task { @MainActor in
guard let window = NSApp.mainWindow ?? NSApp.windows.first else { return }
let currentFrame = window.frame
var newFrame = currentFrame
newFrame.size = targetSize
newFrame.origin.y = currentFrame.maxY - targetSize.height
window.minSize = targetSize
window.setFrame(newFrame, display: true, animate: true)
}
}
}
final class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ notification: Notification) {
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
}
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
false
}
}