| author | |
| committer | |
| log | 05d404210058d714cfef902517fc20ad66b82339 |
| tree | bd998c99ca7002a2463b4f3fe9721037b79cc17c |
| parent | 2ebc9fa4ed24e389eef24039f27c73ae6633858f |
| signature | Signed by PGP key B5690EEEBB952194 |
Co-authored-by: Claude Code <noreply@anthropic.com>3 files changed, 13 insertions(+), 11 deletions(-)
apps/mobile/src/features/usage/UsageRouteScreen.tsx+3-1| ... | ... | @@ -67,7 +67,9 @@ const CHART_HEIGHT = 180; |
| 67 | 67 | export function UsageRouteScreen() { |
| 68 | 68 | const navigation = useNavigation(); |
| 69 | 69 | const insets = useSafeAreaInsets(); |
| 70 | const [tab, setTab] = useState<UsageTab>("usage"); | |
| 70 | // Limits first: remaining quota and reset time are what most people open | |
| 71 | // the screen for. | |
| 72 | const [tab, setTab] = useState<UsageTab>("limits"); | |
| 71 | 73 | const [windowSelection, setWindowSelection] = useState(() => ({ |
| 72 | 74 | days: 30, |
| 73 | 75 | window: makeWindow(30), |
apps/web/src/components/usage/usagePagePreferences.test.ts+3-3| ... | ... | @@ -25,7 +25,7 @@ afterEach(() => { |
| 25 | 25 | |
| 26 | 26 | describe("Usage page preferences", () => { |
| 27 | 27 | it("uses defaults when no preference has been saved", () => { |
| 28 | expect(readUsagePagePreferences()).toEqual({ metric: "cost", windowDays: 30 }); | |
| 28 | expect(readUsagePagePreferences()).toEqual({ metric: "limits", windowDays: 30 }); | |
| 29 | 29 | }); |
| 30 | 30 | |
| 31 | 31 | it.each([1, 7, 30, 90] as const)("round-trips every metric with a %i-day range", (windowDays) => { |
| ... | ... | @@ -41,7 +41,7 @@ describe("Usage page preferences", () => { |
| 41 | 41 | '{"metric":"cost","windowDays":365}', |
| 42 | 42 | ])("replaces invalid preferences on the next save: %s", (value) => { |
| 43 | 43 | values.set(key, value); |
| 44 | expect(readUsagePagePreferences()).toEqual({ metric: "cost", windowDays: 30 }); | |
| 44 | expect(readUsagePagePreferences()).toEqual({ metric: "limits", windowDays: 30 }); | |
| 45 | 45 | saveUsagePagePreferences({ metric: "tokens", windowDays: 7 }); |
| 46 | 46 | expect(readUsagePagePreferences()).toEqual({ metric: "tokens", windowDays: 7 }); |
| 47 | 47 | }); |
| ... | ... | @@ -64,7 +64,7 @@ describe("Usage page preferences", () => { |
| 64 | 64 | throw new Error("SecurityError"); |
| 65 | 65 | }, |
| 66 | 66 | }); |
| 67 | expect(readUsagePagePreferences()).toEqual({ metric: "cost", windowDays: 30 }); | |
| 67 | expect(readUsagePagePreferences()).toEqual({ metric: "limits", windowDays: 30 }); | |
| 68 | 68 | expect(() => saveUsagePagePreferences({ metric: "tokens", windowDays: 7 })).not.toThrow(); |
| 69 | 69 | }); |
| 70 | 70 | }); |
apps/web/src/components/usage/usagePagePreferences.ts+7-7| ... | ... | @@ -9,17 +9,17 @@ const UsagePagePreferencesSchema = Schema.Struct({ |
| 9 | 9 | }); |
| 10 | 10 | export type UsagePagePreferences = typeof UsagePagePreferencesSchema.Type; |
| 11 | 11 | |
| 12 | // Limits is what most people open the page for (how much subscription quota is | |
| 13 | // left, and when it resets), so it is the first-visit default; the last picked | |
| 14 | // tab sticks after that. | |
| 15 | const DEFAULT_PREFERENCES: UsagePagePreferences = { metric: "limits", windowDays: 30 }; | |
| 16 | ||
| 12 | 17 | export function readUsagePagePreferences(): UsagePagePreferences { |
| 13 | 18 | try { |
| 14 | return ( | |
| 15 | getLocalStorageItem(STORAGE_KEY, UsagePagePreferencesSchema) ?? { | |
| 16 | metric: "cost", | |
| 17 | windowDays: 30, | |
| 18 | } | |
| 19 | ); | |
| 19 | return getLocalStorageItem(STORAGE_KEY, UsagePagePreferencesSchema) ?? DEFAULT_PREFERENCES; | |
| 20 | 20 | } catch (error) { |
| 21 | 21 | console.error("Could not read Usage page preferences.", error); |
| 22 | return { metric: "cost", windowDays: 30 }; | |
| 22 | return DEFAULT_PREFERENCES; | |
| 23 | 23 | } |
| 24 | 24 | } |
| 25 | 25 |