From 1f954b736814602632a9e4cbd2bfe03b8e0bca94 Mon Sep 17 00:00:00 2001 From: Callan Barrett Date: Tue, 10 Feb 2026 21:35:16 +0800 Subject: [PATCH] fix: disable pro-only toggles when user lacks pro access Launch on scan and shake to launch toggles could be visually enabled without pro access. Now they show as disabled and open the purchase modal when tapped. Adds regression tests for the disabled state. --- .../integration/settings-readers.test.tsx | 30 +++++++++++++++++-- src/routes/settings.readers.tsx | 7 ++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/__tests__/integration/settings-readers.test.tsx b/src/__tests__/integration/settings-readers.test.tsx index 1e425e9..38521f5 100644 --- a/src/__tests__/integration/settings-readers.test.tsx +++ b/src/__tests__/integration/settings-readers.test.tsx @@ -255,9 +255,22 @@ describe("Settings Readers Integration", () => { expect(launchOnScanLabel).toBeInTheDocument(); }); + it("should disable launch on scan toggle without pro access", () => { + usePreferencesStore.setState({ launcherAccess: false }); + renderComponent(); + + const toggle = screen.getByRole("checkbox", { + name: /settings.readers.launchOnScan/i, + }); + expect(toggle).toBeDisabled(); + }); + it("should toggle launch on scan setting", async () => { const user = userEvent.setup(); - usePreferencesStore.setState({ launchOnScan: false }); + usePreferencesStore.setState({ + launchOnScan: false, + launcherAccess: true, + }); renderComponent(); @@ -351,7 +364,10 @@ describe("Settings Readers Integration", () => { it("should enable shake when toggle is clicked", async () => { const user = userEvent.setup(); - usePreferencesStore.setState({ shakeEnabled: false }); + usePreferencesStore.setState({ + shakeEnabled: false, + launcherAccess: true, + }); renderComponent(); @@ -363,6 +379,16 @@ describe("Settings Readers Integration", () => { expect(usePreferencesStore.getState().shakeEnabled).toBe(true); }); + it("should disable shake toggle without pro access", () => { + usePreferencesStore.setState({ launcherAccess: false }); + renderComponent(); + + const toggle = screen.getByRole("checkbox", { + name: /settings.readers.shakeToLaunch/i, + }); + expect(toggle).toBeDisabled(); + }); + it("should disable shake toggle when disconnected", () => { useStatusStore.setState({ connected: false, diff --git a/src/routes/settings.readers.tsx b/src/routes/settings.readers.tsx index d22cd3e..68981c2 100644 --- a/src/routes/settings.readers.tsx +++ b/src/routes/settings.readers.tsx @@ -315,6 +315,8 @@ function ReadersSettings() { } value={launchOnScan} setValue={setLaunchOnScan} + disabled={!launcherAccess} + onDisabledClick={() => setProPurchaseModalOpen(true)} /> )} @@ -355,7 +357,10 @@ function ReadersSettings() { } value={shakeEnabled} setValue={setShakeEnabled} - disabled={!connected} + disabled={!connected || !launcherAccess} + onDisabledClick={ + !launcherAccess ? () => setProPurchaseModalOpen(true) : undefined + } loading={isLoading} /> )}