@@ -16,7 +16,13 @@ final class SuggestionPanelViewModel: ObservableObject {
1616 )
1717 }
1818
19- @Published var suggestion : Suggestion
19+ enum Content : Equatable {
20+ case empty
21+ case suggestion( Suggestion )
22+ case error( String )
23+ }
24+
25+ @Published var content : Content
2026 @Published var isPanelDisplayed : Bool
2127 @Published var alignTopToAnchor = false
2228 @Published var colorScheme : ColorScheme
@@ -27,15 +33,15 @@ final class SuggestionPanelViewModel: ObservableObject {
2733 var onNextButtonTapped : ( ( ) -> Void ) ?
2834
2935 public init (
30- suggestion : Suggestion = . empty,
36+ content : Content = . empty,
3137 isPanelDisplayed: Bool = false ,
3238 colorScheme: ColorScheme = . dark,
3339 onAcceptButtonTapped: ( ( ) -> Void ) ? = nil ,
3440 onRejectButtonTapped: ( ( ) -> Void ) ? = nil ,
3541 onPreviousButtonTapped: ( ( ) -> Void ) ? = nil ,
3642 onNextButtonTapped: ( ( ) -> Void ) ? = nil
3743 ) {
38- self . suggestion = suggestion
44+ self . content = content
3945 self . isPanelDisplayed = isPanelDisplayed
4046 self . colorScheme = colorScheme
4147 self . onAcceptButtonTapped = onAcceptButtonTapped
@@ -57,23 +63,13 @@ struct SuggestionPanelView: View {
5763 }
5864
5965 ZStack ( alignment: . topLeading) {
60- VStack ( spacing: 0 ) {
61- ScrollView {
62- CodeBlock ( viewModel: viewModel)
63- . frame ( maxWidth: . infinity)
64- }
65- . background ( Color ( nsColor: {
66- switch viewModel. colorScheme {
67- case . dark:
68- return #colorLiteral( red: 0.1580096483 , green: 0.1730263829 , blue: 0.2026666105 , alpha: 1 )
69- case . light:
70- return . white
71- @unknown default :
72- return . white
73- }
74- } ( ) ) )
75-
76- ToolBar ( viewModel: viewModel)
66+ switch viewModel. content {
67+ case . empty:
68+ EmptyView ( )
69+ case let . suggestion( suggestion) :
70+ CodeBlockSuggestionPanel ( viewModel: viewModel, suggestion: suggestion)
71+ case let . error( description) :
72+ ErrorPanel ( viewModel: viewModel, description: description)
7773 }
7874 }
7975 . frame ( maxWidth: . infinity, maxHeight: Style . panelHeight)
@@ -88,7 +84,7 @@ struct SuggestionPanelView: View {
8884 . stroke ( Color . white. opacity ( 0.2 ) , style: . init( lineWidth: 1 ) )
8985 . padding ( 1 )
9086 )
91- . allowsHitTesting ( viewModel. isPanelDisplayed && ! viewModel. suggestion . code . isEmpty )
87+ . allowsHitTesting ( viewModel. isPanelDisplayed && viewModel. content != . empty )
9288 . preferredColorScheme ( viewModel. colorScheme)
9389
9490 if viewModel. alignTopToAnchor {
@@ -99,81 +95,14 @@ struct SuggestionPanelView: View {
9995 }
10096 . opacity ( {
10197 guard viewModel. isPanelDisplayed else { return 0 }
102- guard ! viewModel. suggestion . code . isEmpty else { return 0 }
98+ guard viewModel. content != . empty else { return 0 }
10399 return 1
104100 } ( ) )
105- . animation ( . easeInOut( duration: 0.2 ) , value: viewModel. suggestion )
101+ . animation ( . easeInOut( duration: 0.2 ) , value: viewModel. content )
106102 . animation ( . easeInOut( duration: 0.2 ) , value: viewModel. isPanelDisplayed)
107103 }
108104}
109105
110- struct CodeBlock : View {
111- @ObservedObject var viewModel : SuggestionPanelViewModel
112-
113- var body : some View {
114- VStack {
115- ForEach ( 0 ..< viewModel. suggestion. code. endIndex, id: \. self) { index in
116- HStack ( alignment: . firstTextBaseline) {
117- Text ( " \( index + viewModel. suggestion. startLineIndex + 1 ) " )
118- . multilineTextAlignment ( . trailing)
119- . foregroundColor ( . secondary)
120- . frame ( minWidth: 40 )
121- Text ( AttributedString ( viewModel. suggestion. code [ index] ) )
122- . foregroundColor ( . white. opacity ( 0.1 ) )
123- . frame ( maxWidth: . infinity, alignment: . leading)
124- . multilineTextAlignment ( . leading)
125- . lineSpacing ( 4 )
126- }
127- }
128- }
129- . foregroundColor ( . white)
130- . font ( . system( size: 12 , design: . monospaced) )
131- . padding ( )
132- }
133- }
134-
135- struct ToolBar : View {
136- @ObservedObject var viewModel : SuggestionPanelViewModel
137-
138- var body : some View {
139- HStack {
140- Button ( action: {
141- viewModel. onPreviousButtonTapped ? ( )
142- } ) {
143- Image ( systemName: " chevron.left " )
144- } . buttonStyle ( . plain)
145-
146- Text (
147- " \( viewModel. suggestion. currentSuggestionIndex + 1 ) / \( viewModel. suggestion. suggestionCount) "
148- )
149- . monospacedDigit ( )
150-
151- Button ( action: {
152- viewModel. onNextButtonTapped ? ( )
153- } ) {
154- Image ( systemName: " chevron.right " )
155- } . buttonStyle ( . plain)
156-
157- Spacer ( )
158-
159- Button ( action: {
160- viewModel. onRejectButtonTapped ? ( )
161- } ) {
162- Text ( " Reject " )
163- } . buttonStyle ( CommandButtonStyle ( color: . gray) )
164-
165- Button ( action: {
166- viewModel. onAcceptButtonTapped ? ( )
167- } ) {
168- Text ( " Accept " )
169- } . buttonStyle ( CommandButtonStyle ( color: . indigo) )
170- }
171- . padding ( )
172- . foregroundColor ( . secondary)
173- . background ( . regularMaterial)
174- }
175- }
176-
177106struct CommandButtonStyle : ButtonStyle {
178107 let color : Color
179108
@@ -194,10 +123,12 @@ struct CommandButtonStyle: ButtonStyle {
194123 }
195124}
196125
126+ // MARK: - Previews
127+
197128struct SuggestionPanelView_Dark_Preview : PreviewProvider {
198129 static var previews : some View {
199130 SuggestionPanelView ( viewModel: . init(
200- suggestion : . init(
131+ content : . suggestion ( . init(
201132 startLineIndex: 8 ,
202133 code: highlighted (
203134 code: """
@@ -213,7 +144,7 @@ struct SuggestionPanelView_Dark_Preview: PreviewProvider {
213144 ) ,
214145 suggestionCount: 2 ,
215146 currentSuggestionIndex: 0
216- ) ,
147+ ) ) ,
217148 isPanelDisplayed: true ,
218149 colorScheme: . dark
219150 ) )
@@ -231,7 +162,7 @@ struct SuggestionPanelView_Dark_Preview: PreviewProvider {
231162struct SuggestionPanelView_Bright_Preview : PreviewProvider {
232163 static var previews : some View {
233164 SuggestionPanelView ( viewModel: . init(
234- suggestion : . init(
165+ content : . suggestion ( . init(
235166 startLineIndex: 8 ,
236167 code: highlighted (
237168 code: """
@@ -247,7 +178,7 @@ struct SuggestionPanelView_Bright_Preview: PreviewProvider {
247178 ) ,
248179 suggestionCount: 2 ,
249180 currentSuggestionIndex: 0
250- ) ,
181+ ) ) ,
251182 isPanelDisplayed: true ,
252183 colorScheme: . light
253184 ) )
@@ -265,7 +196,7 @@ struct SuggestionPanelView_Bright_Preview: PreviewProvider {
265196struct SuggestionPanelView_Dark_Objc_Preview : PreviewProvider {
266197 static var previews : some View {
267198 SuggestionPanelView ( viewModel: . init(
268- suggestion : . init(
199+ content : . suggestion ( . init(
269200 startLineIndex: 8 ,
270201 code: highlighted (
271202 code: """
@@ -278,7 +209,7 @@ struct SuggestionPanelView_Dark_Objc_Preview: PreviewProvider {
278209 ) ,
279210 suggestionCount: 2 ,
280211 currentSuggestionIndex: 0
281- ) ,
212+ ) ) ,
282213 isPanelDisplayed: true ,
283214 colorScheme: . dark
284215 ) )
@@ -296,7 +227,7 @@ struct SuggestionPanelView_Dark_Objc_Preview: PreviewProvider {
296227struct SuggestionPanelView_Bright_Objc_Preview : PreviewProvider {
297228 static var previews : some View {
298229 SuggestionPanelView ( viewModel: . init(
299- suggestion : . init(
230+ content : . suggestion ( . init(
300231 startLineIndex: 8 ,
301232 code: highlighted (
302233 code: """
@@ -309,7 +240,7 @@ struct SuggestionPanelView_Bright_Objc_Preview: PreviewProvider {
309240 ) ,
310241 suggestionCount: 2 ,
311242 currentSuggestionIndex: 0
312- ) ,
243+ ) ) ,
313244 isPanelDisplayed: true ,
314245 colorScheme: . light
315246 ) )
@@ -323,3 +254,13 @@ struct SuggestionPanelView_Bright_Objc_Preview: PreviewProvider {
323254 }
324255 }
325256}
257+
258+ struct SuggestionPanelView_Error_Preview : PreviewProvider {
259+ static var previews : some View {
260+ SuggestionPanelView ( viewModel: . init(
261+ content: . error( " This is an error \n error " ) ,
262+ isPanelDisplayed: true
263+ ) )
264+ . frame ( width: 450 , height: 200 )
265+ }
266+ }
0 commit comments