Flatten AGS corners and restyle the Claude card
Claude-Session: https://claude.ai/code/session_014ADhvRXuiTvrXSbConxUey
This commit is contained in:
+103
-44
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
.media-container {
|
.media-container {
|
||||||
background-color: alpha(@background, 0.85);
|
background-color: alpha(@background, 0.85);
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
border: 2px solid alpha(@color4, 0.5);
|
border: 2px solid alpha(@color4, 0.5);
|
||||||
padding: 8px 15px;
|
padding: 8px 15px;
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
.media-cover {
|
.media-cover {
|
||||||
min-width: 64px;
|
min-width: 64px;
|
||||||
min-height: 64px;
|
min-height: 64px;
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
}
|
}
|
||||||
@@ -64,12 +64,12 @@
|
|||||||
.media-progress trough {
|
.media-progress trough {
|
||||||
min-height: 4px;
|
min-height: 4px;
|
||||||
background-color: alpha(@foreground, 0.2);
|
background-color: alpha(@foreground, 0.2);
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-progress highlight {
|
.media-progress highlight {
|
||||||
background-color: @accent;
|
background-color: @accent;
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.media-progress slider {
|
.media-progress slider {
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
background-color: alpha(@background, 0.92);
|
background-color: alpha(@background, 0.92);
|
||||||
border-radius: 12px;
|
border-radius: 0;
|
||||||
border: 2px solid alpha(@color4, 0.5);
|
border: 2px solid alpha(@color4, 0.5);
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
font-family: "JetBrainsMono Nerd Font", sans-serif;
|
font-family: "JetBrainsMono Nerd Font", sans-serif;
|
||||||
@@ -112,7 +112,7 @@
|
|||||||
color: @color5;
|
color: @color5;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 3px 6px;
|
padding: 3px 6px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@
|
|||||||
|
|
||||||
.notification-item {
|
.notification-item {
|
||||||
background-color: alpha(@color0, 0.6);
|
background-color: alpha(@color0, 0.6);
|
||||||
border-radius: 10px;
|
border-radius: 0;
|
||||||
border-left: 3px solid @accent;
|
border-left: 3px solid @accent;
|
||||||
padding: 10px 12px;
|
padding: 10px 12px;
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
|
|
||||||
.qs-tile {
|
.qs-tile {
|
||||||
background-color: alpha(@color0, 0.6);
|
background-color: alpha(@color0, 0.6);
|
||||||
border-radius: 10px;
|
border-radius: 0;
|
||||||
padding: 8px 4px;
|
padding: 8px 4px;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
@@ -228,18 +228,18 @@
|
|||||||
|
|
||||||
.qs-slider trough {
|
.qs-slider trough {
|
||||||
min-height: 8px;
|
min-height: 8px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-color: alpha(@foreground, 0.2);
|
background-color: alpha(@foreground, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.qs-slider highlight {
|
.qs-slider highlight {
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-color: @accent;
|
background-color: @accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.qs-slider slider {
|
.qs-slider slider {
|
||||||
background-color: @foreground;
|
background-color: @foreground;
|
||||||
border-radius: 50%;
|
border-radius: 0;
|
||||||
min-width: 14px;
|
min-width: 14px;
|
||||||
min-height: 14px;
|
min-height: 14px;
|
||||||
margin: -4px;
|
margin: -4px;
|
||||||
@@ -271,12 +271,12 @@
|
|||||||
|
|
||||||
.sys-metric-bar trough {
|
.sys-metric-bar trough {
|
||||||
min-height: 8px;
|
min-height: 8px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-color: alpha(@foreground, 0.2);
|
background-color: alpha(@foreground, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.sys-metric-bar block.filled {
|
.sys-metric-bar block.filled {
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-color: @accent;
|
background-color: @accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +318,7 @@
|
|||||||
|
|
||||||
.wall-thumb {
|
.wall-thumb {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 10px;
|
border-radius: 0;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
@@ -330,7 +330,7 @@
|
|||||||
.wall-thumb-image {
|
.wall-thumb-image {
|
||||||
min-width: 200px;
|
min-width: 200px;
|
||||||
min-height: 112px;
|
min-height: 112px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@@ -361,7 +361,7 @@
|
|||||||
|
|
||||||
.theme-chip {
|
.theme-chip {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
border-radius: 10px;
|
border-radius: 0;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
background-color: alpha(@color0, 0.6);
|
background-color: alpha(@color0, 0.6);
|
||||||
transition: all 0.2s;
|
transition: all 0.2s;
|
||||||
@@ -396,7 +396,7 @@
|
|||||||
|
|
||||||
.theme-swatches {
|
.theme-swatches {
|
||||||
min-height: 36px;
|
min-height: 36px;
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-swatch {
|
.theme-swatch {
|
||||||
@@ -422,7 +422,7 @@
|
|||||||
|
|
||||||
.widget-icon-badge {
|
.widget-icon-badge {
|
||||||
background-color: alpha(@accent, 0.18);
|
background-color: alpha(@accent, 0.18);
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
min-width: 32px;
|
min-width: 32px;
|
||||||
min-height: 32px;
|
min-height: 32px;
|
||||||
color: @accent;
|
color: @accent;
|
||||||
@@ -472,25 +472,39 @@
|
|||||||
|
|
||||||
.widget-level-bar trough {
|
.widget-level-bar trough {
|
||||||
min-height: 6px;
|
min-height: 6px;
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
background-color: alpha(@foreground, 0.15);
|
background-color: alpha(@foreground, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.widget-level-bar block.filled {
|
.widget-level-bar block.filled {
|
||||||
border-radius: 6px;
|
border-radius: 0;
|
||||||
background-color: @accent;
|
background-color: @accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.widget-section-title {
|
.widget-section-title {
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
opacity: 0.55;
|
opacity: 0.45;
|
||||||
margin-top: 2px;
|
border-top: 1px solid alpha(@foreground, 0.12);
|
||||||
|
padding-top: 10px;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-mark {
|
||||||
|
color: @accent;
|
||||||
|
font-size: 20px;
|
||||||
|
min-width: 26px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-name {
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: @foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-plan {
|
.agent-plan {
|
||||||
font-size: 11px;
|
font-size: 10px;
|
||||||
color: @accent;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-status {
|
.agent-status {
|
||||||
@@ -504,40 +518,85 @@
|
|||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-limit-reset {
|
.agent-limit-name {
|
||||||
font-size: 10px;
|
font-size: 14px;
|
||||||
opacity: 0.55;
|
color: @foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar-row {
|
.agent-limit-percent {
|
||||||
|
font-size: 12px;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-limit-reset {
|
||||||
|
font-size: 10px;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-limit-bar,
|
||||||
|
.agent-day-bar {
|
||||||
|
min-height: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-limit-bar trough,
|
||||||
|
.agent-day-bar trough {
|
||||||
|
min-height: 3px;
|
||||||
|
background-color: alpha(@foreground, 0.14);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-limit-bar block.filled,
|
||||||
|
.agent-day-bar block.filled {
|
||||||
|
background-color: @foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-day-row {
|
||||||
padding: 1px 0;
|
padding: 1px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar-label {
|
.agent-day-label {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
opacity: 0.8;
|
opacity: 0.6;
|
||||||
min-width: 44px;
|
min-width: 44px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar-value {
|
.agent-day-value {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
opacity: 0.8;
|
opacity: 0.6;
|
||||||
min-width: 54px;
|
min-width: 58px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar-label.emphasized,
|
.agent-day-label.emphasized,
|
||||||
.agent-bar-value.emphasized {
|
.agent-day-value.emphasized {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
color: @foreground;
|
color: @foreground;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar {
|
.agent-model-bar {
|
||||||
min-height: 4px;
|
min-height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.agent-bar trough {
|
.agent-model-bar trough {
|
||||||
min-height: 4px;
|
min-height: 22px;
|
||||||
|
background-color: alpha(@foreground, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-model-bar block.filled {
|
||||||
|
background-color: alpha(@foreground, 0.18);
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-model-text {
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-model-label {
|
||||||
|
font-size: 11px;
|
||||||
|
color: @foreground;
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-model-value {
|
||||||
|
font-size: 11px;
|
||||||
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
.control-center {
|
.control-center {
|
||||||
@@ -561,14 +620,14 @@
|
|||||||
|
|
||||||
.cc-media {
|
.cc-media {
|
||||||
background-color: alpha(@color0, 0.6);
|
background-color: alpha(@color0, 0.6);
|
||||||
border-radius: 10px;
|
border-radius: 0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cc-media-cover {
|
.cc-media-cover {
|
||||||
min-width: 84px;
|
min-width: 84px;
|
||||||
min-height: 84px;
|
min-height: 84px;
|
||||||
border-radius: 8px;
|
border-radius: 0;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
@@ -595,12 +654,12 @@
|
|||||||
|
|
||||||
.cc-media-seek trough {
|
.cc-media-seek trough {
|
||||||
min-height: 4px;
|
min-height: 4px;
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
background-color: alpha(@foreground, 0.2);
|
background-color: alpha(@foreground, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cc-media-seek highlight {
|
.cc-media-seek highlight {
|
||||||
border-radius: 4px;
|
border-radius: 0;
|
||||||
background-color: @accent;
|
background-color: @accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+52
-70
@@ -2,7 +2,6 @@ import { Gtk } from "ags/gtk3"
|
|||||||
import { createPoll } from "ags/time"
|
import { createPoll } from "ags/time"
|
||||||
import { For } from "ags"
|
import { For } from "ags"
|
||||||
import { shell } from "../lib/utils"
|
import { shell } from "../lib/utils"
|
||||||
import { StatRow } from "./WidgetCard"
|
|
||||||
|
|
||||||
type Limit = {
|
type Limit = {
|
||||||
label: string
|
label: string
|
||||||
@@ -34,9 +33,6 @@ type AgentUsage = {
|
|||||||
plan: string
|
plan: string
|
||||||
statusText: string
|
statusText: string
|
||||||
helpText: string
|
helpText: string
|
||||||
todayPrompts: number
|
|
||||||
todaySessions: number
|
|
||||||
todayTokens: string
|
|
||||||
limits: Limit[]
|
limits: Limit[]
|
||||||
days: DayUsage[]
|
days: DayUsage[]
|
||||||
models: ModelUsage[]
|
models: ModelUsage[]
|
||||||
@@ -48,9 +44,6 @@ const EMPTY_USAGE: AgentUsage = {
|
|||||||
plan: "",
|
plan: "",
|
||||||
statusText: "",
|
statusText: "",
|
||||||
helpText: "",
|
helpText: "",
|
||||||
todayPrompts: 0,
|
|
||||||
todaySessions: 0,
|
|
||||||
todayTokens: "0",
|
|
||||||
limits: [],
|
limits: [],
|
||||||
days: [],
|
days: [],
|
||||||
models: [],
|
models: [],
|
||||||
@@ -82,9 +75,9 @@ function formatResetsIn(resetsAt: string) {
|
|||||||
const hours = Math.floor((minutesLeft % 1440) / 60)
|
const hours = Math.floor((minutesLeft % 1440) / 60)
|
||||||
const minutes = minutesLeft % 60
|
const minutes = minutesLeft % 60
|
||||||
|
|
||||||
if (days > 0) return `resets in ${days}d ${hours}h`
|
if (days > 0) return `Resets in ${days}d ${hours}h`
|
||||||
if (hours > 0) return `resets in ${hours}h ${minutes}m`
|
if (hours > 0) return `Resets in ${hours}h ${minutes}m`
|
||||||
return `resets in ${minutes}m`
|
return `Resets in ${minutes}m`
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatModelName(model: string) {
|
function formatModelName(model: string) {
|
||||||
@@ -94,13 +87,18 @@ function formatModelName(model: string) {
|
|||||||
.replace(/(^| )(\w)/g, (_match, space, letter) => `${space}${letter.toUpperCase()}`)
|
.replace(/(^| )(\w)/g, (_match, space, letter) => `${space}${letter.toUpperCase()}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatPercent(percent: number) {
|
||||||
|
if (percent > 0 && percent < 1) return "<1%"
|
||||||
|
return `${Math.round(percent)}%`
|
||||||
|
}
|
||||||
|
|
||||||
function parseLimits(record: any): Limit[] {
|
function parseLimits(record: any): Limit[] {
|
||||||
if (!Array.isArray(record.limits)) return []
|
if (!Array.isArray(record.limits)) return []
|
||||||
|
|
||||||
return record.limits.map((limit: any) => {
|
return record.limits.map((limit: any) => {
|
||||||
const percent = Number(limit.percent) || 0
|
const percent = Number(limit.percent) || 0
|
||||||
return {
|
return {
|
||||||
label: String(limit.label ?? ""),
|
label: String(limit.label ?? "").replace(/\s*\(.*\)$/, ""),
|
||||||
percent,
|
percent,
|
||||||
fraction: Math.min(1, Math.max(0, percent / 100)),
|
fraction: Math.min(1, Math.max(0, percent / 100)),
|
||||||
resetsIn: formatResetsIn(String(limit.resetsAt ?? "")),
|
resetsIn: formatResetsIn(String(limit.resetsAt ?? "")),
|
||||||
@@ -121,6 +119,8 @@ function parseDays(record: any): DayUsage[] {
|
|||||||
const isToday = date === todayKey
|
const isToday = date === todayKey
|
||||||
const parsedDate = new Date(`${date}T00:00:00`)
|
const parsedDate = new Date(`${date}T00:00:00`)
|
||||||
const weekday = WEEKDAYS[parsedDate.getDay()] ?? date
|
const weekday = WEEKDAYS[parsedDate.getDay()] ?? date
|
||||||
|
const shortDate = `${parsedDate.getMonth() + 1}/${parsedDate.getDate()}`
|
||||||
|
const detail = `${weekday} ${shortDate} - ${formatTokens(tokens)} tokens`
|
||||||
|
|
||||||
return {
|
return {
|
||||||
key: date,
|
key: date,
|
||||||
@@ -129,8 +129,8 @@ function parseDays(record: any): DayUsage[] {
|
|||||||
fraction: tokens / busiestDay,
|
fraction: tokens / busiestDay,
|
||||||
isToday,
|
isToday,
|
||||||
detail: isToday
|
detail: isToday
|
||||||
? `${record.todayPrompts ?? 0} prompts across ${record.todaySessions ?? 0} sessions`
|
? `${detail} - ${record.todayPrompts ?? 0} prompts, ${record.todaySessions ?? 0} sessions`
|
||||||
: date,
|
: detail,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -180,9 +180,6 @@ function parseUsage(stdout: string): AgentUsage {
|
|||||||
plan: String(record.tierLabel ?? ""),
|
plan: String(record.tierLabel ?? ""),
|
||||||
statusText: String(record.usageStatusText ?? ""),
|
statusText: String(record.usageStatusText ?? ""),
|
||||||
helpText: String(record.authHelpText ?? ""),
|
helpText: String(record.authHelpText ?? ""),
|
||||||
todayPrompts: Number(record.todayPrompts) || 0,
|
|
||||||
todaySessions: Number(record.todaySessions) || 0,
|
|
||||||
todayTokens: formatTokens(Number(record.todayTotalTokens) || 0),
|
|
||||||
limits: parseLimits(record),
|
limits: parseLimits(record),
|
||||||
days: parseDays(record),
|
days: parseDays(record),
|
||||||
models: parseModels(record),
|
models: parseModels(record),
|
||||||
@@ -205,36 +202,30 @@ function SectionTitle({ title }: { title: string }) {
|
|||||||
|
|
||||||
function LimitRow({ limit }: { limit: Limit }) {
|
function LimitRow({ limit }: { limit: Limit }) {
|
||||||
return (
|
return (
|
||||||
<box class="agent-limit" vertical spacing={4}>
|
<box vertical spacing={4}>
|
||||||
<box spacing={8}>
|
<box spacing={8}>
|
||||||
<label class="widget-card-label" label={limit.label} xalign={0} halign={Gtk.Align.START} hexpand />
|
<label class="agent-limit-name" label={limit.label} xalign={0} halign={Gtk.Align.START} hexpand />
|
||||||
<label class="widget-card-value" label={`${limit.percent.toFixed(1)}%`} />
|
<label class="agent-limit-percent" label={formatPercent(limit.percent)} />
|
||||||
</box>
|
</box>
|
||||||
<levelbar class="widget-level-bar" value={limit.fraction} />
|
<levelbar class="agent-limit-bar" value={limit.fraction} />
|
||||||
<label class="agent-limit-reset" label={limit.resetsIn} xalign={0} halign={Gtk.Align.START} />
|
<label class="agent-limit-reset" label={limit.resetsIn} xalign={0} halign={Gtk.Align.START} />
|
||||||
</box>
|
</box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function BarRow({ label, tokens, fraction, detail, emphasized }: {
|
function DayRow({ day }: { day: DayUsage }) {
|
||||||
label: string
|
|
||||||
tokens: string
|
|
||||||
fraction: number
|
|
||||||
detail: string
|
|
||||||
emphasized: boolean
|
|
||||||
}) {
|
|
||||||
return (
|
return (
|
||||||
<box class="agent-bar-row" spacing={8} tooltipText={detail}>
|
<box class="agent-day-row" spacing={8} tooltipText={day.detail}>
|
||||||
<label
|
<label
|
||||||
class={emphasized ? "agent-bar-label emphasized" : "agent-bar-label"}
|
class={day.isToday ? "agent-day-label emphasized" : "agent-day-label"}
|
||||||
label={label}
|
label={day.label}
|
||||||
xalign={0}
|
xalign={0}
|
||||||
halign={Gtk.Align.START}
|
halign={Gtk.Align.START}
|
||||||
/>
|
/>
|
||||||
<levelbar class="widget-level-bar agent-bar" value={fraction} hexpand />
|
<levelbar class="agent-day-bar" value={day.fraction} hexpand />
|
||||||
<label
|
<label
|
||||||
class={emphasized ? "agent-bar-value emphasized" : "agent-bar-value"}
|
class={day.isToday ? "agent-day-value emphasized" : "agent-day-value"}
|
||||||
label={tokens}
|
label={day.tokens}
|
||||||
xalign={1}
|
xalign={1}
|
||||||
halign={Gtk.Align.END}
|
halign={Gtk.Align.END}
|
||||||
/>
|
/>
|
||||||
@@ -242,23 +233,37 @@ function BarRow({ label, tokens, fraction, detail, emphasized }: {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ModelRow({ model }: { model: ModelUsage }) {
|
||||||
|
return (
|
||||||
|
<overlay
|
||||||
|
tooltipText={model.detail}
|
||||||
|
overlays={[
|
||||||
|
<box class="agent-model-text" spacing={8}>
|
||||||
|
<label class="agent-model-label" label={model.label} xalign={0} halign={Gtk.Align.START} hexpand />
|
||||||
|
<label class="agent-model-value" label={model.tokens} xalign={1} halign={Gtk.Align.END} />
|
||||||
|
</box>,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<levelbar class="agent-model-bar" value={model.fraction} />
|
||||||
|
</overlay>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function ClaudeUsageCard() {
|
export function ClaudeUsageCard() {
|
||||||
return (
|
return (
|
||||||
<box class="panel widget-card" vertical spacing={10}>
|
<box class="panel widget-card" vertical spacing={10}>
|
||||||
<box class="widget-card-header" spacing={10}>
|
<box spacing={10}>
|
||||||
<box class="widget-icon-badge">
|
<label class="agent-mark" label={""} valign={Gtk.Align.CENTER} />
|
||||||
<label label={""} hexpand vexpand halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER} />
|
<box vertical valign={Gtk.Align.CENTER}>
|
||||||
</box>
|
|
||||||
<box vertical hexpand>
|
|
||||||
<label
|
<label
|
||||||
class="widget-card-title"
|
class="agent-name"
|
||||||
label={usage.as((u) => u.name)}
|
label={usage.as((u) => u.name)}
|
||||||
xalign={0}
|
xalign={0}
|
||||||
halign={Gtk.Align.START}
|
halign={Gtk.Align.START}
|
||||||
/>
|
/>
|
||||||
<label
|
<label
|
||||||
class="agent-plan"
|
class="agent-plan"
|
||||||
label={usage.as((u) => u.plan)}
|
label={usage.as((u) => u.plan.toUpperCase())}
|
||||||
visible={usage.as((u) => u.plan.length > 0)}
|
visible={usage.as((u) => u.plan.length > 0)}
|
||||||
xalign={0}
|
xalign={0}
|
||||||
halign={Gtk.Align.START}
|
halign={Gtk.Align.START}
|
||||||
@@ -286,47 +291,24 @@ export function ClaudeUsageCard() {
|
|||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
|
|
||||||
<box vertical spacing={8} visible={usage.as((u) => u.limits.length > 0)}>
|
<box vertical spacing={10} visible={usage.as((u) => u.limits.length > 0)}>
|
||||||
<SectionTitle title="Limits" />
|
<SectionTitle title="LIMITS" />
|
||||||
<For each={usage.as((u) => u.limits)} id={(limit: Limit) => limit.label}>
|
<For each={usage.as((u) => u.limits)} id={(limit: Limit) => limit.label}>
|
||||||
{(limit: Limit) => <LimitRow limit={limit} />}
|
{(limit: Limit) => <LimitRow limit={limit} />}
|
||||||
</For>
|
</For>
|
||||||
</box>
|
</box>
|
||||||
|
|
||||||
<box vertical spacing={8} visible={usage.as((u) => u.ready)}>
|
|
||||||
<SectionTitle title="Today" />
|
|
||||||
<StatRow icon={""} label="Tokens" value={usage.as((u) => u.todayTokens)} />
|
|
||||||
<StatRow icon={""} label="Prompts" value={usage.as((u) => `${u.todayPrompts}`)} />
|
|
||||||
<StatRow icon={""} label="Sessions" value={usage.as((u) => `${u.todaySessions}`)} />
|
|
||||||
</box>
|
|
||||||
|
|
||||||
<box vertical spacing={6} visible={usage.as((u) => u.days.length > 0)}>
|
<box vertical spacing={6} visible={usage.as((u) => u.days.length > 0)}>
|
||||||
<SectionTitle title="Tokens by day" />
|
<SectionTitle title="TOKENS BY DAY" />
|
||||||
<For each={usage.as((u) => u.days)} id={(day: DayUsage) => day.key}>
|
<For each={usage.as((u) => u.days)} id={(day: DayUsage) => day.key}>
|
||||||
{(day: DayUsage) => (
|
{(day: DayUsage) => <DayRow day={day} />}
|
||||||
<BarRow
|
|
||||||
label={day.label}
|
|
||||||
tokens={day.tokens}
|
|
||||||
fraction={day.fraction}
|
|
||||||
detail={day.detail}
|
|
||||||
emphasized={day.isToday}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
</For>
|
||||||
</box>
|
</box>
|
||||||
|
|
||||||
<box vertical spacing={6} visible={usage.as((u) => u.models.length > 0)}>
|
<box vertical spacing={4} visible={usage.as((u) => u.models.length > 0)}>
|
||||||
<SectionTitle title="Tokens by model" />
|
<SectionTitle title="TOKENS BY MODEL" />
|
||||||
<For each={usage.as((u) => u.models)} id={(model: ModelUsage) => model.key}>
|
<For each={usage.as((u) => u.models)} id={(model: ModelUsage) => model.key}>
|
||||||
{(model: ModelUsage) => (
|
{(model: ModelUsage) => <ModelRow model={model} />}
|
||||||
<BarRow
|
|
||||||
label={model.label}
|
|
||||||
tokens={model.tokens}
|
|
||||||
fraction={model.fraction}
|
|
||||||
detail={model.detail}
|
|
||||||
emphasized={false}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</For>
|
</For>
|
||||||
</box>
|
</box>
|
||||||
</box>
|
</box>
|
||||||
|
|||||||
Reference in New Issue
Block a user