Skip to content

Commit cebf7bd

Browse files
committed
Update chat feature settings
1 parent dd07194 commit cebf7bd

3 files changed

Lines changed: 121 additions & 74 deletions

File tree

Core/Sources/HostApp/FeatureSettings/ChatSettingsView.swift

Lines changed: 87 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -285,78 +285,102 @@ struct ChatSettingsView: View {
285285
#if canImport(ProHostApp)
286286

287287
SubSection(
288-
title: WithFeatureEnabled(\.projectScopeInChat, alignment: .trailing) {
289-
Text("Sense Scope (Experimental)")
290-
},
291-
description: "Experimental. Enable the bot to read the relevant code of the editing file in the project, third party packages and the SDK."
288+
title: Text("Sense Scope (Experimental)"),
289+
description: IfFeatureEnabled(\.senseScopeInChat) {
290+
Text("""
291+
Enable the bot to access the relevant code \
292+
of the editing document in the project, third party packages and the SDK.
293+
""")
294+
} else: {
295+
VStack(alignment: .leading) {
296+
Text("""
297+
Enable the bot to read the relevant code \
298+
of the editing document in the SDK, and
299+
""")
300+
301+
WithFeatureEnabled(\.senseScopeInChat, alignment: .inlineLeading) {
302+
Text("the project and third party packages.")
303+
}
304+
}
305+
}
292306
) {
293-
WithFeatureEnabled(\.senseScopeInChat, alignment: .hidden) {
294-
Form {
295-
Toggle(isOn: $settings.enableSenseScopeByDefaultInChatContext) {
296-
Text("Enable by default")
307+
Form {
308+
Toggle(isOn: $settings.enableSenseScopeByDefaultInChatContext) {
309+
Text("Enable by default")
310+
}
311+
312+
Picker(
313+
"Preferred Chat Model",
314+
selection: $settings.preferredChatModelIdForSenseScope
315+
) {
316+
Text("None").tag("")
317+
318+
if !settings.chatModels
319+
.contains(where: {
320+
$0.id == settings.preferredChatModelIdForSenseScope
321+
}),
322+
!settings.preferredChatModelIdForSenseScope.isEmpty
323+
{
324+
Text(
325+
(settings.chatModels.first?.name).map { "\($0) (Default)" }
326+
?? "No Model Found"
327+
)
328+
.tag(settings.preferredChatModelIdForSenseScope)
297329
}
298330

299-
Picker(
300-
"Preferred Chat Model",
301-
selection: $settings.preferredChatModelIdForSenseScope
302-
) {
303-
Text("None").tag("")
304-
305-
if !settings.chatModels
306-
.contains(where: {
307-
$0.id == settings.preferredChatModelIdForSenseScope
308-
}),
309-
!settings.preferredChatModelIdForSenseScope.isEmpty
310-
{
311-
Text(
312-
(settings.chatModels.first?.name).map { "\($0) (Default)" }
313-
?? "No Model Found"
314-
)
315-
.tag(settings.preferredChatModelIdForSenseScope)
316-
}
317-
318-
ForEach(settings.chatModels, id: \.id) { chatModel in
319-
Text(chatModel.name).tag(chatModel.id)
320-
}
331+
ForEach(settings.chatModels, id: \.id) { chatModel in
332+
Text(chatModel.name).tag(chatModel.id)
321333
}
322334
}
323335
}
324336
}
325337

326338
SubSection(
327-
title: WithFeatureEnabled(\.projectScopeInChat, alignment: .trailing) {
328-
Text("Project Scope (Experimental)")
329-
},
330-
description: "Experimental. Enable the bot to search code symbols in the project, third party packages and the SDK."
339+
title: Text("Project Scope (Experimental)"),
340+
description: IfFeatureEnabled(\.projectScopeInChat) {
341+
Text("""
342+
Enable the bot to search code and texts \
343+
in the project, third party packages and the SDK.
344+
""")
345+
} else: {
346+
VStack(alignment: .leading) {
347+
Text("""
348+
Enable the bot to search code and texts \
349+
in the neighboring files of the editing document, and
350+
""")
351+
352+
WithFeatureEnabled(\.senseScopeInChat, alignment: .inlineLeading) {
353+
Text("the project, third party packages and the SDK.")
354+
}
355+
}
356+
}
331357
) {
332-
WithFeatureEnabled(\.projectScopeInChat, alignment: .hidden) {
333-
Form {
334-
Toggle(isOn: $settings.enableProjectScopeByDefaultInChatContext) {
335-
Text("Enable by default")
358+
Form {
359+
Toggle(isOn: $settings.enableProjectScopeByDefaultInChatContext) {
360+
Text("Enable by default")
361+
}
362+
363+
Picker(
364+
"Preferred Chat Model",
365+
selection: $settings.preferredChatModelIdForProjectScope
366+
) {
367+
Text("None").tag("")
368+
369+
if !settings.chatModels
370+
.contains(where: {
371+
$0.id == settings.preferredChatModelIdForProjectScope
372+
}),
373+
!settings.preferredChatModelIdForProjectScope.isEmpty
374+
{
375+
Text(
376+
(settings.chatModels.first?.name).map { "\($0) (Default)" }
377+
?? "No Model Found"
378+
)
379+
.tag(settings.preferredChatModelIdForProjectScope)
336380
}
337381

338-
Picker(
339-
"Preferred Chat Model",
340-
selection: $settings.preferredChatModelIdForProjectScope
341-
) {
342-
Text("None").tag("")
343-
344-
if !settings.chatModels
345-
.contains(where: {
346-
$0.id == settings.preferredChatModelIdForProjectScope
347-
}),
348-
!settings.preferredChatModelIdForProjectScope.isEmpty
349-
{
350-
Text(
351-
(settings.chatModels.first?.name).map { "\($0) (Default)" }
352-
?? "No Model Found"
353-
)
354-
.tag(settings.preferredChatModelIdForProjectScope)
355-
}
356-
357-
ForEach(settings.chatModels, id: \.id) { chatModel in
358-
Text(chatModel.name).tag(chatModel.id)
359-
}
382+
ForEach(settings.chatModels, id: \.id) { chatModel in
383+
Text(chatModel.name).tag(chatModel.id)
360384
}
361385
}
362386
}
@@ -404,14 +428,15 @@ struct ChatSettingsView: View {
404428
}
405429

406430
// MARK: - Preview
431+
407432
//
408-
//#Preview {
433+
// #Preview {
409434
// ScrollView {
410435
// ChatSettingsView()
411436
// .padding()
412437
// }
413438
// .frame(height: 800)
414439
// .environment(\.overrideFeatureFlag, \.never)
415-
//}
440+
// }
416441
//
417442

Core/Sources/HostApp/SharedComponents/SubSection.swift

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,31 @@
11
import SwiftUI
22

3-
struct SubSection<Title: View, Content: View>: View {
3+
struct SubSection<Title: View, Description: View, Content: View>: View {
44
let title: Title
5-
let description: String
5+
let description: Description
66
@ViewBuilder let content: () -> Content
77

8-
init(title: Title, description: String = "", @ViewBuilder content: @escaping () -> Content) {
8+
init(title: Title, description: Description, @ViewBuilder content: @escaping () -> Content) {
99
self.title = title
1010
self.description = description
1111
self.content = content
1212
}
1313

1414
var body: some View {
1515
VStack(alignment: .leading) {
16-
if !(title is EmptyView && description.isEmpty) {
16+
if !(title is EmptyView && description is EmptyView) {
1717
VStack(alignment: .leading, spacing: 8) {
1818
title
1919
.font(.system(size: 14).weight(.semibold))
2020

21-
if !description.isEmpty {
22-
Text(description)
23-
.multilineTextAlignment(.leading)
24-
.foregroundStyle(.secondary)
25-
}
21+
description
22+
.multilineTextAlignment(.leading)
23+
.foregroundStyle(.secondary)
2624
}
2725
.frame(maxWidth: .infinity, alignment: .leading)
2826
}
2927

30-
if !(title is EmptyView && description.isEmpty) {
28+
if !(title is EmptyView && description is EmptyView) {
3129
Divider().padding(.bottom, 4)
3230
}
3331

@@ -45,8 +43,32 @@ struct SubSection<Title: View, Content: View>: View {
4543
}
4644
}
4745

46+
extension SubSection where Description == Text {
47+
init(title: Title, description: String, @ViewBuilder content: @escaping () -> Content) {
48+
self.init(title: title, description: Text(description), content: content)
49+
}
50+
}
51+
52+
extension SubSection where Description == EmptyView {
53+
init(title: Title, @ViewBuilder content: @escaping () -> Content) {
54+
self.init(title: title, description: EmptyView(), content: content)
55+
}
56+
}
57+
4858
extension SubSection where Title == EmptyView {
49-
init(description: String = "", @ViewBuilder content: @escaping () -> Content) {
59+
init(description: Description, @ViewBuilder content: @escaping () -> Content) {
60+
self.init(title: EmptyView(), description: description, content: content)
61+
}
62+
}
63+
64+
extension SubSection where Title == EmptyView, Description == EmptyView {
65+
init(@ViewBuilder content: @escaping () -> Content) {
66+
self.init(title: EmptyView(), description: EmptyView(), content: content)
67+
}
68+
}
69+
70+
extension SubSection where Title == EmptyView, Description == Text {
71+
init(description: String, @ViewBuilder content: @escaping () -> Content) {
5072
self.init(title: EmptyView(), description: description, content: content)
5173
}
5274
}

Pro

Submodule Pro updated from e89ed3f to 85be255

0 commit comments

Comments
 (0)