Skip to content

Commit ba57cb6

Browse files
committed
Update floating widget to the bottom, move to left or right according to the window position
1 parent 7231ebd commit ba57cb6

4 files changed

Lines changed: 60 additions & 34 deletions

File tree

Core/Sources/SuggestionWidget/Styles.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ enum Style {
33
static let panelWidth: Double = 450
44
static let widgetHeight: Double = 30
55
static var widgetWidth: Double { widgetHeight }
6+
static let widgetPadding: Double = 4
67
}
78

Core/Sources/SuggestionWidget/SuggestionPanelView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ struct SuggestionPanelView: View {
4444

4545
var body: some View {
4646
VStack {
47+
Spacer()
48+
.frame(minHeight: 0, maxHeight: .infinity)
49+
.allowsHitTesting(false)
50+
4751
ZStack(alignment: .topLeading) {
4852
VStack(spacing: 0) {
4953
ScrollView {
@@ -74,10 +78,6 @@ struct SuggestionPanelView: View {
7478
}
7579
.allowsHitTesting(viewModel.isPanelDisplayed && !viewModel.suggestion.isEmpty)
7680
.preferredColorScheme(.dark)
77-
78-
Spacer()
79-
.frame(minHeight: 0, maxHeight: .infinity)
80-
.allowsHitTesting(false)
8181
}
8282
.opacity({
8383
guard viewModel.isPanelDisplayed else { return 0 }

Core/Sources/SuggestionWidget/SuggestionWidgetController.swift

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ public final class SuggestionWidgetController {
186186
for await notification in notifications {
187187
guard let self else { return }
188188
try Task.checkCancellation()
189-
self.updateWindowLocation()
189+
self.updateWindowLocation(animated: false)
190190

191191
if notification.name == kAXFocusedUIElementChangedNotification {
192192
guard let fileURL = try? await Environment.fetchCurrentFileURL(),
@@ -211,7 +211,7 @@ public final class SuggestionWidgetController {
211211
///
212212
/// - note: It's possible to get the scroll view's postion by getting position on the focus
213213
/// element.
214-
private func updateWindowLocation() {
214+
private func updateWindowLocation(animated: Bool = false) {
215215
func hide() {
216216
panelWindow.alphaValue = 0
217217
widgetWindow.alphaValue = 0
@@ -246,26 +246,60 @@ public final class SuggestionWidgetController {
246246
let screen = NSScreen.screens.first
247247
let frame = CGRect(origin: position, size: size)
248248
if foundSize, foundPosition, let screen {
249-
let anchorFrame = CGRect(
250-
x: frame.maxX - 4 - Style.widgetWidth,
251-
y: screen.frame.height - frame.minY - Style.widgetHeight - 4,
249+
let proposedAnchorFrameOnTheRightSide = CGRect(
250+
x: frame.maxX - Style.widgetPadding - Style.widgetWidth,
251+
y: max(screen.frame.height - frame.maxY + Style.widgetPadding, 4),
252252
width: Style.widgetWidth,
253253
height: Style.widgetHeight
254254
)
255-
widgetWindow.setFrame(anchorFrame, display: false)
256255

257-
let proposedPanelX = anchorFrame.maxX + 8
256+
let proposedPanelX = proposedAnchorFrameOnTheRightSide.maxX + Style
257+
.widgetPadding * 2
258258
let putPanelToTheRight = screen.frame.maxX > proposedPanelX + Style.panelWidth
259259

260-
let panelFrame = CGRect(
261-
x: putPanelToTheRight ? proposedPanelX : anchorFrame.maxX - Style
262-
.panelWidth,
263-
y: putPanelToTheRight ? anchorFrame.minY - Style.panelHeight + Style
264-
.widgetHeight : anchorFrame.minY - Style.panelHeight - 4,
265-
width: Style.panelWidth,
266-
height: Style.panelHeight
267-
)
268-
panelWindow.setFrame(panelFrame, display: false)
260+
if putPanelToTheRight {
261+
let anchorFrame = proposedAnchorFrameOnTheRightSide
262+
let panelFrame = CGRect(
263+
x: proposedPanelX,
264+
y: anchorFrame.minY,
265+
width: Style.panelWidth,
266+
height: Style.panelHeight
267+
)
268+
widgetWindow.setFrame(anchorFrame, display: false, animate: animated)
269+
panelWindow.setFrame(panelFrame, display: false, animate: animated)
270+
} else {
271+
let proposedAnchorFrameOnTheLeftSide = CGRect(
272+
x: frame.minX + Style.widgetPadding + Style.widgetWidth,
273+
y: proposedAnchorFrameOnTheRightSide.origin.y,
274+
width: Style.widgetWidth,
275+
height: Style.widgetHeight
276+
)
277+
let proposedPanelX = proposedAnchorFrameOnTheLeftSide.minX - Style
278+
.widgetPadding * 2 - Style.panelWidth
279+
let putAnchorToTheLeft = proposedPanelX > screen.frame.minX
280+
281+
if putAnchorToTheLeft {
282+
let anchorFrame = proposedAnchorFrameOnTheLeftSide
283+
let panelFrame = CGRect(
284+
x: proposedPanelX,
285+
y: anchorFrame.minY,
286+
width: Style.panelWidth,
287+
height: Style.panelHeight
288+
)
289+
widgetWindow.setFrame(anchorFrame, display: false, animate: animated)
290+
panelWindow.setFrame(panelFrame, display: false, animate: animated)
291+
} else {
292+
let anchorFrame = proposedAnchorFrameOnTheRightSide
293+
let panelFrame = CGRect(
294+
x: anchorFrame.maxX - Style.panelWidth,
295+
y: anchorFrame.maxY + Style.widgetPadding,
296+
width: Style.panelWidth,
297+
height: Style.panelHeight
298+
)
299+
widgetWindow.setFrame(anchorFrame, display: false, animate: animated)
300+
panelWindow.setFrame(panelFrame, display: false, animate: animated)
301+
}
302+
}
269303

270304
panelWindow.alphaValue = 1
271305
widgetWindow.alphaValue = 1

Core/Sources/SuggestionWidget/WidgetView.swift

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,9 @@ import SwiftUI
22

33
@MainActor
44
final class WidgetViewModel: ObservableObject {
5-
enum Position {
6-
case topLeft
7-
case topRight
8-
case bottomLeft
9-
case bottomRight
10-
}
11-
12-
var position: Position
135
@Published var isProcessing: Bool
146

15-
init(position: Position = .topRight, isProcessing: Bool = false) {
16-
self.position = position
7+
init(isProcessing: Bool = false) {
178
self.isProcessing = isProcessing
189
}
1910
}
@@ -99,25 +90,25 @@ struct WidgetView_Preview: PreviewProvider {
9990
static var previews: some View {
10091
VStack {
10192
WidgetView(
102-
viewModel: .init(position: .topRight, isProcessing: false),
93+
viewModel: .init(isProcessing: false),
10394
panelViewModel: .init(),
10495
isHovering: false
10596
)
10697

10798
WidgetView(
108-
viewModel: .init(position: .topRight, isProcessing: false),
99+
viewModel: .init(isProcessing: false),
109100
panelViewModel: .init(),
110101
isHovering: true
111102
)
112103

113104
WidgetView(
114-
viewModel: .init(position: .topRight, isProcessing: true),
105+
viewModel: .init(isProcessing: true),
115106
panelViewModel: .init(),
116107
isHovering: false
117108
)
118109

119110
WidgetView(
120-
viewModel: .init(position: .topRight, isProcessing: false),
111+
viewModel: .init(isProcessing: false),
121112
panelViewModel: .init(suggestion: ["Hello"]),
122113
isHovering: false
123114
)

0 commit comments

Comments
 (0)