Skip to content

Commit 3bd4da8

Browse files
committed
Update
1 parent 1c679a9 commit 3bd4da8

3 files changed

Lines changed: 100 additions & 69 deletions

File tree

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
enum Style {
2+
static let panelHeight: Double = 300
3+
static let panelWidth: Double = 450
4+
static let widgetHeight: Double = 30
5+
static var widgetWidth: Double { widgetHeight }
6+
}
7+

Core/Sources/SuggestionWidget/SuggestionPanelView.swift

Lines changed: 79 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -30,74 +30,21 @@ struct SuggestionPanelView: View {
3030
@State var codeHeight: Double = 0
3131

3232
var body: some View {
33-
// weird, if the if statement is at the top level, the view may not update sometimes.
3433
VStack {
3534
ZStack(alignment: .topLeading) {
3635
VStack(spacing: 0) {
3736
ScrollView {
38-
LazyVGrid(columns: [
39-
GridItem(.fixed(30), alignment: .top),
40-
GridItem(.flexible()),
41-
], spacing: 4) {
42-
ForEach(0..<viewModel.suggestion.count, id: \.self) { index in
43-
Text("\(index + viewModel.startLineIndex + 1)")
44-
.foregroundColor(Color.white.opacity(0.6))
45-
Text(viewModel.suggestion[index])
46-
.frame(maxWidth: .infinity, alignment: .leading)
47-
.multilineTextAlignment(.leading)
48-
.lineSpacing(4)
49-
}
50-
}
51-
.foregroundColor(.white)
52-
.font(.system(size: 12, design: .monospaced))
53-
.padding()
54-
.background(
55-
GeometryReader { proxy -> Color in
56-
Task {
57-
codeHeight = proxy.size.height
58-
}
59-
return Color.clear
60-
}
61-
)
62-
63-
Spacer()
37+
CodeBlock(viewModel: viewModel)
6438
}
65-
.frame(maxHeight: max(codeHeight, 300))
66-
.fixedSize(horizontal: false, vertical: true)
67-
68-
HStack {
69-
Text("\(viewModel.currentSuggestionIndex)/\(viewModel.suggestionCount)")
70-
71-
Spacer()
72-
73-
Button(action: {
74-
Task {
75-
try await Environment.triggerAction("Accept Suggestion")
76-
}
77-
}) {
78-
Text("Accept")
79-
}.buttonStyle(CommandButtonStyle(color: .green))
80-
Button(action: {
81-
Task {
82-
try await Environment.triggerAction("Reject Suggestion")
83-
}
84-
}) {
85-
Text("Reject")
86-
}.buttonStyle(CommandButtonStyle(color: .red))
87-
}
88-
.padding()
89-
.foregroundColor(.white)
90-
.background(Color.white.opacity(0.1))
39+
40+
ToolBar(viewModel: viewModel)
9141
}
9242
}
43+
.frame(maxWidth: .infinity, maxHeight: Style.panelHeight)
44+
.fixedSize(horizontal: false, vertical: true)
9345
.background(Color(red: 31 / 255, green: 31 / 255, blue: 36 / 255))
9446
.clipShape(RoundedRectangle(cornerRadius: 8, style: .continuous))
95-
.opacity({
96-
guard viewModel.isPanelDisplayed else { return 0 }
97-
guard !viewModel.suggestion.isEmpty else { return 0 }
98-
return 1
99-
}())
100-
.frame(maxWidth: .infinity)
47+
10148
.onHover { yes in
10249
withAnimation(.easeInOut(duration: 0.2)) {
10350
isHovering = yes
@@ -109,6 +56,79 @@ struct SuggestionPanelView: View {
10956
.frame(minHeight: 0, maxHeight: .infinity)
11057
.allowsHitTesting(false)
11158
}
59+
.overlay(
60+
RoundedRectangle(cornerRadius: 8, style: .continuous)
61+
.stroke(Color.black.opacity(0.3), style: .init(lineWidth: 1))
62+
)
63+
.opacity({
64+
guard viewModel.isPanelDisplayed else { return 0 }
65+
guard !viewModel.suggestion.isEmpty else { return 0 }
66+
return 1
67+
}())
68+
}
69+
}
70+
71+
struct CodeBlock: View {
72+
struct SizePreferenceKey: PreferenceKey {
73+
public static var defaultValue: CGSize = .zero
74+
public static func reduce(value: inout CGSize, nextValue: () -> CGSize) {
75+
value = value.width + value.height > nextValue().width + nextValue()
76+
.height ? value : nextValue()
77+
}
78+
}
79+
80+
@ObservedObject var viewModel: SuggestionPanelViewModel
81+
82+
var body: some View {
83+
LazyVGrid(columns: [
84+
GridItem(.fixed(30), alignment: .top),
85+
GridItem(.flexible()),
86+
], spacing: 4) {
87+
ForEach(0..<viewModel.suggestion.count, id: \.self) { index in
88+
Text("\(index + viewModel.startLineIndex + 1)")
89+
.foregroundColor(Color.white.opacity(0.6))
90+
Text(viewModel.suggestion[index])
91+
.frame(maxWidth: .infinity, alignment: .leading)
92+
.multilineTextAlignment(.leading)
93+
.lineSpacing(4)
94+
}
95+
}
96+
.foregroundColor(.white)
97+
.font(.system(size: 12, design: .monospaced))
98+
.padding()
99+
.background(GeometryReader(content: { proxy in
100+
Color.clear.preference(key: SizePreferenceKey.self, value: proxy.size)
101+
}))
102+
}
103+
}
104+
105+
struct ToolBar: View {
106+
@ObservedObject var viewModel: SuggestionPanelViewModel
107+
108+
var body: some View {
109+
HStack {
110+
Text("\(viewModel.currentSuggestionIndex)/\(viewModel.suggestionCount)")
111+
112+
Spacer()
113+
114+
Button(action: {
115+
Task {
116+
try await Environment.triggerAction("Accept Suggestion")
117+
}
118+
}) {
119+
Text("Accept")
120+
}.buttonStyle(CommandButtonStyle(color: .green))
121+
Button(action: {
122+
Task {
123+
try await Environment.triggerAction("Reject Suggestion")
124+
}
125+
}) {
126+
Text("Reject")
127+
}.buttonStyle(CommandButtonStyle(color: .red))
128+
}
129+
.padding()
130+
.foregroundColor(.white)
131+
.background(Color.white.opacity(0.1))
112132
}
113133
}
114134

Core/Sources/SuggestionWidget/SuggestionWidgetController.swift

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public final class SuggestionWidgetController {
1717
it.isOpaque = false
1818
it.backgroundColor = .clear
1919
it.level = .statusBar
20+
it.hasShadow = true
2021
it.contentView = NSHostingView(
2122
rootView: WidgetView(
2223
viewModel: widgetViewModel,
@@ -38,6 +39,7 @@ public final class SuggestionWidgetController {
3839
it.isOpaque = false
3940
it.backgroundColor = .clear
4041
it.level = .statusBar
42+
it.hasShadow = true
4143
it.contentView = NSHostingView(
4244
rootView: SuggestionPanelView(viewModel: suggestionPanelViewModel)
4345
)
@@ -169,21 +171,23 @@ public final class SuggestionWidgetController {
169171
let frame = CGRect(origin: position, size: size)
170172
if foundSize, foundPosition, let screen {
171173
let anchorFrame = CGRect(
172-
x: frame.maxX - 4 - 30,
173-
y: screen.frame.height - frame.minY - 30 - 4,
174-
width: 30,
175-
height: 30
174+
x: frame.maxX - 4 - Style.widgetWidth,
175+
y: screen.frame.height - frame.minY - Style.widgetHeight - 4,
176+
width: Style.widgetWidth,
177+
height: Style.widgetHeight
176178
)
177179
widgetWindow.setFrame(anchorFrame, display: false)
178180

179181
let proposedPanelX = anchorFrame.maxX + 8
180-
let putPanelToTheRight = screen.frame.maxX > proposedPanelX + 450
181-
182+
let putPanelToTheRight = screen.frame.maxX > proposedPanelX + Style.panelWidth
183+
182184
let panelFrame = CGRect(
183-
x: putPanelToTheRight ? proposedPanelX : anchorFrame.maxX - 450,
184-
y: putPanelToTheRight ? anchorFrame.minY - 300 + 30 : anchorFrame.minY - 300 - 4,
185-
width: 450,
186-
height: 300
185+
x: putPanelToTheRight ? proposedPanelX : anchorFrame.maxX - Style
186+
.panelWidth,
187+
y: putPanelToTheRight ? anchorFrame.minY - Style.panelHeight + Style
188+
.widgetHeight : anchorFrame.minY - Style.panelHeight - 4,
189+
width: Style.panelWidth,
190+
height: Style.panelHeight
187191
)
188192
panelWindow.setFrame(panelFrame, display: false)
189193

0 commit comments

Comments
 (0)