From ca5a68eee918f5674173fd2944fa5529d8be8cba Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 21:16:13 +0000 Subject: [PATCH 1/3] feat: Add approved version check for API Management button on iOS/Android - API Management button now follows same version check logic as pricing routes - On iOS/Android: only shows if app version is approved by server - On desktop/web: always shows (no restrictions) - Fetches products with version to check is_available status - Resolves #419 Co-authored-by: Anthony --- frontend/src/components/AccountMenu.tsx | 43 +++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/AccountMenu.tsx b/frontend/src/components/AccountMenu.tsx index a8bdb3236..611a9af43 100644 --- a/frontend/src/components/AccountMenu.tsx +++ b/frontend/src/components/AccountMenu.tsx @@ -13,7 +13,7 @@ import { FileText, ChevronLeft } from "lucide-react"; -import { isMobile, isTauri } from "@/utils/platform"; +import { isMobile, isTauri, isIOS, isAndroid } from "@/utils/platform"; import { Button } from "@/components/ui/button"; import { @@ -51,6 +51,7 @@ import { useState } from "react"; import type { TeamStatus } from "@/types/team"; import { TeamManagementDialog } from "@/components/team/TeamManagementDialog"; import { ApiKeyManagementDialog } from "@/components/apikeys/ApiKeyManagementDialog"; +import packageJson from "../../package.json"; function ConfirmDeleteDialog() { const { clearHistory } = useLocalState(); @@ -129,10 +130,48 @@ export function AccountMenu() { enabled: isTeamPlan && !!os.auth.user && !!billingStatus }); + // Fetch products with version check for mobile platforms to determine API Management availability + const isIOSPlatform = isIOS(); + const isAndroidPlatform = isAndroid(); + const { data: products } = useQuery({ + queryKey: ["products", isIOSPlatform, isAndroidPlatform], + queryFn: async () => { + try { + const billingService = getBillingService(); + // Send version for mobile builds (iOS/Android need it for App Store restrictions) + if (isIOSPlatform || isAndroidPlatform) { + const version = `v${packageJson.version}`; + return await billingService.getProducts(version); + } + return await billingService.getProducts(); + } catch (error) { + console.error("Error fetching products for version check:", error); + return null; + } + }, + enabled: isIOSPlatform || isAndroidPlatform + }); + // Show alert badge if user has team plan but hasn't created team yet const showTeamSetupAlert = isTeamPlan && teamStatus?.has_team_subscription && !teamStatus?.team_created; + // Determine if API Management should be shown + // On desktop/web: always show + // On iOS/Android: only show if version is approved (at least one product is available) + const showApiManagement = (() => { + if (!isMobile()) { + return true; // Always show on desktop/web + } + // On mobile, check if version is approved + // If products is null/undefined, default to false (hide until we know) + if (!products) { + return false; + } + // Show if at least one product is available (meaning version is approved) + return products.some((product) => product.is_available !== false); + })(); + const handleManageSubscription = async () => { if (!hasStripeAccount) return; @@ -300,7 +339,7 @@ export function AccountMenu() { )} - {!isMobile() && ( + {showApiManagement && ( setIsApiKeyDialogOpen(true)}> API Management From 7cfbe0590da9f03d73d4de21c07cbe5543c07a57 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Mon, 9 Feb 2026 22:31:50 +0000 Subject: [PATCH 2/3] Fix query key to prevent cache poisoning between AccountMenu and pricing page The bot's concern was valid: AccountMenu and pricing page shared the same query key ["products", isIOSPlatform, isAndroidPlatform] but handled errors differently. AccountMenu caught errors and returned null as successful data, which could poison React Query's cache. When the user navigated to pricing, they'd see no paid plans and no error message. Changed AccountMenu's query key to ["products-version-check", ...] to prevent cache collision. This follows the pattern used by Marketing.tsx which uses a separate ["marketing-products"] key. Co-authored-by: Anthony --- frontend/src/components/AccountMenu.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/components/AccountMenu.tsx b/frontend/src/components/AccountMenu.tsx index 611a9af43..ea5faa347 100644 --- a/frontend/src/components/AccountMenu.tsx +++ b/frontend/src/components/AccountMenu.tsx @@ -134,7 +134,7 @@ export function AccountMenu() { const isIOSPlatform = isIOS(); const isAndroidPlatform = isAndroid(); const { data: products } = useQuery({ - queryKey: ["products", isIOSPlatform, isAndroidPlatform], + queryKey: ["products-version-check", isIOSPlatform, isAndroidPlatform], queryFn: async () => { try { const billingService = getBillingService(); From 9449a88ef27cbe07cba93700ab2a8e9edf2fada8 Mon Sep 17 00:00:00 2001 From: "claude[bot]" <41898282+claude[bot]@users.noreply.github.com> Date: Tue, 10 Feb 2026 00:34:06 +0000 Subject: [PATCH 3/3] Fix Android gating for API Management button Only iOS should check version approval - Android, desktop, and web should always show the API Management button. Co-authored-by: Anthony --- frontend/src/components/AccountMenu.tsx | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/AccountMenu.tsx b/frontend/src/components/AccountMenu.tsx index ea5faa347..25adb3a85 100644 --- a/frontend/src/components/AccountMenu.tsx +++ b/frontend/src/components/AccountMenu.tsx @@ -13,7 +13,7 @@ import { FileText, ChevronLeft } from "lucide-react"; -import { isMobile, isTauri, isIOS, isAndroid } from "@/utils/platform"; +import { isMobile, isTauri, isIOS } from "@/utils/platform"; import { Button } from "@/components/ui/button"; import { @@ -130,16 +130,15 @@ export function AccountMenu() { enabled: isTeamPlan && !!os.auth.user && !!billingStatus }); - // Fetch products with version check for mobile platforms to determine API Management availability + // Fetch products with version check for iOS to determine API Management availability const isIOSPlatform = isIOS(); - const isAndroidPlatform = isAndroid(); const { data: products } = useQuery({ - queryKey: ["products-version-check", isIOSPlatform, isAndroidPlatform], + queryKey: ["products-version-check", isIOSPlatform], queryFn: async () => { try { const billingService = getBillingService(); - // Send version for mobile builds (iOS/Android need it for App Store restrictions) - if (isIOSPlatform || isAndroidPlatform) { + // Send version for iOS builds (App Store restrictions) + if (isIOSPlatform) { const version = `v${packageJson.version}`; return await billingService.getProducts(version); } @@ -149,7 +148,7 @@ export function AccountMenu() { return null; } }, - enabled: isIOSPlatform || isAndroidPlatform + enabled: isIOSPlatform }); // Show alert badge if user has team plan but hasn't created team yet @@ -157,13 +156,13 @@ export function AccountMenu() { isTeamPlan && teamStatus?.has_team_subscription && !teamStatus?.team_created; // Determine if API Management should be shown - // On desktop/web: always show - // On iOS/Android: only show if version is approved (at least one product is available) + // On desktop/web/Android: always show + // On iOS only: only show if version is approved (at least one product is available) const showApiManagement = (() => { - if (!isMobile()) { - return true; // Always show on desktop/web + if (!isIOSPlatform) { + return true; // Always show on desktop/web/Android } - // On mobile, check if version is approved + // On iOS, check if version is approved // If products is null/undefined, default to false (hide until we know) if (!products) { return false;