@@ -6,6 +6,7 @@ import Preferences
66import SuggestionBasic
77import SwiftUI
88import WebSearchService
9+ import SharedUIComponents
910
1011@Reducer
1112struct WebSearchSettings {
@@ -98,12 +99,18 @@ struct WebSearchView: View {
9899 var body : some View {
99100 WithPerceptionTracking {
100101 ScrollView {
101- Form {
102- Section ( header : Text ( " Search Provider " ) ) {
102+ VStack ( alignment : . leading ) {
103+ Form {
103104 Picker ( " Search Provider " , selection: $settings. searchProvider) {
104105 ForEach ( UserDefaultPreferenceKeys . SearchProvider. allCases, id: \. self) {
105106 provider in
106- Text ( provider. rawValue) . tag ( provider)
107+ switch provider {
108+ case . serpAPI:
109+ Text ( " Serp API " ) . tag ( provider)
110+ case . headlessBrowser:
111+ Text ( " Headless Browser " ) . tag ( provider)
112+ }
113+
107114 }
108115 }
109116 . pickerStyle ( . segmented)
@@ -115,14 +122,21 @@ struct WebSearchView: View {
115122 case . headlessBrowser:
116123 headlessBrowserForm ( )
117124 }
118-
119- Section {
125+ }
126+ . padding ( )
127+ }
128+ . safeAreaInset ( edge: . bottom) {
129+ VStack ( spacing: 0 ) {
130+ Divider ( )
131+ HStack {
120132 Button ( " Test Search " ) {
121133 store. send ( . test)
122134 }
135+ Spacer ( )
123136 }
137+ . padding ( )
124138 }
125- . padding ( )
139+ . background ( . regularMaterial )
126140 }
127141 . sheet ( item: $store. testResult) { testResult in
128142 testResultView ( testResult: testResult)
@@ -135,7 +149,12 @@ struct WebSearchView: View {
135149
136150 @ViewBuilder
137151 func serpAPIForm( ) -> some View {
138- Section ( header: Text ( " SerpAPI " ) ) {
152+ SubSection (
153+ title: Text ( " Serp API Settings " ) ,
154+ description: """
155+ Use Serp API to do web search. Serp API is more reliable and faster than headless browser. But you need to provide an API key for it.
156+ """
157+ ) {
139158 Picker ( " Engine " , selection: $settings. serpAPIEngine) {
140159 ForEach (
141160 UserDefaultPreferenceKeys . SerpAPIEngine. allCases,
@@ -144,7 +163,7 @@ struct WebSearchView: View {
144163 Text ( engine. rawValue) . tag ( engine)
145164 }
146165 }
147-
166+
148167 WithPerceptionTracking {
149168 APIKeyPicker ( store: store. scope (
150169 state: \. apiKeySelection,
@@ -156,7 +175,12 @@ struct WebSearchView: View {
156175
157176 @ViewBuilder
158177 func headlessBrowserForm( ) -> some View {
159- Section ( header: Text ( " Headless Browser " ) ) {
178+ SubSection (
179+ title: Text ( " Headless Browser Settings " ) ,
180+ description: """
181+ The app will open a webview in the background to do web search. This method uses a set of rules to extract information from the web page, if you notice that it stops working, please submit an issue to the developer.
182+ """
183+ ) {
160184 Picker ( " Engine " , selection: $settings. headlessBrowserEngine) {
161185 ForEach (
162186 UserDefaultPreferenceKeys . HeadlessBrowserEngine. allCases,
@@ -172,8 +196,8 @@ struct WebSearchView: View {
172196 func testResultView( testResult: WebSearchSettings . TestResult ) -> some View {
173197 VStack {
174198 Text ( " Test Result " )
199+ . padding ( . top)
175200 . font ( . headline)
176- . padding ( )
177201
178202 if let result = testResult. result {
179203 switch result {
@@ -183,18 +207,20 @@ struct WebSearchView: View {
183207 . foregroundColor ( . green)
184208
185209 Text ( " Found \( webSearchResult. webPages. count) results: " )
186- . padding ( . top)
187210
188211 ScrollView {
189212 ForEach ( webSearchResult. webPages, id: \. urlString) { page in
190- VStack ( alignment: . leading) {
191- Text ( page. title)
192- . font ( . headline)
193- Text ( page. urlString)
194- . font ( . caption)
195- . foregroundColor ( . blue)
196- Text ( page. snippet)
197- . padding ( . top, 2 )
213+ HStack {
214+ VStack ( alignment: . leading) {
215+ Text ( page. title)
216+ . font ( . headline)
217+ Text ( page. urlString)
218+ . font ( . caption)
219+ . foregroundColor ( . blue)
220+ Text ( page. snippet)
221+ . padding ( . top, 2 )
222+ }
223+ Spacer ( minLength: 0 )
198224 }
199225 . padding ( . vertical, 4 )
200226 Divider ( )
@@ -207,21 +233,27 @@ struct WebSearchView: View {
207233 Text ( " Error (Completed in \( testResult. duration, specifier: " %.2f " ) s) " )
208234 . foregroundColor ( . red)
209235 Text ( error. localizedDescription)
210- . padding ( . top)
211236 }
212- . padding ( )
213237 }
214238 } else {
215- VStack {
216- ProgressView ( )
217- }
218- . padding ( )
239+ ProgressView ( ) . padding ( )
219240 }
220241
221- Button ( " Close " ) {
222- store. testResult = nil
242+ Spacer ( )
243+
244+ VStack ( spacing: 0 ) {
245+ Divider ( )
246+
247+ HStack {
248+ Spacer ( )
249+
250+ Button ( " Close " ) {
251+ store. testResult = nil
252+ }
253+ . keyboardShortcut ( . cancelAction)
254+ }
255+ . padding ( )
223256 }
224- . padding ( )
225257 }
226258 . frame ( minWidth: 400 , minHeight: 300 )
227259 }
0 commit comments