@@ -10,7 +10,7 @@ import Luminare
1010import SwiftUI
1111
1212struct ConversationSidebarView : View {
13- @Environment ( ConversationViewModel . self) private var conversationViewModel
13+ @Environment ( ConversationViewModel . self) private var vm
1414 @Environment ( \. managedObjectContext) private var viewContext
1515
1616 @FetchRequest (
@@ -22,70 +22,82 @@ struct ConversationSidebarView: View {
2222 @Binding var selectedConversation : Conversation ?
2323
2424 @State private var keyword = " "
25- @State private var showingNewConversationAlert = false
26- @State private var newConversationTitle = " "
27- @State private var showingClearConfirmation = false
2825
2926 let padding : CGFloat = 8
3027
3128 var body : some View {
3229 VStack ( spacing: 0 ) {
33- HStack {
34- Spacer ( )
35- Button ( action: conversationViewModel. createConversation) {
36- Image ( systemName: " plus " )
37- }
30+ headerView ( )
31+ logoView ( )
32+ searchField ( )
33+ conversationList ( )
34+ }
35+ . background ( . black. opacity ( 0.4 ) )
36+ }
3837
39- SettingsLink {
40- Image ( systemName: " gear " )
41- }
38+ @MainActor
39+ @ViewBuilder
40+ private func headerView( ) -> some View {
41+ HStack {
42+ Spacer ( )
43+ Button ( action: vm. createConversation) {
44+ Image ( systemName: " plus " )
4245 }
43- . frame ( height: 50 )
44- . padding ( . horizontal, padding)
45- . buttonStyle ( . plain)
46-
47- HStack {
48- Image ( " AppLogo " )
49- . resizable ( )
50- . aspectRatio ( contentMode: . fit)
51- . frame ( width: 60 , height: 60 )
52- . shadow ( radius: 5 )
53- Text ( " ChatMLX " )
54- . font ( . title)
55- . fontWeight ( . bold)
46+ SettingsLink {
47+ Image ( systemName: " gear " )
5648 }
49+ }
50+ . frame ( height: 50 )
51+ . padding ( . horizontal, padding)
52+ . buttonStyle ( . plain)
53+ }
5754
58- LuminareSection {
59- UltramanTextField (
60- $keyword, placeholder: Text ( " Search Conversation... " ) ,
61- onSubmit: updateSearchPredicate
62- )
55+ @MainActor
56+ @ViewBuilder
57+ private func logoView( ) -> some View {
58+ HStack {
59+ Image ( " AppLogo " )
60+ . resizable ( )
61+ . aspectRatio ( contentMode: . fit)
62+ . frame ( width: 60 , height: 60 )
63+ . shadow ( radius: 5 )
64+ Text ( " ChatMLX " )
65+ . font ( . title)
66+ . fontWeight ( . bold)
67+ }
68+ }
6369
64- . frame ( height: 25 )
65- } . padding ( . horizontal, padding)
70+ @MainActor
71+ @ViewBuilder
72+ private func searchField( ) -> some View {
73+ LuminareSection {
74+ UltramanTextField (
75+ $keyword,
76+ placeholder: Text ( " Search Conversation... " ) ,
77+ onSubmit: updateSearchPredicate
78+ )
79+ . frame ( height: 25 )
80+ }
81+ . padding ( . horizontal, padding)
82+ }
6683
67- ScrollView {
68- LazyVStack ( spacing: 0 ) {
69- ForEach ( conversations) { conversation in
70- ConversationSidebarItem (
71- conversation: conversation,
72- selectedConversation: $selectedConversation
73- )
74- }
84+ @MainActor
85+ @ViewBuilder
86+ private func conversationList( ) -> some View {
87+ ScrollView {
88+ LazyVStack ( spacing: 0 ) {
89+ ForEach ( conversations) { conversation in
90+ ConversationSidebarItem ( conversation: conversation)
7591 }
7692 }
77- . padding ( . top, 6 )
7893 }
79- . background ( . black . opacity ( 0.4 ) )
94+ . padding ( . top , 6 )
8095 }
8196
8297 private func updateSearchPredicate( ) {
83- if keyword. isEmpty {
84- conversations. nsPredicate = nil
85- } else {
86- conversations. nsPredicate = NSPredicate (
87- format: " title CONTAINS [cd] %@ OR ANY messages.content CONTAINS [cd] %@ " , keyword,
88- keyword)
89- }
98+ conversations. nsPredicate = keyword. isEmpty ? nil : NSPredicate (
99+ format: " title CONTAINS [cd] %@ OR ANY messages.content CONTAINS [cd] %@ " ,
100+ keyword, keyword
101+ )
90102 }
91103}
0 commit comments