/ Jade / ChatView.swift
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  }