108 lines
3.6 KiB
Swift
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
|
|
}
|
|
}
|