mirror of
https://github.com/stablyai/orca.git
synced 2026-10-20 00:03:45 +00:00
* feat(mobile): show usage reset countdown on accounts screen
Surface the rate-limit reset time ("5h resets in 3h 54m · 7d resets in
6d 7h") under the usage bars on the mobile accounts screen, matching the
desktop status-bar tooltip copy. The resetsAt timestamps already arrive
in the accounts.subscribe snapshot; this only adds the presentation.
Claude-Session: https://claude.ai/code/session_01FvjvCsc9QoyQALqvxkvDqQ
* docs(mobile): JSDoc for new usage reset selectors
Claude-Session: https://claude.ai/code/session_01FvjvCsc9QoyQALqvxkvDqQ
* refactor(mobile): per-bar reset countdown instead of combined line
Drop the redundant "5h/7d" prefixes — each countdown now renders under
its own bar ("Resets in 3h 54m"), matching the desktop tooltip copy
exactly.
Claude-Session: https://claude.ai/code/session_01FvjvCsc9QoyQALqvxkvDqQ
* Extract shared reset-countdown formatter for desktop and mobile
- Move duration/countdown formatting out of tooltip.tsx into
src/shared/rate-limit-reset-format.ts so mobile's account-usage-state
can reuse it instead of a duplicated copy (with tests).
- Re-export formatResetCountdown from tooltip.tsx to avoid touching
existing import paths.
- Resend the pairing deep link once more in start-emulator.mjs since
the first can arrive before the Expo app's JS router is ready.
---------
Co-authored-by: kaynan <kaynan.camargo@terceiro-sky.com.br>
Co-authored-by: Jinjing <6427696+AmethystLiang@users.noreply.github.com>
33 lines
1.2 KiB
TypeScript
33 lines
1.2 KiB
TypeScript
// Why: shared by the desktop status-bar tooltip and the mobile accounts screen
|
|
// so rate-limit reset/expiry countdown copy stays identical across surfaces.
|
|
// Pure (no platform imports) — safe to bundle in both the renderer and mobile.
|
|
|
|
/**
|
|
* Compact human duration for a rate-limit window, flooring to whole units:
|
|
* "47m", "3h 54m", "6d 7h". Returns "now" for a non-positive delta so callers
|
|
* can special-case the "already reset" copy.
|
|
*/
|
|
export function formatResetDuration(ms: number): string {
|
|
if (ms <= 0) {
|
|
return 'now'
|
|
}
|
|
const totalMins = Math.floor(ms / 60_000)
|
|
if (totalMins < 60) {
|
|
return `${totalMins}m`
|
|
}
|
|
const hours = Math.floor(totalMins / 60)
|
|
const mins = totalMins % 60
|
|
if (hours >= 24) {
|
|
const days = Math.floor(hours / 24)
|
|
const remHours = hours % 24
|
|
return remHours > 0 ? `${days}d ${remHours}h` : `${days}d`
|
|
}
|
|
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`
|
|
}
|
|
|
|
/** "Resets in 3h 54m" / "Resets now" for a window's time-until-reset (ms). */
|
|
export function formatResetCountdown(ms: number): string {
|
|
const duration = formatResetDuration(ms)
|
|
return duration === 'now' ? 'Resets now' : `Resets in ${duration}`
|
|
}
|