Refresh the look and layout of the model-usage plugin
This commit is contained in:
@@ -26,23 +26,22 @@ Item {
|
||||
}
|
||||
|
||||
property var providers: [claudeProvider, codexProvider]
|
||||
|
||||
// A subscription earns a place in the panel by being both switched on in
|
||||
// settings and actually present on this machine — nobody wants a Codex tab
|
||||
// full of zeroes on a box that has never run Codex.
|
||||
property var enabledProviders: {
|
||||
var rev = syncRevision
|
||||
var running = syncRunning
|
||||
var result = []
|
||||
if (claudeProvider.enabled) result.push(displayProvider(claudeProvider))
|
||||
if (codexProvider.enabled) result.push(displayProvider(codexProvider))
|
||||
if (claudeProvider.enabled && claudeProvider.installed) result.push(displayProvider(claudeProvider))
|
||||
if (codexProvider.enabled && codexProvider.installed) result.push(displayProvider(codexProvider))
|
||||
return result
|
||||
}
|
||||
|
||||
property int activeIndex: 0
|
||||
property var activeProvider: enabledProviders.length > 0 ? enabledProviders[Math.min(activeIndex, enabledProviders.length - 1)] : null
|
||||
property bool refreshing: claudeProvider.refreshing || codexProvider.refreshing || syncRunning
|
||||
property double aggregateUpdatedAtMs: aggregateData && aggregateData.updatedAtMs ? Number(aggregateData.updatedAtMs) : 0
|
||||
property double lastRefreshedAtMs: Math.max(aggregateUpdatedAtMs, claudeProvider.lastRefreshedAtMs || 0, codexProvider.lastRefreshedAtMs || 0)
|
||||
property string barDisplayMode: setting("barDisplayMode", "active")
|
||||
property int barCycleIntervalSec: Math.max(1, Number(setting("barCycleIntervalSec", 5)))
|
||||
property string barMetric: setting("barMetric", "prompts")
|
||||
property int refreshIntervalSec: Math.max(30, Number(setting("refreshIntervalSec", 900)))
|
||||
|
||||
property var syncModeSetting: setting("syncMode", setting("syncEnabled", false))
|
||||
@@ -75,13 +74,6 @@ Item {
|
||||
return value === undefined || value === null ? fallback : value
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: root.barCycleIntervalSec * 1000
|
||||
running: root.barDisplayMode === "cycle" && root.enabledProviders.length > 1
|
||||
repeat: true
|
||||
onTriggered: root.activeIndex = (root.activeIndex + 1) % root.enabledProviders.length
|
||||
}
|
||||
|
||||
Timer {
|
||||
interval: root.refreshIntervalSec * 1000
|
||||
running: true
|
||||
@@ -147,10 +139,6 @@ Item {
|
||||
onLoaded: root.detectedHostname = String(text() || "").trim()
|
||||
}
|
||||
|
||||
onEnabledProvidersChanged: {
|
||||
if (enabledProviders.length === 0 || activeIndex >= enabledProviders.length) activeIndex = 0
|
||||
}
|
||||
|
||||
function providerEnabled(id) {
|
||||
if (!settings || !settings.providers || !settings.providers[id]) return id === "claude" || id === "codex"
|
||||
return settings.providers[id].enabled !== false
|
||||
@@ -355,6 +343,8 @@ Item {
|
||||
recentByDay: recentByDay,
|
||||
totalPrompts: 0,
|
||||
totalSessions: 0,
|
||||
activeDays: 0,
|
||||
activeDates: ({}),
|
||||
modelUsage: ({}),
|
||||
devices: ({})
|
||||
}
|
||||
@@ -378,6 +368,12 @@ Item {
|
||||
acc.todayTotalTokens += numberValue(stats.todayTotalTokens)
|
||||
acc.totalPrompts += numberValue(stats.totalPrompts)
|
||||
acc.totalSessions += numberValue(stats.totalSessions)
|
||||
// Active days overlap between machines, so union the dates rather than
|
||||
// summing counts. Snapshots written before activeDates existed only
|
||||
// carry a count; the widest one stands in for them.
|
||||
var activeDates = Array.isArray(stats.activeDates) ? stats.activeDates : []
|
||||
for (var ad = 0; ad < activeDates.length; ad++) acc.activeDates[String(activeDates[ad])] = true
|
||||
acc.activeDays = Math.max(acc.activeDays, numberValue(stats.activeDays))
|
||||
addObjectNumbers(acc.todayTokensByModel, stats.todayTokensByModel || {})
|
||||
|
||||
var recent = Array.isArray(stats.recentDays) ? stats.recentDays : []
|
||||
@@ -418,6 +414,7 @@ Item {
|
||||
recentDays: recentDays,
|
||||
totalPrompts: acc.totalPrompts,
|
||||
totalSessions: acc.totalSessions,
|
||||
activeDays: Math.max(acc.activeDays, Object.keys(acc.activeDates).length),
|
||||
modelUsage: acc.modelUsage,
|
||||
deviceCount: providerDevices.length,
|
||||
devices: providerDevices
|
||||
@@ -447,6 +444,8 @@ Item {
|
||||
recentDays: cloneValue(provider.recentDays, []),
|
||||
totalPrompts: numberValue(provider.totalPrompts),
|
||||
totalSessions: numberValue(provider.totalSessions),
|
||||
activeDays: numberValue(provider.activeDays),
|
||||
activeDates: cloneValue(provider.activeDates, []),
|
||||
modelUsage: cloneValue(provider.modelUsage, ({}))
|
||||
}
|
||||
}
|
||||
@@ -502,6 +501,7 @@ Item {
|
||||
recentDays: synced ? (stats.recentDays || []) : provider.recentDays,
|
||||
totalPrompts: synced ? numberValue(stats.totalPrompts) : provider.totalPrompts,
|
||||
totalSessions: synced ? numberValue(stats.totalSessions) : provider.totalSessions,
|
||||
activeDays: synced ? numberValue(stats.activeDays) : provider.activeDays,
|
||||
modelUsage: synced ? (stats.modelUsage || ({})) : provider.modelUsage,
|
||||
hasLocalStats: synced ? (stats.hasLocalStats !== false) : provider.hasLocalStats,
|
||||
|
||||
@@ -531,12 +531,34 @@ Item {
|
||||
return String(n)
|
||||
}
|
||||
|
||||
function modelWordCase(word) {
|
||||
if (word === "gpt") return "GPT"
|
||||
return word.charAt(0).toUpperCase() + word.slice(1)
|
||||
}
|
||||
|
||||
// Model ids arrive hyphenated with the version split across segments
|
||||
// (`claude-opus-4-8`, `gpt-5.6-sol`). Rejoin the numeric run into one
|
||||
// version and title-case the words around it.
|
||||
function friendlyModelName(id) {
|
||||
if (!id) return "Unknown"
|
||||
var name = String(id).replace(/^claude-/, "").replace(/-\d{8}$/, "")
|
||||
var parts = name.split("-")
|
||||
if (parts.length >= 3) return parts[0].charAt(0).toUpperCase() + parts[0].slice(1) + " " + parts[1] + "." + parts[2]
|
||||
if (parts.length === 2) return parts[0].charAt(0).toUpperCase() + parts[0].slice(1) + " " + parts[1]
|
||||
return name.charAt(0).toUpperCase() + name.slice(1)
|
||||
var words = []
|
||||
var version = []
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i]
|
||||
if (part === "") continue
|
||||
if (/^\d/.test(part)) {
|
||||
version.push(part)
|
||||
continue
|
||||
}
|
||||
if (version.length > 0) {
|
||||
words.push(version.join("."))
|
||||
version = []
|
||||
}
|
||||
words.push(modelWordCase(part))
|
||||
}
|
||||
if (version.length > 0) words.push(version.join("."))
|
||||
return words.length > 0 ? words.join(" ") : "Unknown"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user