Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const state = vi.hoisted(() => ({
saveResetTimerDisplayModeMock: vi.fn(),
loadMenubarIconStyleMock: vi.fn(),
saveMenubarIconStyleMock: vi.fn(),
loadPreferMenubarWeeklyLimitMock: vi.fn(),
savePreferMenubarWeeklyLimitMock: vi.fn(),
migrateLegacyTraySettingsMock: vi.fn(),
loadGlobalShortcutMock: vi.fn(),
saveGlobalShortcutMock: vi.fn(),
Expand Down Expand Up @@ -229,6 +231,8 @@ vi.mock("@/lib/settings", async () => {
saveResetTimerDisplayMode: state.saveResetTimerDisplayModeMock,
loadMenubarIconStyle: state.loadMenubarIconStyleMock,
saveMenubarIconStyle: state.saveMenubarIconStyleMock,
loadPreferMenubarWeeklyLimit: state.loadPreferMenubarWeeklyLimitMock,
savePreferMenubarWeeklyLimit: state.savePreferMenubarWeeklyLimitMock,
migrateLegacyTraySettings: state.migrateLegacyTraySettingsMock,
loadGlobalShortcut: state.loadGlobalShortcutMock,
saveGlobalShortcut: state.saveGlobalShortcutMock,
Expand Down Expand Up @@ -267,6 +271,8 @@ describe("App", () => {
state.saveResetTimerDisplayModeMock.mockReset()
state.loadMenubarIconStyleMock.mockReset()
state.saveMenubarIconStyleMock.mockReset()
state.loadPreferMenubarWeeklyLimitMock.mockReset()
state.savePreferMenubarWeeklyLimitMock.mockReset()
state.migrateLegacyTraySettingsMock.mockReset()
state.loadGlobalShortcutMock.mockReset()
state.saveGlobalShortcutMock.mockReset()
Expand Down Expand Up @@ -305,6 +311,8 @@ describe("App", () => {
state.saveResetTimerDisplayModeMock.mockResolvedValue(undefined)
state.loadMenubarIconStyleMock.mockResolvedValue("provider")
state.saveMenubarIconStyleMock.mockResolvedValue(undefined)
state.loadPreferMenubarWeeklyLimitMock.mockResolvedValue(false)
state.savePreferMenubarWeeklyLimitMock.mockResolvedValue(undefined)
state.migrateLegacyTraySettingsMock.mockResolvedValue(undefined)
state.loadGlobalShortcutMock.mockResolvedValue(null)
state.saveGlobalShortcutMock.mockResolvedValue(undefined)
Expand Down
9 changes: 9 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ function App() {
setDisplayMode,
menubarIconStyle,
setMenubarIconStyle,
preferMenubarWeeklyLimit,
setPreferMenubarWeeklyLimit,
resetTimerDisplayMode,
setResetTimerDisplayMode,
setGlobalShortcut,
Expand All @@ -67,6 +69,8 @@ function App() {
setDisplayMode: state.setDisplayMode,
menubarIconStyle: state.menubarIconStyle,
setMenubarIconStyle: state.setMenubarIconStyle,
preferMenubarWeeklyLimit: state.preferMenubarWeeklyLimit,
setPreferMenubarWeeklyLimit: state.setPreferMenubarWeeklyLimit,
resetTimerDisplayMode: state.resetTimerDisplayMode,
setResetTimerDisplayMode: state.setResetTimerDisplayMode,
setGlobalShortcut: state.setGlobalShortcut,
Expand Down Expand Up @@ -100,6 +104,7 @@ function App() {
pluginStates,
displayMode,
menubarIconStyle,
preferMenubarWeeklyLimit,
activeView,
})

Expand All @@ -116,6 +121,7 @@ function App() {
setThemeMode,
setDisplayMode,
setMenubarIconStyle,
setPreferMenubarWeeklyLimit,
setResetTimerDisplayMode,
setGlobalShortcut,
setStartOnLogin,
Expand All @@ -132,12 +138,14 @@ function App() {
handleResetTimerDisplayModeChange,
handleResetTimerDisplayModeToggle,
handleMenubarIconStyleChange,
handlePreferMenubarWeeklyLimitChange,
} = useSettingsDisplayActions({
setThemeMode,
setDisplayMode,
resetTimerDisplayMode,
setResetTimerDisplayMode,
setMenubarIconStyle,
setPreferMenubarWeeklyLimit,
scheduleTrayIconUpdate,
})

Expand Down Expand Up @@ -245,6 +253,7 @@ function App() {
onResetTimerDisplayModeChange: handleResetTimerDisplayModeChange,
onResetTimerDisplayModeToggle: handleResetTimerDisplayModeToggle,
onMenubarIconStyleChange: handleMenubarIconStyleChange,
onPreferMenubarWeeklyLimitChange: handlePreferMenubarWeeklyLimitChange,
traySettingsPreview,
onGlobalShortcutChange: handleGlobalShortcutChange,
onStartOnLoginChange: handleStartOnLoginChange,
Expand Down
7 changes: 7 additions & 0 deletions src/components/app/app-content.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ function createProps(): AppContentProps {
onDisplayModeChange: vi.fn(),
onResetTimerDisplayModeChange: vi.fn(),
onResetTimerDisplayModeToggle: vi.fn(),
onMenubarIconStyleChange: vi.fn(),
onPreferMenubarWeeklyLimitChange: vi.fn(),
traySettingsPreview: {
bars: [],
providerBars: [],
providerPercentText: "--%",
},
onGlobalShortcutChange: vi.fn(),
onStartOnLoginChange: vi.fn(),
}
Expand Down
6 changes: 6 additions & 0 deletions src/components/app/app-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export type AppContentActionProps = {
onResetTimerDisplayModeChange: (mode: ResetTimerDisplayMode) => void
onResetTimerDisplayModeToggle: () => void
onMenubarIconStyleChange: (value: MenubarIconStyle) => void
onPreferMenubarWeeklyLimitChange: (value: boolean) => void
traySettingsPreview: TraySettingsPreview
onGlobalShortcutChange: (value: GlobalShortcut) => void
onStartOnLoginChange: (value: boolean) => void
Expand All @@ -52,6 +53,7 @@ export function AppContent({
onResetTimerDisplayModeChange,
onResetTimerDisplayModeToggle,
onMenubarIconStyleChange,
onPreferMenubarWeeklyLimitChange,
traySettingsPreview,
onGlobalShortcutChange,
onStartOnLoginChange,
Expand All @@ -66,6 +68,7 @@ export function AppContent({
displayMode,
resetTimerDisplayMode,
menubarIconStyle,
preferMenubarWeeklyLimit,
autoUpdateInterval,
globalShortcut,
themeMode,
Expand All @@ -75,6 +78,7 @@ export function AppContent({
displayMode: state.displayMode,
resetTimerDisplayMode: state.resetTimerDisplayMode,
menubarIconStyle: state.menubarIconStyle,
preferMenubarWeeklyLimit: state.preferMenubarWeeklyLimit,
autoUpdateInterval: state.autoUpdateInterval,
globalShortcut: state.globalShortcut,
themeMode: state.themeMode,
Expand Down Expand Up @@ -110,6 +114,8 @@ export function AppContent({
onResetTimerDisplayModeChange={onResetTimerDisplayModeChange}
menubarIconStyle={menubarIconStyle}
onMenubarIconStyleChange={onMenubarIconStyleChange}
preferMenubarWeeklyLimit={preferMenubarWeeklyLimit}
onPreferMenubarWeeklyLimitChange={onPreferMenubarWeeklyLimitChange}
traySettingsPreview={traySettingsPreview}
globalShortcut={globalShortcut}
onGlobalShortcutChange={onGlobalShortcutChange}
Expand Down
26 changes: 26 additions & 0 deletions src/hooks/app/use-settings-bootstrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const {
loadDisplayModeMock,
loadGlobalShortcutMock,
loadMenubarIconStyleMock,
loadPreferMenubarWeeklyLimitMock,
loadPluginSettingsMock,
loadResetTimerDisplayModeMock,
loadStartOnLoginMock,
Expand All @@ -32,6 +33,7 @@ const {
loadDisplayModeMock: vi.fn(),
loadGlobalShortcutMock: vi.fn(),
loadMenubarIconStyleMock: vi.fn(),
loadPreferMenubarWeeklyLimitMock: vi.fn(),
loadPluginSettingsMock: vi.fn(),
loadResetTimerDisplayModeMock: vi.fn(),
loadStartOnLoginMock: vi.fn(),
Expand All @@ -58,6 +60,7 @@ vi.mock("@/lib/settings", () => ({
DEFAULT_DISPLAY_MODE: "left",
DEFAULT_GLOBAL_SHORTCUT: null,
DEFAULT_MENUBAR_ICON_STYLE: "provider",
DEFAULT_PREFER_MENUBAR_WEEKLY_LIMIT: false,
DEFAULT_RESET_TIMER_DISPLAY_MODE: "relative",
DEFAULT_START_ON_LOGIN: false,
DEFAULT_THEME_MODE: "system",
Expand All @@ -66,6 +69,7 @@ vi.mock("@/lib/settings", () => ({
loadDisplayMode: loadDisplayModeMock,
loadGlobalShortcut: loadGlobalShortcutMock,
loadMenubarIconStyle: loadMenubarIconStyleMock,
loadPreferMenubarWeeklyLimit: loadPreferMenubarWeeklyLimitMock,
loadPluginSettings: loadPluginSettingsMock,
loadResetTimerDisplayMode: loadResetTimerDisplayModeMock,
loadStartOnLogin: loadStartOnLoginMock,
Expand All @@ -88,6 +92,7 @@ function createArgs() {
setGlobalShortcut: vi.fn(),
setStartOnLogin: vi.fn(),
setMenubarIconStyle: vi.fn(),
setPreferMenubarWeeklyLimit: vi.fn(),
setLoadingForPlugins: vi.fn(),
setErrorForPlugins: vi.fn(),
startBatch: vi.fn().mockResolvedValue(undefined),
Expand All @@ -107,6 +112,7 @@ describe("useSettingsBootstrap", () => {
loadDisplayModeMock.mockReset()
loadGlobalShortcutMock.mockReset()
loadMenubarIconStyleMock.mockReset()
loadPreferMenubarWeeklyLimitMock.mockReset()
loadPluginSettingsMock.mockReset()
loadResetTimerDisplayModeMock.mockReset()
loadStartOnLoginMock.mockReset()
Expand Down Expand Up @@ -136,6 +142,7 @@ describe("useSettingsBootstrap", () => {
loadResetTimerDisplayModeMock.mockResolvedValue("relative")
loadGlobalShortcutMock.mockResolvedValue("CommandOrControl+Shift+O")
loadMenubarIconStyleMock.mockResolvedValue("provider")
loadPreferMenubarWeeklyLimitMock.mockResolvedValue(true)
loadStartOnLoginMock.mockResolvedValue(true)
migrateLegacyTraySettingsMock.mockResolvedValue(undefined)
savePluginSettingsMock.mockResolvedValue(undefined)
Expand Down Expand Up @@ -170,4 +177,23 @@ describe("useSettingsBootstrap", () => {

errorSpy.mockRestore()
})

it("falls back to default menubar weekly limit preference when loading fails", async () => {
const weeklyPreferenceError = new Error("weekly preference unavailable")
const errorSpy = vi.spyOn(console, "error").mockImplementation(() => {})
loadPreferMenubarWeeklyLimitMock.mockRejectedValueOnce(weeklyPreferenceError)
const args = createArgs()

renderHook(() => useSettingsBootstrap(args))

await waitFor(() => {
expect(errorSpy).toHaveBeenCalledWith(
"Failed to load menubar weekly limit preference:",
weeklyPreferenceError
)
expect(args.setPreferMenubarWeeklyLimit).toHaveBeenCalledWith(false)
})

errorSpy.mockRestore()
})
})
13 changes: 13 additions & 0 deletions src/hooks/app/use-settings-bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
DEFAULT_DISPLAY_MODE,
DEFAULT_GLOBAL_SHORTCUT,
DEFAULT_MENUBAR_ICON_STYLE,
DEFAULT_PREFER_MENUBAR_WEEKLY_LIMIT,
DEFAULT_RESET_TIMER_DISPLAY_MODE,
DEFAULT_START_ON_LOGIN,
DEFAULT_THEME_MODE,
Expand All @@ -21,6 +22,7 @@ import {
loadGlobalShortcut,
loadMenubarIconStyle,
migrateLegacyTraySettings,
loadPreferMenubarWeeklyLimit,
loadPluginSettings,
loadResetTimerDisplayMode,
loadStartOnLogin,
Expand All @@ -46,6 +48,7 @@ type UseSettingsBootstrapArgs = {
setGlobalShortcut: (value: GlobalShortcut) => void
setStartOnLogin: (value: boolean) => void
setMenubarIconStyle: (value: MenubarIconStyle) => void
setPreferMenubarWeeklyLimit: (value: boolean) => void
setLoadingForPlugins: (ids: string[]) => void
setErrorForPlugins: (ids: string[], error: string) => void
startBatch: (pluginIds?: string[]) => Promise<string[] | undefined>
Expand All @@ -61,6 +64,7 @@ export function useSettingsBootstrap({
setGlobalShortcut,
setStartOnLogin,
setMenubarIconStyle,
setPreferMenubarWeeklyLimit,
setLoadingForPlugins,
setErrorForPlugins,
startBatch,
Expand Down Expand Up @@ -153,6 +157,13 @@ export function useSettingsBootstrap({
console.error("Failed to load menubar icon style:", error)
}

let storedPreferMenubarWeeklyLimit = DEFAULT_PREFER_MENUBAR_WEEKLY_LIMIT
try {
storedPreferMenubarWeeklyLimit = await loadPreferMenubarWeeklyLimit()
} catch (error) {
console.error("Failed to load menubar weekly limit preference:", error)
}

if (isMounted) {
setPluginSettings(normalized)
setAutoUpdateInterval(storedInterval)
Expand All @@ -162,6 +173,7 @@ export function useSettingsBootstrap({
setGlobalShortcut(storedGlobalShortcut)
setStartOnLogin(storedStartOnLogin)
setMenubarIconStyle(storedMenubarIconStyle)
setPreferMenubarWeeklyLimit(storedPreferMenubarWeeklyLimit)

const enabledIds = getEnabledPluginIds(normalized)
setLoadingForPlugins(enabledIds)
Expand Down Expand Up @@ -192,6 +204,7 @@ export function useSettingsBootstrap({
setGlobalShortcut,
setLoadingForPlugins,
setMenubarIconStyle,
setPreferMenubarWeeklyLimit,
migrateLegacyTraySettings,
setPluginSettings,
setPluginsMeta,
Expand Down
Loading
Loading