ChatView.swift
1 // 2 // ChatView.swift 3 // MLXChatExample 4 // 5 // Created by İbrahim Çetin on 20.04.2025. 6 // 7 8 import AVFoundation 9 import AVKit 10 import SwiftUI 11 12 /// Main chat interface view that manages the conversation UI and user interactions. 13 /// Displays messages, handles media attachments, and provides input controls. 14 struct ChatView: View { 15 /// View model that manages the chat state and business logic 16 @Bindable private var vm: ChatViewModel 17 @Binding var selectedTab: Int 18 19 /// Initializes the chat view with a view model 20 /// - Parameter viewModel: The view model to manage chat state 21 init(viewModel: ChatViewModel, selectedTab: Binding<Int>) { 22 self.vm = viewModel 23 self._selectedTab = selectedTab 24 } 25 26 var body: some View { 27 NavigationStack { 28 VStack(spacing: 0) { 29 // Display conversation history 30 ConversationView(messages: vm.messages, viewModel: vm, selectedTab: $selectedTab) 31 32 Divider() 33 34 // Show media previews if attachments are present 35 if !vm.mediaSelection.isEmpty { 36 MediaPreviewsView(mediaSelection: vm.mediaSelection) 37 } 38 39 // Input field with send and media attachment buttons 40 PromptField( 41 prompt: $vm.prompt, 42 sendButtonAction: vm.generate, 43 // Only show media button for vision-capable models 44 mediaButtonAction: vm.selectedModel.isVisionModel 45 ? { 46 vm.mediaSelection.isShowing = true 47 } : nil 48 ) 49 .padding() 50 } 51 .navigationTitle("Jade") 52 .toolbar { 53 ChatToolbarView(vm: vm) 54 } 55 // Handle media file selection 56 .fileImporter( 57 isPresented: $vm.mediaSelection.isShowing, 58 allowedContentTypes: [.image, .movie], 59 onCompletion: vm.addMedia 60 ) 61 } 62 } 63 } 64 65 #Preview { 66 ChatViewPreviewWrapper() 67 } 68 69 private struct ChatViewPreviewWrapper: View { 70 @State private var selectedTab = 0 71 72 var body: some View { 73 ChatView(viewModel: ChatViewModel(mlxService: MLXService()), selectedTab: $selectedTab) 74 } 75 }