// // oAIApp.swift // oAI // // Main app entry point // // SPDX-License-Identifier: AGPL-3.0-or-later // Copyright (C) 2026 Rune Olsen // // This file is part of oAI. // // oAI is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // oAI is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General // Public License for more details. // // You should have received a copy of the GNU Affero General Public // License along with oAI. If not, see . import SwiftUI #if os(macOS) import AppKit #endif @main struct oAIApp: App { @State private var chatViewModel = ChatViewModel() @State private var showAbout = false init() { // Start email handler on app launch EmailHandlerService.shared.start() // Sync Git changes on app launch (pull + import) Task { await GitSyncService.shared.syncOnStartup() } } var body: some Scene { WindowGroup { ContentView() .environment(chatViewModel) .preferredColorScheme(.dark) .sheet(isPresented: $showAbout) { AboutView() } #if os(macOS) .onReceive(NotificationCenter.default.publisher(for: NSApplication.willTerminateNotification)) { _ in // Trigger auto-save on app quit Task { await chatViewModel.onAppWillTerminate() } } #endif } #if os(macOS) .windowStyle(.hiddenTitleBar) .windowToolbarStyle(.unified) .defaultSize(width: 1024, height: 800) .windowResizability(.contentMinSize) .commands { CommandGroup(replacing: .appInfo) { Button("About oAI") { showAbout = true } } CommandGroup(replacing: .appSettings) { Button("Settings...") { chatViewModel.showSettings = true } .keyboardShortcut(",", modifiers: .command) } CommandGroup(replacing: .help) { Button("oAI Help") { openHelp() } .keyboardShortcut("?", modifiers: .command) } } #endif } #if os(macOS) private func openHelp() { if let helpBookURL = Bundle.main.url(forResource: "oAI.help", withExtension: nil) { NSWorkspace.shared.open(helpBookURL.appendingPathComponent("Contents/Resources/en.lproj/index.html")) } else { // Fallback to Apple Help if help book not found NSHelpManager.shared.openHelpAnchor("", inBook: Bundle.main.object(forInfoDictionaryKey: "CFBundleHelpBookName") as? String) } } #endif }