Skip to content
Closed
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
2 changes: 2 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ pub struct SettingsSnapshot {
float_bar_style: String,
taskbar_widget_open_on_hover: bool,
float_bar_density: String,
float_bar_information_mode: String,
float_bar_contrast: String,
float_bar_click_through: bool,
float_bar_provider_ids: Vec<String>,
Expand Down Expand Up @@ -661,6 +662,7 @@ impl From<Settings> for SettingsSnapshot {
float_bar_style: settings.float_bar_style,
taskbar_widget_open_on_hover: settings.taskbar_widget_open_on_hover,
float_bar_density: settings.float_bar_density,
float_bar_information_mode: settings.float_bar_information_mode,
float_bar_contrast,
float_bar_click_through: settings.float_bar_click_through,
float_bar_provider_ids: settings.float_bar_provider_ids,
Expand Down
2 changes: 2 additions & 0 deletions apps/desktop-tauri/src-tauri/src/commands/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub struct SettingsUpdate {
pub float_bar_style: Option<String>,
pub taskbar_widget_open_on_hover: Option<bool>,
pub float_bar_density: Option<String>,
pub float_bar_information_mode: Option<String>,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Notify the detached FloatBar when information mode changes.

notifies_float_bar() does not check float_bar_information_mode. Therefore, changing only Exact/Calm can persist to Rust without emitting the configuration event that makes FloatBar.tsx re-fetch its snapshot, leaving the visible bar in the previous mode until another setting change or restart. Include this field in the predicate and add a mode-only update regression test.

Suggested fix
     fn notifies_float_bar(&self) -> bool {
         self.enabled_providers.is_some()
             || self.refresh_interval_secs.is_some()
             || self.codex_custom_sessions_dirs.is_some()
             || self.high_usage_threshold.is_some()
             || self.critical_usage_threshold.is_some()
             || self.provider_usage_thresholds.is_some()
             || self.show_as_used.is_some()
             || self.reset_time_relative.is_some()
             || self.show_reset_when_exhausted.is_some()
+            || self.float_bar_information_mode.is_some()
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop-tauri/src-tauri/src/commands/settings.rs` at line 61, Update the
notifies_float_bar() predicate to include float_bar_information_mode alongside
the existing FloatBar settings, so mode-only changes emit the configuration
event. Add a regression test covering an Exact/Calm-only change and verify that
it triggers notification.

pub float_bar_contrast: Option<String>,
pub float_bar_click_through: Option<bool>,
pub float_bar_provider_ids: Option<Vec<String>>,
Expand Down Expand Up @@ -283,6 +284,7 @@ impl SettingsUpdate {
style: self.float_bar_style.clone(),
open_on_hover: self.taskbar_widget_open_on_hover,
density: self.float_bar_density.clone(),
information_mode: self.float_bar_information_mode.clone(),
contrast: self.float_bar_contrast.clone(),
click_through: self.float_bar_click_through,
provider_ids: self.float_bar_provider_ids.clone(),
Expand Down
22 changes: 22 additions & 0 deletions apps/desktop-tauri/src-tauri/src/floatbar/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub struct SettingsPatch {
pub style: Option<String>,
pub open_on_hover: Option<bool>,
pub density: Option<String>,
pub information_mode: Option<String>,
pub contrast: Option<String>,
pub click_through: Option<bool>,
pub provider_ids: Option<Vec<String>>,
Expand All @@ -126,6 +127,7 @@ impl SettingsPatch {
&& self.style.is_none()
&& self.open_on_hover.is_none()
&& self.density.is_none()
&& self.information_mode.is_none()
&& self.contrast.is_none()
&& self.click_through.is_none()
&& self.provider_ids.is_none()
Expand Down Expand Up @@ -164,6 +166,10 @@ impl SettingsPatch {
if let Some(v) = &self.density {
settings.float_bar_density = codexbar::settings::normalize_float_bar_density(v);
}
if let Some(v) = &self.information_mode {
settings.float_bar_information_mode =
codexbar::settings::normalize_float_bar_information_mode(v);
}
if let Some(v) = &self.contrast {
settings.float_bar_contrast = Some(codexbar::settings::normalize_float_bar_contrast(v));
}
Expand Down Expand Up @@ -218,6 +224,22 @@ mod tests {
assert!(SettingsPatch::default().is_empty());
}

#[test]
fn information_mode_only_change_is_a_non_empty_patch() {
// A mode-only change must count as a float-bar patch so the detached
// bar is told to re-fetch (after_settings_saved notifies when the patch
// is non-empty), and so it applies the new mode on disk.
let patch = SettingsPatch {
information_mode: Some("calm".into()),
..SettingsPatch::default()
};
assert!(!patch.is_empty());

let mut settings = Settings::default();
patch.apply(&mut settings);
assert_eq!(settings.float_bar_information_mode, "calm");
}

#[test]
fn settings_patch_apply_only_writes_present_fields() {
let mut s = Settings {
Expand Down
1 change: 1 addition & 0 deletions apps/desktop-tauri/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ function settings(overrides: Partial<SettingsSnapshot> = {}): SettingsSnapshot {
floatBarStyle: "floating",
taskbarWidgetOpenOnHover: true,
floatBarDensity: "standard",
floatBarInformationMode: "exact",
floatBarContrast: "auto",
floatBarClickThrough: false,
floatBarProviderIds: [],
Expand Down
45 changes: 45 additions & 0 deletions apps/desktop-tauri/src/floatbar/FloatBar.css
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,51 @@ body.floatbar-window #root {
.floatbar__reset--emphasis .floatbar__reset-time {
font-weight: 650;
}
/* ── Calm information mode ─────────────────────────────────────────────
The pill leads with a trustworthy pace state + next reset and becomes an
expandable button. No new motion, so reduced-motion is unaffected. */
.floatbar__pill--calm {
cursor: pointer;
}
.floatbar__pill--calm:focus-visible {
outline: 2px solid color-mix(in srgb, var(--ceiling-accent, #26b5ce) 70%, white);
outline-offset: 1px;
}
.floatbar__pace {
font-size: 0.86em;
font-weight: 650;
line-height: 1;
white-space: nowrap;
}
.floatbar__pace--steady {
color: color-mix(in srgb, #34d399 62%, white);
}
.floatbar__pace--watch {
color: color-mix(in srgb, #f59e0b 68%, white);
}
.floatbar__calm-reset {
display: inline-flex;
align-items: center;
gap: calc(3px * var(--floatbar-scale, 1));
opacity: 0.66;
line-height: 1;
}
.floatbar__calm-sep {
opacity: 0.5;
}
.floatbar__pct--calm {
padding-left: calc(6px * var(--floatbar-scale, 1));
margin-left: calc(2px * var(--floatbar-scale, 1));
border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use the Stylelint-compliant keyword casing.

-  border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent);
+  border-left: 1px solid color-mix(in srgb, currentcolor 18%, transparent);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
border-left: 1px solid color-mix(in srgb, currentColor 18%, transparent);
border-left: 1px solid color-mix(in srgb, currentcolor 18%, transparent);
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 325-325: Expected "currentColor" to be "currentcolor" (value-keyword-case)

(value-keyword-case)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop-tauri/src/floatbar/FloatBar.css` at line 325, Update the
border-left declaration in FloatBar.css to use the Stylelint-compliant casing
for the color-mix function keyword, preserving the existing color values and
border styling.

Source: Linters/SAST tools

font-size: 0.98em;
}
.floatbar--light-bg .floatbar__pace--steady {
color: color-mix(in srgb, #059669 78%, black);
}
.floatbar--light-bg .floatbar__pace--watch {
color: color-mix(in srgb, #b45309 82%, black);
}

.floatbar--vertical .floatbar__text {
flex-direction: column;
align-items: center;
Expand Down
68 changes: 68 additions & 0 deletions apps/desktop-tauri/src/floatbar/FloatBar.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ function settings(overrides: Partial<SettingsSnapshot> = {}): SettingsSnapshot {
floatBarStyle: "floating",
taskbarWidgetOpenOnHover: true,
floatBarDensity: "standard",
floatBarInformationMode: "exact",
floatBarContrast: "light-text",
floatBarClickThrough: false,
floatBarProviderIds: [],
Expand Down Expand Up @@ -221,6 +222,73 @@ describe("FloatBar", () => {
expect(titles[1]).toMatch(/Claude: 20% used/);
});

it("calm mode leads with a pace state and expands to the exact % on click", async () => {
const calmProvider: ProviderUsageSnapshot = {
...snapshot("codex", "Codex", 60, {
resetsAt: new Date(Date.now() + 2 * 3600_000).toISOString(),
}),
updatedAt: new Date().toISOString(),
pace: {
windowLabel: "Weekly",
stage: "on_track",
deltaPercent: 0,
willLastToReset: true,
etaSeconds: null,
expectedUsedPercent: 60,
actualUsedPercent: 60,
},
};
tauriMocks.getCachedProviders.mockResolvedValue([calmProvider]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(
settings({ floatBarInformationMode: "calm" }),
);

const { container } = renderFloatBar(
bootstrap({ floatBarInformationMode: "calm" }),
);
await waitFor(() => {
expect(container.querySelector(".floatbar__pill--calm")).toBeInTheDocument();
});

// Calm leads with the trustworthy pace state; the exact % is hidden until
// the user expands, and the pill is a keyboard-accessible button.
expect(container.querySelector(".floatbar__pace")).toHaveTextContent("On pace");
expect(container.querySelector(".floatbar__pct--calm")).toBeNull();
const pill = container.querySelector<HTMLElement>(".floatbar__pill--calm")!;
expect(pill.getAttribute("role")).toBe("button");
expect(pill.getAttribute("tabindex")).toBe("0");

act(() => {
pill.click();
});
expect(container.querySelector(".floatbar__pct--calm")).toHaveTextContent("60%");
});

it("calm + compact stays non-blank and drops the window·reset row", async () => {
// No fresh pace + compact density (which hides the window/reset): the pill
// must still show the exact % rather than collapse to just the icon, and
// the calm reset row (with its separator) must not render.
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("codex", "Codex", 60, {
resetsAt: new Date(Date.now() + 3600_000).toISOString(),
}),
]);
tauriMocks.getSettingsSnapshot.mockResolvedValue(
settings({ floatBarInformationMode: "calm", floatBarDensity: "compact" }),
);

const { container } = renderFloatBar(
bootstrap({ floatBarInformationMode: "calm", floatBarDensity: "compact" }),
);
await waitFor(() => {
expect(container.querySelector(".floatbar__pill--calm")).toBeInTheDocument();
});

expect(container.querySelector(".floatbar__calm-reset")).toBeNull();
expect(container.querySelector(".floatbar__calm-sep")).toBeNull();
expect(container.querySelector(".floatbar__pct--calm")).toHaveTextContent("60%");
});

it("does not render hypothetical local costs from the legacy setting", async () => {
tauriMocks.getCachedProviders.mockResolvedValue([
snapshot("codex", "Codex", 75),
Expand Down
Loading