Files
bearwave-mac/Sources/BearWaveApp/BearWaveApp.swift
2026-06-25 09:48:58 +02:00

108 lines
3.6 KiB
Swift

import AppKit
import BearWaveCore
import SwiftUI
@main
struct BearWaveApp: App {
private static let releaseVersion = "v0.1.0-alpha.1"
private static let buildVersion = "1"
@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(replacing: .appInfo) {
Button("About BearWave") {
showAboutPanel()
}
}
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 showAboutPanel() {
var options: [NSApplication.AboutPanelOptionKey: Any] = [
.applicationName: "BearWave",
.applicationVersion: Self.releaseVersion,
.version: "Build \(Self.buildVersion)"
]
if let iconURL = Bundle.main.url(forResource: "bearwave_about", withExtension: "png"),
let icon = NSImage(contentsOf: iconURL) {
options[.applicationIcon] = icon
}
NSApp.orderFrontStandardAboutPanel(options: options)
NSApp.activate(ignoringOtherApps: true)
}
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
}
}