@@ -15,22 +15,6 @@ extension List {
1515struct CustomCommandView : View {
1616 final class Settings : ObservableObject {
1717 @AppStorage ( \. customCommands) var customCommands
18- var illegalNames : [ String ] {
19- let existed = customCommands. map ( \. name)
20- let builtin : [ String ] = [
21- " Get Suggestions " ,
22- " Accept Suggestion " ,
23- " Reject Suggestion " ,
24- " Next Suggestion " ,
25- " Previous Suggestion " ,
26- " Real-time Suggestions " ,
27- " Prefetch Suggestions " ,
28- " Open Chat " ,
29- " Prompt to Code " ,
30- ]
31-
32- return existed + builtin
33- }
3418
3519 init ( customCommands: AppStorage < [ CustomCommand ] > ? = nil ) {
3620 if let list = customCommands {
@@ -67,6 +51,8 @@ struct CustomCommandView: View {
6751 Text ( " Custom Chat " )
6852 case . promptToCode:
6953 Text ( " Prompt to Code " )
54+ case . oneTimeDialog:
55+ Text ( " One-time Dialog " )
7056 }
7157 }
7258 . font ( . caption)
@@ -146,224 +132,6 @@ struct CustomCommandView: View {
146132 }
147133}
148134
149- struct EditCustomCommandView : View {
150- @Environment ( \. toast) var toast
151- @Binding var editingCommand : CustomCommandView . EditingCommand ?
152- var settings : CustomCommandView . Settings
153- let originalName : String
154- @State var commandType : CommandType
155-
156- @State var name : String
157- @State var prompt : String
158- @State var systemPrompt : String
159- @State var usePrompt : Bool
160- @State var continuousMode : Bool
161- @State var editingContentInFullScreen : Binding < String > ?
162- @State var generatingPromptToCodeDescription : Bool
163-
164- enum CommandType : Int , CaseIterable {
165- case chatWithSelection
166- case promptToCode
167- case customChat
168- }
169-
170- init (
171- editingCommand: Binding < CustomCommandView . EditingCommand ? > ,
172- settings: CustomCommandView . Settings
173- ) {
174- _editingCommand = editingCommand
175- self . settings = settings
176- originalName = editingCommand. wrappedValue? . command. name ?? " "
177- name = originalName
178- switch editingCommand. wrappedValue? . command. feature {
179- case let . chatWithSelection( extraSystemPrompt, prompt, useExtraSystemPrompt) :
180- commandType = . chatWithSelection
181- self . prompt = prompt ?? " "
182- systemPrompt = extraSystemPrompt ?? " "
183- usePrompt = useExtraSystemPrompt ?? true
184- continuousMode = false
185- generatingPromptToCodeDescription = true
186- case let . customChat( systemPrompt, prompt) :
187- commandType = . customChat
188- self . systemPrompt = systemPrompt ?? " "
189- self . prompt = prompt ?? " "
190- usePrompt = false
191- continuousMode = false
192- generatingPromptToCodeDescription = true
193- case let . promptToCode( extraSystemPrompt, prompt, continuousMode, generateDescription) :
194- commandType = . promptToCode
195- self . prompt = prompt ?? " "
196- systemPrompt = extraSystemPrompt ?? " "
197- usePrompt = false
198- self . continuousMode = continuousMode ?? false
199- generatingPromptToCodeDescription = generateDescription ?? true
200- case . none:
201- commandType = . chatWithSelection
202- prompt = " "
203- systemPrompt = " "
204- continuousMode = false
205- usePrompt = true
206- generatingPromptToCodeDescription = true
207- }
208- }
209-
210- var body : some View {
211- ScrollView {
212- Form {
213- TextField ( " Name " , text: $name)
214-
215- Picker ( " Command Type " , selection: $commandType) {
216- ForEach ( CommandType . allCases, id: \. rawValue) { commandType in
217- Text ( {
218- switch commandType {
219- case . chatWithSelection:
220- return " Send Message "
221- case . promptToCode:
222- return " Prompt to Code "
223- case . customChat:
224- return " Custom Chat "
225- }
226- } ( ) as String ) . tag ( commandType)
227- }
228- }
229-
230- switch commandType {
231- case . chatWithSelection:
232- systemPromptTextField ( title: " Extra System Prompt " , hasToggle: true )
233- promptTextField
234- case . promptToCode:
235- continuousModeToggle
236- generateDescriptionToggle
237- systemPromptTextField ( title: " Extra System Prompt " , hasToggle: false )
238- promptTextField
239- case . customChat:
240- systemPromptTextField ( hasToggle: false )
241- promptTextField
242- }
243- } . padding ( )
244- } . safeAreaInset ( edge: . bottom) {
245- VStack {
246- Divider ( )
247-
248- VStack {
249- Text (
250- " After renaming or adding a custom command, please restart Xcode to refresh the menu. "
251- )
252- . foregroundStyle ( . secondary)
253-
254- HStack {
255- Spacer ( )
256- Button ( " Close " ) {
257- editingCommand = nil
258- }
259-
260- lazy var newCommand = CustomCommand (
261- commandId: editingCommand? . command. id ?? UUID ( ) . uuidString,
262- name: name,
263- feature: {
264- switch commandType {
265- case . chatWithSelection:
266- return . chatWithSelection(
267- extraSystemPrompt: systemPrompt,
268- prompt: prompt,
269- useExtraSystemPrompt: usePrompt
270- )
271- case . promptToCode:
272- return . promptToCode(
273- extraSystemPrompt: systemPrompt,
274- prompt: prompt,
275- continuousMode: continuousMode,
276- generateDescription: generatingPromptToCodeDescription
277- )
278- case . customChat:
279- return . customChat(
280- systemPrompt: systemPrompt,
281- prompt: prompt
282- )
283- }
284- } ( )
285- )
286-
287- if editingCommand? . isNew ?? true {
288- Button ( " Add " ) {
289- guard !settings. illegalNames. contains ( newCommand. name) else {
290- toast ( Text ( " Command name is illegal. " ) , . error)
291- return
292- }
293- guard !newCommand. name. isEmpty else {
294- toast ( Text ( " Command name cannot be empty. " ) , . error)
295- return
296- }
297- settings. customCommands. append ( newCommand)
298- editingCommand? . isNew = false
299- editingCommand? . command = newCommand
300-
301- toast ( Text ( " The command is created. " ) , . info)
302- }
303- } else {
304- Button ( " Save " ) {
305- guard !settings. illegalNames. contains ( newCommand. name)
306- || newCommand. name == originalName
307- else {
308- toast ( Text ( " Command name is illegal. " ) , . error)
309- return
310- }
311- guard !newCommand. name. isEmpty else {
312- toast ( Text ( " Command name cannot be empty. " ) , . error)
313- return
314- }
315-
316- if let index = settings. customCommands. firstIndex ( where: {
317- $0. id == newCommand. id
318- } ) {
319- settings. customCommands [ index] = newCommand
320- } else {
321- settings. customCommands. append ( newCommand)
322- }
323-
324- toast ( Text ( " The command is updated. " ) , . info)
325- }
326- }
327- }
328- }
329- . padding ( . horizontal)
330- }
331- . padding ( . bottom)
332- . background ( . regularMaterial)
333- }
334- }
335-
336- @ViewBuilder
337- var promptTextField : some View {
338- VStack ( alignment: . leading, spacing: 4 ) {
339- Text ( " Prompt " )
340- EditableText ( text: $prompt)
341- }
342- . padding ( . vertical, 4 )
343- }
344-
345- @ViewBuilder
346- func systemPromptTextField( title: String ? = nil , hasToggle: Bool ) -> some View {
347- VStack ( alignment: . leading, spacing: 4 ) {
348- if hasToggle {
349- Toggle ( title ?? " System Prompt " , isOn: $usePrompt)
350- } else {
351- Text ( title ?? " System Prompt " )
352- }
353- EditableText ( text: $systemPrompt)
354- }
355- . padding ( . vertical, 4 )
356- }
357-
358- var continuousModeToggle : some View {
359- Toggle ( " Continuous Mode " , isOn: $continuousMode)
360- }
361-
362- var generateDescriptionToggle : some View {
363- Toggle ( " Generate Description " , isOn: $generatingPromptToCodeDescription)
364- }
365- }
366-
367135// MARK: - Previews
368136
369137struct CustomCommandView_Preview : PreviewProvider {
@@ -403,25 +171,3 @@ struct CustomCommandView_Preview: PreviewProvider {
403171 }
404172}
405173
406- struct EditCustomCommandView_Preview : PreviewProvider {
407- static var previews : some View {
408- EditCustomCommandView (
409- editingCommand: . constant( CustomCommandView . EditingCommand (
410- isNew: false ,
411- command: . init(
412- commandId: " 4 " ,
413- name: " Explain Code " ,
414- feature: . promptToCode(
415- extraSystemPrompt: nil ,
416- prompt: " Hello " ,
417- continuousMode: false ,
418- generateDescription: true
419- )
420- )
421- ) ) ,
422- settings: . init( customCommands: . init( wrappedValue: [ ] , " CustomCommandView_Preview " ) )
423- )
424- . frame ( width: 800 )
425- }
426- }
427-
0 commit comments