1+ import Combine
2+ import Perception
13import SharedUIComponents
4+ import SuggestionModel
25import SwiftUI
6+ import XcodeInspector
37
48struct CodeBlockSuggestionPanel : View {
5- @ObservedObject var suggestion : CodeSuggestionProvider
9+ let suggestion : CodeSuggestionProvider
10+ @Environment ( CursorPositionTracker . self) var cursorPositionTracker
611 @Environment ( \. colorScheme) var colorScheme
712 @AppStorage ( \. suggestionCodeFont) var codeFont
813 @AppStorage ( \. suggestionDisplayCompactMode) var suggestionDisplayCompactMode
@@ -15,141 +20,154 @@ struct CodeBlockSuggestionPanel: View {
1520 @AppStorage ( \. codeBackgroundColorDark) var codeBackgroundColorDark
1621
1722 struct ToolBar : View {
18- @ ObservedObject var suggestion : CodeSuggestionProvider
23+ let suggestion : CodeSuggestionProvider
1924
2025 var body : some View {
21- HStack {
22- Button ( action: {
23- suggestion. selectPreviousSuggestion ( )
24- } ) {
25- Image ( systemName: " chevron.left " )
26- } . buttonStyle ( . plain)
27-
28- Text (
29- " \( suggestion. currentSuggestionIndex + 1 ) / \( suggestion. suggestionCount) "
30- )
31- . monospacedDigit ( )
32-
33- Button ( action: {
34- suggestion. selectNextSuggestion ( )
35- } ) {
36- Image ( systemName: " chevron.right " )
37- } . buttonStyle ( . plain)
38-
39- Spacer ( )
40-
41- Button ( action: {
42- suggestion. dismissSuggestion ( )
43- } ) {
44- Text ( " Dismiss " ) . foregroundStyle ( . tertiary) . padding ( . trailing, 4 )
45- } . buttonStyle ( . plain)
46-
47- Button ( action: {
48- suggestion. rejectSuggestion ( )
49- } ) {
50- Text ( " Reject " )
51- } . buttonStyle ( CommandButtonStyle ( color: . gray) )
52-
53- Button ( action: {
54- suggestion. acceptSuggestion ( )
55- } ) {
56- Text ( " Accept " )
57- } . buttonStyle ( CommandButtonStyle ( color: . accentColor) )
26+ WithPerceptionTracking {
27+ HStack {
28+ Button ( action: {
29+ suggestion. selectPreviousSuggestion ( )
30+ } ) {
31+ Image ( systemName: " chevron.left " )
32+ } . buttonStyle ( . plain)
33+
34+ Text (
35+ " \( suggestion. currentSuggestionIndex + 1 ) / \( suggestion. suggestionCount) "
36+ )
37+ . monospacedDigit ( )
38+
39+ Button ( action: {
40+ suggestion. selectNextSuggestion ( )
41+ } ) {
42+ Image ( systemName: " chevron.right " )
43+ } . buttonStyle ( . plain)
44+
45+ Spacer ( )
46+
47+ Button ( action: {
48+ suggestion. dismissSuggestion ( )
49+ } ) {
50+ Text ( " Dismiss " ) . foregroundStyle ( . tertiary) . padding ( . trailing, 4 )
51+ } . buttonStyle ( . plain)
52+
53+ Button ( action: {
54+ suggestion. rejectSuggestion ( )
55+ } ) {
56+ Text ( " Reject " )
57+ } . buttonStyle ( CommandButtonStyle ( color: . gray) )
58+
59+ Button ( action: {
60+ suggestion. acceptSuggestion ( )
61+ } ) {
62+ Text ( " Accept " )
63+ } . buttonStyle ( CommandButtonStyle ( color: . accentColor) )
64+ }
65+ . padding ( )
66+ . foregroundColor ( . secondary)
67+ . background ( . regularMaterial)
5868 }
59- . padding ( )
60- . foregroundColor ( . secondary)
61- . background ( . regularMaterial)
6269 }
6370 }
6471
6572 struct CompactToolBar : View {
66- @ ObservedObject var suggestion : CodeSuggestionProvider
73+ let suggestion : CodeSuggestionProvider
6774
6875 var body : some View {
69- HStack {
70- Button ( action: {
71- suggestion. selectPreviousSuggestion ( )
72- } ) {
73- Image ( systemName: " chevron.left " )
74- } . buttonStyle ( . plain)
75-
76- Text (
77- " \( suggestion. currentSuggestionIndex + 1 ) / \( suggestion. suggestionCount) "
78- )
79- . monospacedDigit ( )
80-
81- Button ( action: {
82- suggestion. selectNextSuggestion ( )
83- } ) {
84- Image ( systemName: " chevron.right " )
85- } . buttonStyle ( . plain)
86-
87- Spacer ( )
88-
89- Button ( action: {
90- suggestion. dismissSuggestion ( )
91- } ) {
92- Image ( systemName: " xmark " )
93- } . buttonStyle ( . plain)
76+ WithPerceptionTracking {
77+ HStack {
78+ Button ( action: {
79+ suggestion. selectPreviousSuggestion ( )
80+ } ) {
81+ Image ( systemName: " chevron.left " )
82+ } . buttonStyle ( . plain)
83+
84+ Text (
85+ " \( suggestion. currentSuggestionIndex + 1 ) / \( suggestion. suggestionCount) "
86+ )
87+ . monospacedDigit ( )
88+
89+ Button ( action: {
90+ suggestion. selectNextSuggestion ( )
91+ } ) {
92+ Image ( systemName: " chevron.right " )
93+ } . buttonStyle ( . plain)
94+
95+ Spacer ( )
96+
97+ Button ( action: {
98+ suggestion. dismissSuggestion ( )
99+ } ) {
100+ Image ( systemName: " xmark " )
101+ } . buttonStyle ( . plain)
102+ }
103+ . padding ( 4 )
104+ . font ( . caption)
105+ . foregroundColor ( . secondary)
106+ . background ( . regularMaterial)
94107 }
95- . padding ( 4 )
96- . font ( . caption)
97- . foregroundColor ( . secondary)
98- . background ( . regularMaterial)
99108 }
100109 }
101110
102111 var body : some View {
103- VStack ( spacing: 0 ) {
104- CustomScrollView {
105- CodeBlock (
106- code: suggestion. code,
107- language: suggestion. language,
108- startLineIndex: suggestion. startLineIndex,
109- scenario: " suggestion " ,
110- colorScheme: colorScheme,
111- font: codeFont. value. nsFont,
112- droppingLeadingSpaces: hideCommonPrecedingSpaces,
113- proposedForegroundColor: {
114- if syncHighlightTheme {
115- if colorScheme == . light,
116- let color = codeForegroundColorLight. value? . swiftUIColor
117- {
118- return color
119- } else if let color = codeForegroundColorDark. value? . swiftUIColor {
120- return color
112+ WithPerceptionTracking {
113+ VStack ( spacing: 0 ) {
114+ CustomScrollView {
115+ WithPerceptionTracking {
116+ AsyncCodeBlock (
117+ code: suggestion. code,
118+ language: suggestion. language,
119+ startLineIndex: suggestion. startLineIndex,
120+ scenario: " suggestion " ,
121+ font: codeFont. value. nsFont,
122+ droppingLeadingSpaces: hideCommonPrecedingSpaces,
123+ proposedForegroundColor: {
124+ if syncHighlightTheme {
125+ if colorScheme == . light,
126+ let color = codeForegroundColorLight. value? . swiftUIColor
127+ {
128+ return color
129+ } else if let color = codeForegroundColorDark. value?
130+ . swiftUIColor
131+ {
132+ return color
133+ }
134+ }
135+ return nil
136+ } ( ) ,
137+ dimmedCharacterCount: suggestion. startLineIndex
138+ == cursorPositionTracker. cursorPosition. line
139+ ? cursorPositionTracker. cursorPosition. character
140+ : 0
141+ )
142+ . frame ( maxWidth: . infinity)
143+ . background ( { ( ) -> Color in
144+ if syncHighlightTheme {
145+ if colorScheme == . light,
146+ let color = codeBackgroundColorLight. value? . swiftUIColor
147+ {
148+ return color
149+ } else if let color = codeBackgroundColorDark. value? . swiftUIColor {
150+ return color
151+ }
121152 }
122- }
123- return nil
124- } ( )
125- )
126- . frame ( maxWidth: . infinity)
127- . background ( { ( ) -> Color in
128- if syncHighlightTheme {
129- if colorScheme == . light,
130- let color = codeBackgroundColorLight. value? . swiftUIColor
131- {
132- return color
133- } else if let color = codeBackgroundColorDark. value? . swiftUIColor {
134- return color
135- }
153+ return Color . contentBackground
154+ } ( ) )
136155 }
137- return Color . contentBackground
138- } ( ) )
139- }
156+ }
140157
141- if suggestionDisplayCompactMode {
142- CompactToolBar ( suggestion: suggestion)
143- } else {
144- ToolBar ( suggestion: suggestion)
158+ if suggestionDisplayCompactMode {
159+ CompactToolBar ( suggestion: suggestion)
160+ } else {
161+ ToolBar ( suggestion: suggestion)
162+ }
145163 }
164+ . xcodeStyleFrame ( cornerRadius: {
165+ switch suggestionPresentationMode {
166+ case . nearbyTextCursor: 6
167+ case . floatingWidget: nil
168+ }
169+ } ( ) )
146170 }
147- . xcodeStyleFrame ( cornerRadius: {
148- switch suggestionPresentationMode {
149- case . nearbyTextCursor: 6
150- case . floatingWidget: nil
151- }
152- } ( ) )
153171 }
154172}
155173
0 commit comments