Skip to content

Commit 22b1033

Browse files
committed
Add UI to setup the enabled project list
1 parent 54a50ca commit 22b1033

1 file changed

Lines changed: 166 additions & 19 deletions

File tree

Copilot for Xcode/SettingsView.swift

Lines changed: 166 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,34 @@ import LaunchAgentManager
22
import Preferences
33
import 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-
235
struct 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+
122255
struct 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

Comments
 (0)