mirror of
https://github.com/carey314/mio-plugin-worker.git
synced 2026-08-10 07:04:32 +00:00
fix: pomodoro paused-in-break fraction + notif status wired to store
Two P0 issues from 2026-05-19 code review: 1. PomodoroView progress ring used pomodoroFocusMin*60 as denominator in paused state. If the user paused mid-break, ring rendered 80% done when the underlying break was actually 40% done. Now the store exposes pomodoroPhaseTotalSec which reads pausedPhase to pick the right denominator. 2. WorkerNotificationCenter set its own isAuthorized but never wrote WorkerStore.notificationsAuthorized — the top-bar notif status dot stayed dim even after the user authorized. Refactored into a single applyAuthorized helper that writes both. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8022abca76
commit
3fb2c5c2a8
@ -31,24 +31,35 @@ final class WorkerNotificationCenter {
|
|||||||
let status = settings.authorizationStatus
|
let status = settings.authorizationStatus
|
||||||
switch status {
|
switch status {
|
||||||
case .authorized, .provisional, .ephemeral:
|
case .authorized, .provisional, .ephemeral:
|
||||||
Task { @MainActor in WorkerNotificationCenter.shared.isAuthorized = true }
|
Task { @MainActor in Self.applyAuthorized(true) }
|
||||||
case .denied:
|
case .denied:
|
||||||
Task { @MainActor in WorkerNotificationCenter.shared.isAuthorized = false }
|
Task { @MainActor in Self.applyAuthorized(false) }
|
||||||
WorkerDebugLog.write("notifications denied — falling back to in-panel dot")
|
WorkerDebugLog.write("notifications denied — falling back to in-panel dot")
|
||||||
case .notDetermined:
|
case .notDetermined:
|
||||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
|
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
|
||||||
if let error = error {
|
if let error = error {
|
||||||
WorkerDebugLog.write("notif auth error: \(error)")
|
WorkerDebugLog.write("notif auth error: \(error)")
|
||||||
}
|
}
|
||||||
Task { @MainActor in WorkerNotificationCenter.shared.isAuthorized = granted }
|
Task { @MainActor in Self.applyAuthorized(granted) }
|
||||||
WorkerDebugLog.write("notif auth granted=\(granted)")
|
WorkerDebugLog.write("notif auth granted=\(granted)")
|
||||||
}
|
}
|
||||||
@unknown default:
|
@unknown default:
|
||||||
Task { @MainActor in WorkerNotificationCenter.shared.isAuthorized = false }
|
Task { @MainActor in Self.applyAuthorized(false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// P0 fix (2026-05-19 review): prior code set
|
||||||
|
/// `WorkerNotificationCenter.shared.isAuthorized` but never
|
||||||
|
/// propagated to `WorkerStore.notificationsAuthorized`. Result: the
|
||||||
|
/// top-bar notif status dot stayed dim even after the user authorized.
|
||||||
|
/// Always write both so observers see consistent state.
|
||||||
|
@MainActor
|
||||||
|
private static func applyAuthorized(_ value: Bool) {
|
||||||
|
WorkerNotificationCenter.shared.isAuthorized = value
|
||||||
|
WorkerStore.shared.notificationsAuthorized = value
|
||||||
|
}
|
||||||
|
|
||||||
/// Fire-and-forget local notification. Returns true if scheduled
|
/// Fire-and-forget local notification. Returns true if scheduled
|
||||||
/// (best effort — auth status may flip between scheduling and firing).
|
/// (best effort — auth status may flip between scheduling and firing).
|
||||||
@discardableResult
|
@discardableResult
|
||||||
|
|||||||
@ -279,6 +279,34 @@ final class WorkerStore: ObservableObject {
|
|||||||
|
|
||||||
// MARK: - Pomodoro
|
// MARK: - Pomodoro
|
||||||
|
|
||||||
|
/// Total duration (seconds) of the active phase. Used as denominator
|
||||||
|
/// for the progress ring fraction in PomodoroView.
|
||||||
|
///
|
||||||
|
/// P0 fix (2026-05-19 review): the ring previously used
|
||||||
|
/// `pomodoroFocusMin * 60` as denominator for the paused state,
|
||||||
|
/// which is wrong when the user paused mid-break (denominator was
|
||||||
|
/// 25min while remaining was a break's 5min worth → ring read 80%
|
||||||
|
/// done when it was actually ~40%). Now `paused` looks at the
|
||||||
|
/// underlying `pausedPhase` so break/long-break paused renders right.
|
||||||
|
var pomodoroPhaseTotalSec: Int {
|
||||||
|
let isLongBreak = pomodoroCycleProgress >= 4
|
||||||
|
switch pomodoroPhase {
|
||||||
|
case .focus:
|
||||||
|
return pomodoroFocusMin * 60
|
||||||
|
case .rest:
|
||||||
|
return (isLongBreak ? pomodoroLongBreakMin : pomodoroBreakMin) * 60
|
||||||
|
case .paused:
|
||||||
|
switch pausedPhase {
|
||||||
|
case .rest:
|
||||||
|
return (isLongBreak ? pomodoroLongBreakMin : pomodoroBreakMin) * 60
|
||||||
|
default:
|
||||||
|
return pomodoroFocusMin * 60
|
||||||
|
}
|
||||||
|
case .idle:
|
||||||
|
return pomodoroFocusMin * 60
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func pomodoroStart() {
|
func pomodoroStart() {
|
||||||
if pomodoroPhase == .paused {
|
if pomodoroPhase == .paused {
|
||||||
pomodoroPhase = pausedPhase
|
pomodoroPhase = pausedPhase
|
||||||
|
|||||||
@ -116,12 +116,10 @@ struct PomodoroView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var progressFraction: CGFloat {
|
private var progressFraction: CGFloat {
|
||||||
let total: Int
|
// P0 fix (2026-05-19 review): delegate to store so paused-in-break
|
||||||
switch store.pomodoroPhase {
|
// gets the right denominator. Inline switch couldn't see the
|
||||||
case .focus: total = store.pomodoroFocusMin * 60
|
// private pausedPhase.
|
||||||
case .rest: total = store.pomodoroBreakMin * 60
|
let total = store.pomodoroPhaseTotalSec
|
||||||
case .paused, .idle: total = store.pomodoroFocusMin * 60
|
|
||||||
}
|
|
||||||
guard total > 0 else { return 0 }
|
guard total > 0 else { return 0 }
|
||||||
let remaining = max(0, store.pomodoroRemaining)
|
let remaining = max(0, store.pomodoroRemaining)
|
||||||
return CGFloat(total - remaining) / CGFloat(total)
|
return CGFloat(total - remaining) / CGFloat(total)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user