From 0c3e0938bb50ea1951022f183986a345cee4cbe3 Mon Sep 17 00:00:00 2001 From: origami99 <22319104+origami99@users.noreply.github.com> Date: Mon, 9 Nov 2026 03:05:08 +0200 Subject: [PATCH 1/2] fix(theme): stack Claude weekly and Fable meters without a session --- src/theme_engine/tests.rs | 77 +++++++++++++++++++++----- src/themes/classic-usage-widget.json | 83 ++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 33 deletions(-) diff --git a/src/theme_engine/tests.rs b/src/theme_engine/tests.rs index 73e7c38d..cd22e8cc 100644 --- a/src/theme_engine/tests.rs +++ b/src/theme_engine/tests.rs @@ -944,12 +944,16 @@ fn built_in_themes_hide_absent_claude_sessions_and_keep_weekly_and_fable_limits( } #[test] -fn built_in_classic_adds_a_fable_column_when_the_limit_is_available() { +fn classic_stacks_weekly_and_fable_without_a_claude_session() { use crate::models::{UsageData, UsageLimit, UsageSection}; - let usage = AppUsageData::from_iter([( + let mut usage = AppUsageData::from_iter([( ProviderId::Claude, UsageData { + weekly: UsageSection { + available: true, + ..Default::default() + }, limits: vec![UsageLimit { key: "weekly_scoped_fable".into(), kind: "weekly_scoped".into(), @@ -968,20 +972,63 @@ fn built_in_classic_adds_a_fable_column_when_the_limit_is_available() { }, )]); let theme = ThemeDocument::starter(); + let surface = &theme.surfaces[0]; - assert_eq!( - resolve_surface_size( - &theme, - 0, - Some(&usage), - ThemeRuntime::new(true, false, false) - ), - (310, 46) - ); - assert!(theme.surfaces[0] - .children - .iter() - .any(|object| object.id == "fable-provider")); + for session_available in [false, true] { + let mut claude = usage.get(ProviderId::Claude).unwrap().clone(); + claude.session.available = session_available; + usage.insert(ProviderId::Claude, claude); + for codex_enabled in [false, true] { + let runtime = ThemeRuntime::new(true, codex_enabled, false); + let (width, height) = resolve_surface_size(&theme, 0, Some(&usage), runtime); + let canvas = Canvas { + width, + height, + ..Default::default() + }; + let (objects, warnings) = + resolve_objects_for(surface, &canvas, &surface.children, Some(&usage), runtime); + assert!(warnings.is_empty(), "{warnings:?}"); + let object = |prefix: &str| { + objects + .iter() + .find(|o| o.source.id.starts_with(prefix)) + .unwrap() + }; + let session_label_visible = objects + .iter() + .any(|o| o.source.id.starts_with("session-label-")); + let stacked = !session_available && !codex_enabled; + let weekly_y = if stacked { 5.0 } else { 28.0 }; + assert_eq!(session_label_visible, !stacked); + let weekly_label = object("weekly-label-"); + assert_eq!(weekly_label.y, weekly_y); + let fable_label = objects + .iter() + .find(|o| o.source.id.starts_with("fable-window-label-")); + assert_eq!(fable_label.is_some(), stacked); + + let weekly_bar = object("claude-weekly-segments-"); + let weekly_value = object("claude-weekly-value-"); + let fable_bar = object("fable-weekly-segments-"); + let fable_value = object("fable-weekly-value-"); + assert_eq!(weekly_bar.y, weekly_y); + assert_eq!(weekly_value.y, weekly_y); + assert_eq!(fable_bar.y, if stacked { 28.0 } else { 5.0 }); + assert_eq!(fable_value.y, 28.0); + if let Some(fable_label) = fable_label { + assert_eq!(fable_label.x, weekly_label.x); + assert_eq!(fable_label.y, fable_bar.y); + assert_eq!(weekly_bar.x, fable_bar.x); + assert_eq!(weekly_bar.width, fable_bar.width); + assert_eq!(weekly_value.x, fable_value.x); + assert!(fable_value.x + fable_value.width <= f64::from(width)); + assert_eq!(width, 245); + } else { + assert!(fable_bar.x >= weekly_value.x + weekly_value.width); + } + } + } } #[test] diff --git a/src/themes/classic-usage-widget.json b/src/themes/classic-usage-widget.json index 373ebe18..de93eac3 100644 --- a/src/themes/classic-usage-widget.json +++ b/src/themes/classic-usage-widget.json @@ -20,7 +20,7 @@ "offset_x": 0, "offset_y": 0 }, - "width": "42 + providers.count * (ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62) + max(0, providers.count - 1) * 3 + (providers.opencode.enabled + providers.cursor.enabled) * 28 + providers.claude.enabled * claude.model.fable.available * 93", + "width": "42 + providers.count * (ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62) + max(0, providers.count - 1) * 3 + (providers.opencode.enabled + providers.cursor.enabled) * 28 + providers.claude.enabled * claude.model.fable.available * (93 - 65 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available))", "height": "46", "mouse_events": { "right_click": "show_context_menu(\"classic-v1\")" @@ -87,7 +87,7 @@ { "id": "session-label-dark", "name": "dark 5-hour label", - "render": "system.dark", + "render": "system.dark && !(providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "x": "13", "y": "5", "width": "18", @@ -111,6 +111,28 @@ "name": "dark 7-day label", "render": "system.dark * (1 - providers.opencode.enabled)", "x": "13", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "width": "18", + "height": "13", + "content": { + "type": "text", + "template": "{i18n.weekly_window}", + "font_family": "Segoe UI", + "font_size": "12", + "weight": "medium", + "rendering": "clear_type", + "contrast": "1", + "align": "left", + "color": { + "color": "#888888FF" + } + } + }, + { + "id": "fable-window-label-dark", + "name": "dark Fable 7-day label", + "render": "system.dark && providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available", + "x": "13", "y": "28", "width": "18", "height": "13", @@ -131,7 +153,7 @@ { "id": "session-label-light", "name": "light 5-hour label", - "render": "1 - system.dark", + "render": "(1 - system.dark) && !(providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "x": "13", "y": "5", "width": "18", @@ -155,6 +177,28 @@ "name": "light 7-day label", "render": "(1 - system.dark) * (1 - providers.opencode.enabled)", "x": "13", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "width": "18", + "height": "13", + "content": { + "type": "text", + "template": "{i18n.weekly_window}", + "font_family": "Segoe UI", + "font_size": "12", + "weight": "medium", + "rendering": "clear_type", + "contrast": "1", + "align": "left", + "color": { + "color": "#404040FF" + } + } + }, + { + "id": "fable-window-label-light", + "name": "light Fable 7-day label", + "render": "(1 - system.dark) && providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available", + "x": "13", "y": "28", "width": "18", "height": "13", @@ -528,7 +572,7 @@ "name": "dark Claude Code 7-day segments", "render": "system.dark", "parent": "claude-provider", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -553,7 +597,7 @@ "render": "(system.dark) && !claude.credits.available", "parent": "claude-provider", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "62", "height": "13", "content": { @@ -575,7 +619,7 @@ "name": "light Claude Code 7-day segments", "render": "1 - system.dark", "parent": "claude-provider", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -600,7 +644,7 @@ "render": "(1 - system.dark) && !claude.credits.available", "parent": "claude-provider", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "62", "height": "13", "content": { @@ -1210,7 +1254,7 @@ "name": "dark claude credit overlay", "render": "(system.dark) && claude.credits.available", "parent": "claude-provider", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -1237,7 +1281,7 @@ "render": "(system.dark) && claude.credits.available", "parent": "claude-provider", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "62", "height": "13", "content": { @@ -1260,7 +1304,7 @@ "name": "light claude credit overlay", "render": "(1 - system.dark) && claude.credits.available", "parent": "claude-provider", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -1287,7 +1331,7 @@ "render": "(1 - system.dark) && claude.credits.available", "parent": "claude-provider", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28", + "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "62", "height": "13", "content": { @@ -1714,7 +1758,8 @@ "name": "Fable weekly meter", "render": "providers.claude.enabled && claude.model.fable.available", "parent": "provider-row", - "width": "90", + "x": "-(ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62 + 3) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "width": "90 + (ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "height": "46" }, { @@ -1722,8 +1767,8 @@ "name": "dark Fable weekly segments", "render": "system.dark", "parent": "fable-provider", - "y": "5", - "width": "floor((90 + 1) / 11) * 11 - 1", + "y": "5 + 23 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "width": "87 + (ceil(10 / max(1, providers.count)) * 11 - 1 - 87) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "height": "13", "content": { "type": "progress", @@ -1737,7 +1782,7 @@ }, "corner_radius": "2", "segments": 8, - "segments_expression": "floor((90 + 1) / 11)", + "segments_expression": "8 + 2 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "segment_gap": "1" } }, @@ -1746,6 +1791,7 @@ "name": "dark Fable weekly value", "render": "system.dark", "parent": "fable-provider", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "y": "28", "width": "90", "height": "13", @@ -1768,8 +1814,8 @@ "name": "light Fable weekly segments", "render": "1 - system.dark", "parent": "fable-provider", - "y": "5", - "width": "floor((90 + 1) / 11) * 11 - 1", + "y": "5 + 23 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "width": "87 + (ceil(10 / max(1, providers.count)) * 11 - 1 - 87) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "height": "13", "content": { "type": "progress", @@ -1783,7 +1829,7 @@ }, "corner_radius": "2", "segments": 8, - "segments_expression": "floor((90 + 1) / 11)", + "segments_expression": "8 + 2 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "segment_gap": "1" } }, @@ -1792,6 +1838,7 @@ "name": "light Fable weekly value", "render": "1 - system.dark", "parent": "fable-provider", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", "y": "28", "width": "90", "height": "13", From a11cd32124c8d3c19eaa3943afdeda1ea2f7682e Mon Sep 17 00:00:00 2001 From: origami99 <22319104+origami99@users.noreply.github.com> Date: Mon, 9 Nov 2026 04:31:10 +0200 Subject: [PATCH 2/2] fix(theme): keep Claude weekly meters together with other providers --- src/theme_engine/tests.rs | 74 +++++++----- src/themes/classic-usage-widget.json | 163 ++++++++++++++++++--------- 2 files changed, 159 insertions(+), 78 deletions(-) diff --git a/src/theme_engine/tests.rs b/src/theme_engine/tests.rs index cd22e8cc..6a4b9ba3 100644 --- a/src/theme_engine/tests.rs +++ b/src/theme_engine/tests.rs @@ -978,8 +978,14 @@ fn classic_stacks_weekly_and_fable_without_a_claude_session() { let mut claude = usage.get(ProviderId::Claude).unwrap().clone(); claude.session.available = session_available; usage.insert(ProviderId::Claude, claude); - for codex_enabled in [false, true] { - let runtime = ThemeRuntime::new(true, codex_enabled, false); + for (runtime, provider_count) in [ + (ThemeRuntime::new(true, false, false), 1), + (ThemeRuntime::new(true, true, false), 2), + ( + ThemeRuntime::from_providers(ProviderSet::from_enabled(ProviderId::ALL)), + ProviderId::ALL.len(), + ), + ] { let (width, height) = resolve_surface_size(&theme, 0, Some(&usage), runtime); let canvas = Canvas { width, @@ -989,41 +995,57 @@ fn classic_stacks_weekly_and_fable_without_a_claude_session() { let (objects, warnings) = resolve_objects_for(surface, &canvas, &surface.children, Some(&usage), runtime); assert!(warnings.is_empty(), "{warnings:?}"); - let object = |prefix: &str| { - objects - .iter() - .find(|o| o.source.id.starts_with(prefix)) - .unwrap() - }; - let session_label_visible = objects - .iter() - .any(|o| o.source.id.starts_with("session-label-")); - let stacked = !session_available && !codex_enabled; + let find = |prefix: &str| objects.iter().find(|o| o.source.id.starts_with(prefix)); + let stacked = !session_available; let weekly_y = if stacked { 5.0 } else { 28.0 }; - assert_eq!(session_label_visible, !stacked); - let weekly_label = object("weekly-label-"); - assert_eq!(weekly_label.y, weekly_y); - let fable_label = objects - .iter() - .find(|o| o.source.id.starts_with("fable-window-label-")); - assert_eq!(fable_label.is_some(), stacked); - let weekly_bar = object("claude-weekly-segments-"); - let weekly_value = object("claude-weekly-value-"); - let fable_bar = object("fable-weekly-segments-"); - let fable_value = object("fable-weekly-value-"); + assert_eq!( + find("session-label-").is_some(), + session_available || provider_count > 1 + ); + assert_eq!( + find("claude-session-segments-").is_some(), + session_available + ); + assert_eq!(find("claude-window-label-").is_some(), stacked); + assert_eq!(find("fable-window-label-").is_some(), stacked); + + let weekly_bar = find("claude-weekly-segments-").unwrap(); + let weekly_value = find("claude-weekly-value-").unwrap(); + let fable_bar = find("fable-weekly-segments-").unwrap(); + let fable_value = find("fable-weekly-value-").unwrap(); assert_eq!(weekly_bar.y, weekly_y); assert_eq!(weekly_value.y, weekly_y); assert_eq!(fable_bar.y, if stacked { 28.0 } else { 5.0 }); assert_eq!(fable_value.y, 28.0); - if let Some(fable_label) = fable_label { - assert_eq!(fable_label.x, weekly_label.x); + if stacked { + let claude_label = find("claude-window-label-").unwrap(); + let fable_label = find("fable-window-label-").unwrap(); + assert_eq!(claude_label.x, fable_label.x); + assert_eq!(claude_label.y, weekly_bar.y); assert_eq!(fable_label.y, fable_bar.y); assert_eq!(weekly_bar.x, fable_bar.x); assert_eq!(weekly_bar.width, fable_bar.width); assert_eq!(weekly_value.x, fable_value.x); assert!(fable_value.x + fable_value.width <= f64::from(width)); - assert_eq!(width, 245); + + for provider in objects + .iter() + .filter(|object| object.source.parent.as_deref() == Some("provider-row")) + { + assert!(provider.x + provider.width <= claude_label.x); + } + if provider_count == 1 { + assert_eq!(width, 245); + assert!(find("weekly-label-").is_none()); + } else if provider_count == 2 { + let codex_session = find("codex-session-segments-").unwrap(); + let codex_weekly = find("codex-weekly-segments-").unwrap(); + assert_eq!(codex_session.x, 41.0); + assert_eq!(codex_session.x, codex_weekly.x); + assert_eq!(find("session-label-").unwrap().y, codex_session.y); + assert_eq!(find("weekly-label-").unwrap().y, codex_weekly.y); + } } else { assert!(fable_bar.x >= weekly_value.x + weekly_value.width); } diff --git a/src/themes/classic-usage-widget.json b/src/themes/classic-usage-widget.json index de93eac3..e71a2ea1 100644 --- a/src/themes/classic-usage-widget.json +++ b/src/themes/classic-usage-widget.json @@ -20,7 +20,7 @@ "offset_x": 0, "offset_y": 0 }, - "width": "42 + providers.count * (ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62) + max(0, providers.count - 1) * 3 + (providers.opencode.enabled + providers.cursor.enabled) * 28 + providers.claude.enabled * claude.model.fable.available * (93 - 65 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available))", + "width": "42 + providers.count * (ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62) + max(0, providers.count - 1) * 3 + (providers.opencode.enabled + providers.cursor.enabled) * 28 + providers.claude.enabled * claude.model.fable.available * if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 28 + 28 * (providers.count > 1), 93)", "height": "46", "mouse_events": { "right_click": "show_context_menu(\"classic-v1\")" @@ -109,9 +109,9 @@ { "id": "weekly-label-dark", "name": "dark 7-day label", - "render": "system.dark * (1 - providers.opencode.enabled)", + "render": "system.dark && !providers.opencode.enabled && !((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available) && providers.count == 1)", "x": "13", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "y": "28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "18", "height": "13", "content": { @@ -128,11 +128,34 @@ } } }, + { + "id": "claude-window-label-dark", + "name": "dark Claude 7-day label", + "render": "system.dark && (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "x": "0", + "y": "5", + "width": "18", + "height": "13", + "content": { + "type": "text", + "template": "{i18n.weekly_window}", + "font_family": "Segoe UI", + "font_size": "12", + "weight": "medium", + "rendering": "clear_type", + "contrast": "1", + "align": "left", + "color": { + "color": "#888888FF" + } + }, + "parent": "claude-usage" + }, { "id": "fable-window-label-dark", "name": "dark Fable 7-day label", - "render": "system.dark && providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available", - "x": "13", + "render": "system.dark && (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "x": "0", "y": "28", "width": "18", "height": "13", @@ -148,7 +171,8 @@ "color": { "color": "#888888FF" } - } + }, + "parent": "claude-usage" }, { "id": "session-label-light", @@ -175,9 +199,9 @@ { "id": "weekly-label-light", "name": "light 7-day label", - "render": "(1 - system.dark) * (1 - providers.opencode.enabled)", + "render": "(1 - system.dark) && !providers.opencode.enabled && !((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available) && providers.count == 1)", "x": "13", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "y": "28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", "width": "18", "height": "13", "content": { @@ -194,11 +218,34 @@ } } }, + { + "id": "claude-window-label-light", + "name": "light Claude 7-day label", + "render": "(1 - system.dark) && (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "x": "0", + "y": "5", + "width": "18", + "height": "13", + "content": { + "type": "text", + "template": "{i18n.weekly_window}", + "font_family": "Segoe UI", + "font_size": "12", + "weight": "medium", + "rendering": "clear_type", + "contrast": "1", + "align": "left", + "color": { + "color": "#404040FF" + } + }, + "parent": "claude-usage" + }, { "id": "fable-window-label-light", "name": "light Fable 7-day label", - "render": "(1 - system.dark) && providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available", - "x": "13", + "render": "(1 - system.dark) && (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "x": "0", "y": "28", "width": "18", "height": "13", @@ -214,7 +261,8 @@ "color": { "color": "#404040FF" } - } + }, + "parent": "claude-usage" }, { "id": "cursor-provider", @@ -467,17 +515,25 @@ }, { "id": "claude-provider", - "name": "Claude Code provider", - "render": "providers.claude.enabled", + "name": "Claude Code slot", + "render": "providers.claude.enabled && !(providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", "parent": "provider-row", "width": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62", "height": "46" }, + { + "id": "claude-usage", + "name": "Claude Code usage", + "render": "providers.claude.enabled", + "x": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), canvas.width - 1 - ((ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 90 + 28), 41 + providers.cursor.enabled * ((ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 90 + 3))", + "width": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), (ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 90 + 28, (ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 62)", + "height": "46" + }, { "id": "claude-session-segments-dark", "name": "dark Claude Code 5-hour segments", "render": "(system.dark) && claude.session.available", - "parent": "claude-provider", + "parent": "claude-usage", "y": "5", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", @@ -501,7 +557,7 @@ "id": "claude-session-value-dark", "name": "dark Claude Code 5-hour value", "render": "(system.dark) && claude.session.available", - "parent": "claude-provider", + "parent": "claude-usage", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", "y": "5", "width": "62", @@ -524,7 +580,7 @@ "id": "claude-session-segments-light", "name": "light Claude Code 5-hour segments", "render": "(1 - system.dark) && claude.session.available", - "parent": "claude-provider", + "parent": "claude-usage", "y": "5", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", @@ -548,7 +604,7 @@ "id": "claude-session-value-light", "name": "light Claude Code 5-hour value", "render": "(1 - system.dark) && claude.session.available", - "parent": "claude-provider", + "parent": "claude-usage", "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", "y": "5", "width": "62", @@ -571,8 +627,8 @@ "id": "claude-weekly-segments-dark", "name": "dark Claude Code 7-day segments", "render": "system.dark", - "parent": "claude-provider", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -589,15 +645,16 @@ "segments": 10, "segments_expression": "ceil(10 / max(1, providers.count))", "segment_gap": "1" - } + }, + "x": "0 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)" }, { "id": "claude-weekly-value-dark", "name": "dark Claude Code 7-day value", "render": "(system.dark) && !claude.credits.available", - "parent": "claude-provider", - "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "62", "height": "13", "content": { @@ -618,8 +675,8 @@ "id": "claude-weekly-segments-light", "name": "light Claude Code 7-day segments", "render": "1 - system.dark", - "parent": "claude-provider", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -636,15 +693,16 @@ "segments": 10, "segments_expression": "ceil(10 / max(1, providers.count))", "segment_gap": "1" - } + }, + "x": "0 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)" }, { "id": "claude-weekly-value-light", "name": "light Claude Code 7-day value", "render": "(1 - system.dark) && !claude.credits.available", - "parent": "claude-provider", - "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "62", "height": "13", "content": { @@ -1253,8 +1311,8 @@ "id": "claude-credits-segments-dark", "name": "dark claude credit overlay", "render": "(system.dark) && claude.credits.available", - "parent": "claude-provider", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -1273,15 +1331,16 @@ "segments": 10, "segments_expression": "ceil(10 / max(1, providers.count))", "segment_gap": "1" - } + }, + "x": "0 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)" }, { "id": "claude-credits-value-dark", "name": "dark claude credit balance", "render": "(system.dark) && claude.credits.available", - "parent": "claude-provider", - "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "62", "height": "13", "content": { @@ -1303,8 +1362,8 @@ "id": "claude-credits-segments-light", "name": "light claude credit overlay", "render": "(1 - system.dark) && claude.credits.available", - "parent": "claude-provider", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "ceil(10 / max(1, providers.count)) * 11 - 1", "height": "13", "content": { @@ -1323,15 +1382,16 @@ "segments": 10, "segments_expression": "ceil(10 / max(1, providers.count))", "segment_gap": "1" - } + }, + "x": "0 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)" }, { "id": "claude-credits-value-light", "name": "light claude credit balance", "render": "(1 - system.dark) && claude.credits.available", - "parent": "claude-provider", - "x": "ceil(10 / max(1, providers.count)) * 11 - 1 + 4", - "y": "28 - (12 + 11 * claude.model.fable.available) * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available)", + "parent": "claude-usage", + "x": "(ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 28 * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 5, 28 - 12 * (providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available))", "width": "62", "height": "13", "content": { @@ -1757,9 +1817,8 @@ "id": "fable-provider", "name": "Fable weekly meter", "render": "providers.claude.enabled && claude.model.fable.available", - "parent": "provider-row", - "x": "-(ceil(10 / max(1, providers.count)) * 11 - 1 + 4 + 62 + 3) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", - "width": "90 + (ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "x": "canvas.width - 1 - if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), (ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 90, 90)", + "width": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), (ceil(10 / max(1, providers.count)) * 11 - 1) + 4 + 90, 90)", "height": "46" }, { @@ -1767,8 +1826,8 @@ "name": "dark Fable weekly segments", "render": "system.dark", "parent": "fable-provider", - "y": "5 + 23 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", - "width": "87 + (ceil(10 / max(1, providers.count)) * 11 - 1 - 87) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 28, 5)", + "width": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), (ceil(10 / max(1, providers.count)) * 11 - 1), 87)", "height": "13", "content": { "type": "progress", @@ -1782,7 +1841,7 @@ }, "corner_radius": "2", "segments": 8, - "segments_expression": "8 + 2 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "segments_expression": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), ceil(10 / max(1, providers.count)), 8)", "segment_gap": "1" } }, @@ -1791,7 +1850,7 @@ "name": "dark Fable weekly value", "render": "system.dark", "parent": "fable-provider", - "x": "(ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "x": "((ceil(10 / max(1, providers.count)) * 11 - 1) + 4) * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", "y": "28", "width": "90", "height": "13", @@ -1814,8 +1873,8 @@ "name": "light Fable weekly segments", "render": "1 - system.dark", "parent": "fable-provider", - "y": "5 + 23 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", - "width": "87 + (ceil(10 / max(1, providers.count)) * 11 - 1 - 87) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "y": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), 28, 5)", + "width": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), (ceil(10 / max(1, providers.count)) * 11 - 1), 87)", "height": "13", "content": { "type": "progress", @@ -1829,7 +1888,7 @@ }, "corner_radius": "2", "segments": 8, - "segments_expression": "8 + 2 * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "segments_expression": "if((providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available), ceil(10 / max(1, providers.count)), 8)", "segment_gap": "1" } }, @@ -1838,7 +1897,7 @@ "name": "light Fable weekly value", "render": "1 - system.dark", "parent": "fable-provider", - "x": "(ceil(10 / max(1, providers.count)) * 11 - 1 + 4) * ((providers.count == 1 && providers.claude.enabled && claude.weekly.available && !claude.session.available) && claude.model.fable.available)", + "x": "((ceil(10 / max(1, providers.count)) * 11 - 1) + 4) * (providers.claude.enabled && claude.weekly.available && !claude.session.available && claude.model.fable.available)", "y": "28", "width": "90", "height": "13",