| 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,7 +67,9 @@ const CHART_HEIGHT = 180; |
| 67 | export function UsageRouteScreen() { | 67 | export function UsageRouteScreen() { |
| 68 | const navigation = useNavigation(); | 68 | const navigation = useNavigation(); |
| 69 | const insets = useSafeAreaInsets(); | 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 | const [windowSelection, setWindowSelection] = useState(() => ({ | 73 | const [windowSelection, setWindowSelection] = useState(() => ({ |
| 72 | days: 30, | 74 | days: 30, |
| 73 | window: makeWindow(30), | 75 | window: makeWindow(30), |
apps/web/src/components/usage/usagePagePreferences.test.ts+3-3| ... | @@ -25,7 +25,7 @@ afterEach(() => { | ... | @@ -25,7 +25,7 @@ afterEach(() => { |
| 25 | 25 | ||
| 26 | describe("Usage page preferences", () => { | 26 | describe("Usage page preferences", () => { |
| 27 | it("uses defaults when no preference has been saved", () => { | 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 | it.each([1, 7, 30, 90] as const)("round-trips every metric with a %i-day range", (windowDays) => { | 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,7 +41,7 @@ describe("Usage page preferences", () => { |
| 41 | '{"metric":"cost","windowDays":365}', | 41 | '{"metric":"cost","windowDays":365}', |
| 42 | ])("replaces invalid preferences on the next save: %s", (value) => { | 42 | ])("replaces invalid preferences on the next save: %s", (value) => { |
| 43 | values.set(key, value); | 43 | values.set(key, value); |
| 44 | expect(readUsagePagePreferences()).toEqual({ metric: "cost", windowDays: 30 }); | 44 | expect(readUsagePagePreferences()).toEqual({ metric: "limits", windowDays: 30 }); |
| 45 | saveUsagePagePreferences({ metric: "tokens", windowDays: 7 }); | 45 | saveUsagePagePreferences({ metric: "tokens", windowDays: 7 }); |
| 46 | expect(readUsagePagePreferences()).toEqual({ metric: "tokens", windowDays: 7 }); | 46 | expect(readUsagePagePreferences()).toEqual({ metric: "tokens", windowDays: 7 }); |
| 47 | }); | 47 | }); |
| ... | @@ -64,7 +64,7 @@ describe("Usage page preferences", () => { | ... | @@ -64,7 +64,7 @@ describe("Usage page preferences", () => { |
| 64 | throw new Error("SecurityError"); | 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 | expect(() => saveUsagePagePreferences({ metric: "tokens", windowDays: 7 })).not.toThrow(); | 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,17 +9,17 @@ const UsagePagePreferencesSchema = Schema.Struct({ |
| 9 | }); | 9 | }); |
| 10 | export type UsagePagePreferences = typeof UsagePagePreferencesSchema.Type; | 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 | export function readUsagePagePreferences(): UsagePagePreferences { | 17 | export function readUsagePagePreferences(): UsagePagePreferences { |
| 13 | try { | 18 | try { |
| 14 | return ( | 19 | return getLocalStorageItem(STORAGE_KEY, UsagePagePreferencesSchema) ?? DEFAULT_PREFERENCES; |
| 15 | getLocalStorageItem(STORAGE_KEY, UsagePagePreferencesSchema) ?? { | ||
| 16 | metric: "cost", | ||
| 17 | windowDays: 30, | ||
| 18 | } | ||
| 19 | ); | ||
| 20 | } catch (error) { | 20 | } catch (error) { |
| 21 | console.error("Could not read Usage page preferences.", error); | 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 |