@@ -2,29 +2,34 @@ import LaunchAgentManager
22import Preferences
33import SwiftUI
44
5- final class Settings : ObservableObject {
6- @AppStorage ( \. quitXPCServiceOnXcodeAndAppQuit)
7- var quitXPCServiceOnXcodeAndAppQuit : Bool
8- @AppStorage ( \. realtimeSuggestionToggle)
9- var realtimeSuggestionToggle : Bool
10- @AppStorage ( \. realtimeSuggestionDebounce)
11- var realtimeSuggestionDebounce : Double
12- @AppStorage ( \. suggestionPresentationMode)
13- var suggestionPresentationMode : Preferences . PresentationMode
14- @AppStorage ( \. suggestionWidgetPositionMode)
15- var suggestionWidgetPositionMode : SuggestionWidgetPositionMode
16- @AppStorage ( \. widgetColorScheme)
17- var widgetColorScheme : WidgetColorScheme
18- @AppStorage ( \. acceptSuggestionWithAccessibilityAPI)
19- var acceptSuggestionWithAccessibilityAPI : Bool
20- init ( ) { }
21- }
22-
235struct SettingsView : View {
6+ final class Settings : ObservableObject {
7+ @AppStorage ( \. quitXPCServiceOnXcodeAndAppQuit)
8+ var quitXPCServiceOnXcodeAndAppQuit : Bool
9+ @AppStorage ( \. realtimeSuggestionToggle)
10+ var realtimeSuggestionToggle : Bool
11+ @AppStorage ( \. realtimeSuggestionDebounce)
12+ var realtimeSuggestionDebounce : Double
13+ @AppStorage ( \. suggestionPresentationMode)
14+ var suggestionPresentationMode : Preferences . PresentationMode
15+ @AppStorage ( \. suggestionWidgetPositionMode)
16+ var suggestionWidgetPositionMode : SuggestionWidgetPositionMode
17+ @AppStorage ( \. widgetColorScheme)
18+ var widgetColorScheme : WidgetColorScheme
19+ @AppStorage ( \. acceptSuggestionWithAccessibilityAPI)
20+ var acceptSuggestionWithAccessibilityAPI : Bool
21+ @AppStorage ( \. disableSuggestionFeatureGlobally)
22+ var disableSuggestionFeatureGlobally : Bool
23+ @AppStorage ( \. suggestionFeatureEnabledProjectList)
24+ var suggestionFeatureEnabledProjectList : [ String ]
25+ init ( ) { }
26+ }
27+
2428 @StateObject var settings = Settings ( )
2529 @State var editingRealtimeSuggestionDebounce : Double = UserDefaults . shared
2630 . value ( for: \. realtimeSuggestionDebounce)
2731 @Environment ( \. updateChecker) var updateChecker
32+ @State var isSuggestionFeatureEnabledListPickerOpen = false
2833
2934 var body : some View {
3035 Section {
@@ -90,6 +95,21 @@ struct SettingsView: View {
9095 }
9196 . toggleStyle ( . switch)
9297
98+ HStack {
99+ Toggle ( isOn: $settings. disableSuggestionFeatureGlobally) {
100+ Text ( " Disable suggestion feature globally " )
101+ }
102+ . toggleStyle ( . switch)
103+
104+ Button ( " Enabled List " ) {
105+ isSuggestionFeatureEnabledListPickerOpen = true
106+ }
107+ } . sheet ( isPresented: $isSuggestionFeatureEnabledListPickerOpen) {
108+ SuggestionFeatureEnabledProjectListView (
109+ isOpen: $isSuggestionFeatureEnabledListPickerOpen
110+ )
111+ }
112+
93113 HStack {
94114 Slider ( value: $editingRealtimeSuggestionDebounce, in: 0 ... 2 , step: 0.1 ) {
95115 Text ( " Real-time suggestion fetch debounce " )
@@ -109,7 +129,7 @@ struct SettingsView: View {
109129 . fill ( Color . white. opacity ( 0.2 ) )
110130 )
111131 }
112-
132+
113133 Toggle ( isOn: $settings. acceptSuggestionWithAccessibilityAPI) {
114134 Text ( " Use accessibility API to accept suggestion in widget " )
115135 }
@@ -119,9 +139,136 @@ struct SettingsView: View {
119139 }
120140}
121141
142+ struct SuggestionFeatureEnabledProjectListView : View {
143+ final class Settings : ObservableObject {
144+ @AppStorage ( \. suggestionFeatureEnabledProjectList)
145+ var suggestionFeatureEnabledProjectList : [ String ]
146+
147+ init ( suggestionFeatureEnabledProjectList: AppStorage < [ String ] > ? = nil ) {
148+ if let list = suggestionFeatureEnabledProjectList {
149+ _suggestionFeatureEnabledProjectList = list
150+ }
151+ }
152+ }
153+
154+ var isOpen : Binding < Bool >
155+ @State var isAddingNewProject = false
156+ @StateObject var settings = Settings ( )
157+
158+ var body : some View {
159+ VStack {
160+ HStack {
161+ Button ( action: {
162+ self . isOpen. wrappedValue = false
163+ } ) {
164+ Image ( systemName: " xmark.circle.fill " )
165+ . foregroundStyle ( . secondary)
166+ . padding ( )
167+ }
168+ . buttonStyle ( . plain)
169+ Text ( " Enabled Projects " )
170+ Spacer ( )
171+ Button ( action: {
172+ isAddingNewProject = true
173+ } ) {
174+ Image ( systemName: " plus.circle.fill " )
175+ . foregroundStyle ( . secondary)
176+ . padding ( )
177+ }
178+ . buttonStyle ( . plain)
179+ }
180+ . background ( . black. opacity ( 0.2 ) )
181+
182+ List {
183+ ForEach (
184+ settings. suggestionFeatureEnabledProjectList,
185+ id: \. self
186+ ) { project in
187+ HStack {
188+ Text ( project)
189+ . contextMenu {
190+ Button ( " Remove " ) {
191+ settings. suggestionFeatureEnabledProjectList. removeAll (
192+ where: { $0 == project }
193+ )
194+ }
195+ }
196+ Spacer ( )
197+
198+ Button ( action: {
199+ settings. suggestionFeatureEnabledProjectList. removeAll (
200+ where: { $0 == project }
201+ )
202+ } ) {
203+ Image ( systemName: " trash.fill " )
204+ . foregroundStyle ( . secondary)
205+ }
206+ . buttonStyle ( . plain)
207+ }
208+ }
209+ }
210+ . overlay {
211+ if settings. suggestionFeatureEnabledProjectList. isEmpty {
212+ Text ( """
213+ Empty
214+ Add project with " + " button
215+ Or right clicking the circular widget
216+ """ )
217+ . multilineTextAlignment ( . center)
218+ }
219+ }
220+ }
221+ . frame ( width: 300 , height: 400 )
222+ . sheet ( isPresented: $isAddingNewProject) {
223+ SuggestionFeatureAddEnabledProjectView ( isOpen: $isAddingNewProject, settings: settings)
224+ }
225+ }
226+ }
227+
228+ struct SuggestionFeatureAddEnabledProjectView : View {
229+ var isOpen : Binding < Bool >
230+ var settings : SuggestionFeatureEnabledProjectListView . Settings
231+ @State var rootPath = " "
232+
233+ var body : some View {
234+ VStack {
235+ Text ( " Enter the root path of the project. Do not use `~` to replace /Users/yourUserName. " )
236+ TextField ( " Root path " , text: $rootPath)
237+ HStack {
238+ Spacer ( )
239+ Button ( " Cancel " ) {
240+ isOpen. wrappedValue = false
241+ }
242+ Button ( " Add " ) {
243+ settings. suggestionFeatureEnabledProjectList. append ( rootPath)
244+ isOpen. wrappedValue = false
245+ }
246+ } . buttonStyle ( . copilot)
247+ }
248+ . padding ( )
249+ . frame ( minWidth: 500 )
250+ }
251+ }
252+
253+ // MARK: - Previews
254+
122255struct SettingsView_Preview : PreviewProvider {
123256 static var previews : some View {
124257 SettingsView ( )
125258 . background ( . purple)
126259 }
127260}
261+
262+ struct SuggestionFeatureEnabledProjectListView_Preview : PreviewProvider {
263+ static var previews : some View {
264+ SuggestionFeatureEnabledProjectListView (
265+ isOpen: . constant( true ) ,
266+ settings: . init( suggestionFeatureEnabledProjectList: . init( wrappedValue: [
267+ " hello/2 " ,
268+ " hello/3 " ,
269+ " hello/4 " ,
270+ ] , " SuggestionFeatureEnabledProjectListView_Preview " ) )
271+ )
272+ . background ( . purple)
273+ }
274+ }
0 commit comments