mirror of
https://github.com/kuhyx/steam-backlog-enforcer.git
synced 2026-11-11 12:07:32 +01:00
Say "masked" only when launchers really are
The cutoff badge asserted "launchers are masked" from `blocked` alone, but the two can disagree: the total-block branch of `playtime_tick` calls `reconcile(should_block=False)` and leaves `blocked_at` set, so the mounts are gone while the day still reads blocked. The panel already fetches `rules.masked_launchers` for its "Masked now" row, so the badge now reads the same live count instead of inferring one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9062fa8c10
commit
08aa5c42f8
@ -40,7 +40,7 @@ export function BudgetPanel({ demo }: Props) {
|
||||
<p className="error">{data.error ?? 'Budget state unavailable.'}</p>
|
||||
</section>
|
||||
) : (
|
||||
<BudgetTodayCard today={data.today} />
|
||||
<BudgetTodayCard today={data.today} maskedCount={data.rules.masked_launchers.length} />
|
||||
)}
|
||||
<BudgetLiveCard session={data.session} />
|
||||
<BudgetHistoryChart days={data.history} budgetSeconds={data.rules.budget_seconds} />
|
||||
|
||||
@ -5,7 +5,7 @@ import { BudgetTodayCard } from './BudgetTodayCard'
|
||||
|
||||
describe('BudgetTodayCard', () => {
|
||||
it('shows remaining time, usage and the next warning', () => {
|
||||
render(<BudgetTodayCard today={makeBudgetToday()} />)
|
||||
render(<BudgetTodayCard today={makeBudgetToday()} maskedCount={0} />)
|
||||
expect(screen.getByText('7h 0m')).toBeInTheDocument()
|
||||
expect(screen.getByText(/1h 0m of 8h 0m used/)).toBeInTheDocument()
|
||||
expect(screen.getByText(/Next warning at 1h 0m remaining/)).toBeInTheDocument()
|
||||
@ -16,6 +16,7 @@ describe('BudgetTodayCard', () => {
|
||||
render(
|
||||
<BudgetTodayCard
|
||||
today={makeBudgetToday({ seconds_remaining: 900, warned_seconds: [3600, 1800] })}
|
||||
maskedCount={0}
|
||||
/>,
|
||||
)
|
||||
expect(document.querySelector('.budget-meter--warn')).not.toBeNull()
|
||||
@ -28,26 +29,33 @@ describe('BudgetTodayCard', () => {
|
||||
next_warning_seconds: null,
|
||||
warned_seconds: [3600, 1800, 600, 300],
|
||||
})}
|
||||
maskedCount={0}
|
||||
/>,
|
||||
)
|
||||
expect(screen.getByText(/No further warnings today/)).toBeInTheDocument()
|
||||
expect(document.querySelector('.budget-meter--warn')).not.toBeNull()
|
||||
})
|
||||
|
||||
const blockedToday = () =>
|
||||
makeBudgetToday({
|
||||
blocked: true,
|
||||
blocked_at: 1,
|
||||
seconds_used: 28800,
|
||||
seconds_remaining: 0,
|
||||
fraction_used: 1,
|
||||
next_warning_seconds: null,
|
||||
})
|
||||
|
||||
it('shows the cutoff badge when blocked', () => {
|
||||
render(
|
||||
<BudgetTodayCard
|
||||
today={makeBudgetToday({
|
||||
blocked: true,
|
||||
blocked_at: 1,
|
||||
seconds_used: 28800,
|
||||
seconds_remaining: 0,
|
||||
fraction_used: 1,
|
||||
next_warning_seconds: null,
|
||||
})}
|
||||
/>,
|
||||
)
|
||||
expect(screen.getByText(/Cutoff engaged/)).toBeInTheDocument()
|
||||
render(<BudgetTodayCard today={blockedToday()} maskedCount={2} />)
|
||||
expect(screen.getByText(/Cutoff engaged — launchers are masked/)).toBeInTheDocument()
|
||||
expect(document.querySelector('.budget-meter--blocked')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('does not claim a mask that is not in place', () => {
|
||||
render(<BudgetTodayCard today={blockedToday()} maskedCount={0} />)
|
||||
expect(
|
||||
screen.getByText(/Cutoff engaged — launchers are not currently masked/),
|
||||
).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
@ -3,6 +3,7 @@ import type { BudgetToday } from '../types'
|
||||
|
||||
interface Props {
|
||||
today: BudgetToday
|
||||
maskedCount: number
|
||||
}
|
||||
|
||||
/** Which colour the meter takes: normal, into the warning band, or spent.
|
||||
@ -17,7 +18,7 @@ function meterState(today: BudgetToday): string {
|
||||
return today.warned_seconds.length > 0 ? 'warn' : 'ok'
|
||||
}
|
||||
|
||||
export function BudgetTodayCard({ today }: Props) {
|
||||
export function BudgetTodayCard({ today, maskedCount }: Props) {
|
||||
return (
|
||||
<section className="budget-today">
|
||||
<h2>Today</h2>
|
||||
@ -39,7 +40,14 @@ export function BudgetTodayCard({ today }: Props) {
|
||||
<p className="hint">
|
||||
{today.blocked ? (
|
||||
<span className="budget-badge budget-badge--blocked">
|
||||
Cutoff engaged — launchers are masked
|
||||
{/* Read the live mount count rather than inferring it from
|
||||
`blocked`: the total-block branch releases every mount while
|
||||
leaving `blocked_at` set, so the two can genuinely disagree —
|
||||
and a badge claiming a mask that is not there is the one thing
|
||||
this panel must never do. */}
|
||||
{maskedCount > 0
|
||||
? 'Cutoff engaged — launchers are masked'
|
||||
: 'Cutoff engaged — launchers are not currently masked'}
|
||||
</span>
|
||||
) : today.next_warning_seconds === null ? (
|
||||
'No further warnings today.'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user