// // ContentView.swift // oAI // // Root navigation container // import SwiftUI struct ContentView: View { @Environment(ChatViewModel.self) var chatViewModel var body: some View { @Bindable var vm = chatViewModel NavigationStack { ChatView( onModelSelect: { chatViewModel.showModelSelector = true }, onProviderChange: { newProvider in chatViewModel.changeProvider(newProvider) } ) .navigationTitle("") .toolbar { #if os(macOS) macOSToolbar #endif } } .frame(minWidth: 600, minHeight: 400) #if os(macOS) .onKeyPress(.return, phases: .down) { press in if press.modifiers.contains(.command) { chatViewModel.sendMessage() return .handled } return .ignored } #endif .sheet(isPresented: $vm.showModelSelector) { ModelSelectorView( models: chatViewModel.availableModels, selectedModel: chatViewModel.selectedModel, onSelect: { model in chatViewModel.selectedModel = model chatViewModel.showModelSelector = false } ) .task { if chatViewModel.availableModels.count <= 10 { await chatViewModel.loadAvailableModels() } } } .sheet(isPresented: $vm.showSettings, onDismiss: { chatViewModel.syncFromSettings() }) { SettingsView() } .sheet(isPresented: $vm.showStats) { StatsView( stats: chatViewModel.sessionStats, model: chatViewModel.selectedModel, provider: chatViewModel.currentProvider ) } .sheet(isPresented: $vm.showHelp) { HelpView() } .sheet(isPresented: $vm.showCredits) { CreditsView(provider: chatViewModel.currentProvider) } .sheet(isPresented: $vm.showConversations) { ConversationListView(onLoad: { conversation in chatViewModel.loadConversation(conversation) }) } .sheet(item: $vm.modelInfoTarget) { model in ModelInfoView(model: model) } } #if os(macOS) @ToolbarContentBuilder private var macOSToolbar: some ToolbarContent { ToolbarItemGroup(placement: .automatic) { // New conversation Button(action: { chatViewModel.newConversation() }) { Label("New Chat", systemImage: "square.and.pencil") } .keyboardShortcut("n", modifiers: .command) .help("New conversation") Button(action: { chatViewModel.showConversations = true }) { Label("History", systemImage: "clock.arrow.circlepath") } .keyboardShortcut("l", modifiers: .command) .help("Saved conversations (Cmd+L)") Spacer() Button(action: { chatViewModel.showModelSelector = true }) { Label("Model", systemImage: "cpu") } .keyboardShortcut("m", modifiers: .command) .help("Select AI model (Cmd+M)") Button(action: { if let model = chatViewModel.selectedModel { chatViewModel.modelInfoTarget = model } }) { Label("Model Info", systemImage: "info.circle") } .keyboardShortcut("i", modifiers: .command) .help("Model info (Cmd+I)") .disabled(chatViewModel.selectedModel == nil) Button(action: { chatViewModel.showStats = true }) { Label("Stats", systemImage: "chart.bar") } .keyboardShortcut("s", modifiers: .command) .help("Session statistics (Cmd+S)") Button(action: { chatViewModel.showCredits = true }) { Label("Credits", systemImage: "creditcard") } .help("Check API credits") Spacer() Button(action: { chatViewModel.showSettings = true }) { Label("Settings", systemImage: "gearshape") } .keyboardShortcut(",", modifiers: .command) .help("Settings (Cmd+,)") Button(action: { chatViewModel.showHelp = true }) { Label("Help", systemImage: "questionmark.circle") } .keyboardShortcut("/", modifiers: .command) .help("Help & commands (Cmd+/)") } } #endif } #Preview { ContentView() .environment(ChatViewModel()) }