Skip to content

Commit 8ae7fce

Browse files
Fix floating timer widget: increase size and enable reactive updates
- Increase window size from 150x100 to 180x160 to prevent button clipping - Refactor FloatingTimerView to take AppState directly for reactive updates - Remove AnyView type-erasure to enable proper @observable tracking - Remove unused updateView() method from controller Amp-Thread-ID: https://ampcode.com/threads/T-019c1b0b-acc4-7570-99b5-0308ea608699 Co-authored-by: Amp <amp@ampcode.com>
1 parent 6677e9e commit 8ae7fce

3 files changed

Lines changed: 14 additions & 48 deletions

File tree

MobCrew/MobCrew/Features/FloatingTimer/FloatingTimerController.swift

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftUI
33

44
final class FloatingTimerController {
55
private var window: FloatingTimerWindow?
6-
private var hostingView: NSHostingView<AnyView>?
6+
private var hostingView: NSHostingView<FloatingTimerView>?
77

88
private let appState: AppState
99

@@ -38,17 +38,9 @@ final class FloatingTimerController {
3838
private func createWindow() {
3939
let window = FloatingTimerWindow()
4040

41-
let view = FloatingTimerView(
42-
displayTime: appState.timerState.displayTime,
43-
driverName: appState.roster.driver?.name,
44-
navigatorName: appState.roster.navigator?.name,
45-
isRunning: appState.timerState.isRunning,
46-
onToggle: { [weak self] in
47-
self?.appState.toggleTimer()
48-
}
49-
)
41+
let view = FloatingTimerView(appState: appState)
5042

51-
let hostingView = NSHostingView(rootView: AnyView(view))
43+
let hostingView = NSHostingView(rootView: view)
5244
hostingView.frame = window.contentView?.bounds ?? .zero
5345
hostingView.autoresizingMask = [.width, .height]
5446

@@ -58,22 +50,6 @@ final class FloatingTimerController {
5850
self.hostingView = hostingView
5951
}
6052

61-
func updateView() {
62-
guard let hostingView = hostingView else { return }
63-
64-
let view = FloatingTimerView(
65-
displayTime: appState.timerState.displayTime,
66-
driverName: appState.roster.driver?.name,
67-
navigatorName: appState.roster.navigator?.name,
68-
isRunning: appState.timerState.isRunning,
69-
onToggle: { [weak self] in
70-
self?.appState.toggleTimer()
71-
}
72-
)
73-
74-
hostingView.rootView = AnyView(view)
75-
}
76-
7753
private func positionWindow() {
7854
guard let window = window,
7955
let screen = NSScreen.main else { return }

MobCrew/MobCrew/Features/FloatingTimer/FloatingTimerView.swift

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
import SwiftUI
22

33
struct FloatingTimerView: View {
4-
let displayTime: String
5-
let driverName: String?
6-
let navigatorName: String?
7-
let isRunning: Bool
8-
let onToggle: () -> Void
4+
let appState: AppState
95

106
var body: some View {
117
VStack(spacing: 8) {
12-
Text(displayTime)
8+
Text(appState.timerState.displayTime)
139
.font(.system(size: 36, weight: .bold, design: .monospaced))
1410
.foregroundStyle(.white)
1511

1612
VStack(spacing: 6) {
17-
RoleLabel(role: "Driver", name: driverName, isDriver: true)
18-
RoleLabel(role: "Navigator", name: navigatorName, isDriver: false)
13+
RoleLabel(role: "Driver", name: appState.roster.driver?.name, isDriver: true)
14+
RoleLabel(role: "Navigator", name: appState.roster.navigator?.name, isDriver: false)
1915
}
2016

21-
Button(action: onToggle) {
22-
Image(systemName: isRunning ? "pause.fill" : "play.fill")
17+
Button(action: { appState.toggleTimer() }) {
18+
Image(systemName: appState.timerState.isRunning ? "pause.fill" : "play.fill")
2319
.font(.system(size: 16, weight: .semibold))
2420
.foregroundStyle(.white)
2521
.frame(width: 32, height: 32)
26-
.background(isRunning ? Color.orange : Color.green)
22+
.background(appState.timerState.isRunning ? Color.orange : Color.green)
2723
.clipShape(Circle())
2824
}
2925
.buttonStyle(.plain)
@@ -58,13 +54,7 @@ private struct RoleLabel: View {
5854
}
5955

6056
#Preview {
61-
FloatingTimerView(
62-
displayTime: "05:00",
63-
driverName: "Alice",
64-
navigatorName: "Bob",
65-
isRunning: false,
66-
onToggle: {}
67-
)
68-
.padding()
69-
.background(Color.gray)
57+
FloatingTimerView(appState: AppState())
58+
.padding()
59+
.background(Color.gray)
7060
}

MobCrew/MobCrew/Features/FloatingTimer/FloatingTimerWindow.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import AppKit
22

33
final class FloatingTimerWindow: NSPanel {
44

5-
init(contentRect: NSRect = NSRect(x: 0, y: 0, width: 150, height: 100)) {
5+
init(contentRect: NSRect = NSRect(x: 0, y: 0, width: 180, height: 160)) {
66
super.init(
77
contentRect: contentRect,
88
styleMask: [.borderless, .nonactivatingPanel],

0 commit comments

Comments
 (0)