Show recovery guidance when paused usage has no cache

This commit is contained in:
David Heinemeier Hansson committed 2026-10-04 07:10:41 -04:00
1 parent 6809987892
commit 7f91a8d49e
2 files changed
+46

No files matched your search

+38
View File
@@ -422,6 +422,10 @@ Panel {
return status !== "" && status !== "Limits paused" && !needsSignIn(item) ? status : ""
}
function pausedWithoutLimits(item) {
return !!item && item.usageStatusText === "Limits paused" && limitWindows(item).length === 0
}
// Sign an account that's already here in again, following along in the
// add view just like adding one.
function signInAgain(p, account) {
@@ -1343,6 +1347,12 @@ Panel {
wrapMode: Text.WordWrap
}
UnavailableUsage {
visible: !section.multi && root.pausedWithoutLimits(section.provider)
width: parent.width
record: section.provider
}
Column {
visible: !section.multi && section.windows.length > 0
width: parent.width
@@ -1449,6 +1459,11 @@ Panel {
width: parent.width
spacing: Style.space(12)
UnavailableUsage {
width: parent.width
record: accountBlock.modelData
}
Repeater {
model: root.displayWindows({ limits: accountBlock.modelData.limits || [] })
@@ -1833,6 +1848,29 @@ Panel {
}
}
// With no measured windows, leave a place to discover how to get usage.
component UnavailableUsage: Item {
id: unavailable
property var record: null
visible: root.pausedWithoutLimits(record)
implicitHeight: unavailableLabel.implicitHeight
Text {
id: unavailableLabel
text: "Usage unavailable"
color: root.dim
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
}
HoverHandler { id: unavailableHover }
PanelToolTip {
visible: unavailableHover.hovered && unavailable.visible
text: unavailable.record ? String(unavailable.record.authHelpText || "Usage has not been updated yet.") : ""
}
}
// One line per limit window: title, meter, percentage, and reset. A
// model-scoped allowance on the same clock ("Fable" on Weekly) is a marker
// on this row's meter, named in the row's tooltip.
@@ -328,6 +328,14 @@ const start = source.indexOf('function windowIsLong')
const end = source.indexOf('// The window that decides')
assert(start > 0 && end > start, 'agents panel exposes its limit-window helpers')
eval(source.slice(start, end).replaceAll('root.nowMs', 'panelRoot.nowMs'))
eval(source.slice(source.indexOf('function needsSignIn'), source.indexOf('// Sign an account')))
const paused = { usageStatusText: 'Limits paused', limits: [] }
assertEqual(pausedWithoutLimits(paused), true, 'paused usage without a cache shows a recovery placeholder')
assertEqual(otherTrouble(paused), '', 'paused usage never puts the confusing status in the header')
assertEqual(pausedWithoutLimits({ ...paused, limits: [{ label: 'Session (5-hour)', percent: 0, resetsAt: '' }] }), false, 'cached usage replaces the recovery placeholder')
assertEqual(pausedWithoutLimits({ usageStatusText: 'Sign-in expired', limits: [] }), false, 'expired sign-ins retain their sign-in action')
assertEqual(pausedWithoutLimits(null), false, 'missing records do not show a paused-usage placeholder')
assertDeepEqual(
limitWindows({ limits: [