diff --git a/apps/mobile/app/(tabs)/index.tsx b/apps/mobile/app/(tabs)/index.tsx index b2bd7a4..a5ad23c 100644 --- a/apps/mobile/app/(tabs)/index.tsx +++ b/apps/mobile/app/(tabs)/index.tsx @@ -10,6 +10,7 @@ import { useConnections } from "@/store/connection.store" import { useProjects } from "@/store/projects.store" import { useAllowsMultipleConnections } from "@/lib/entitlement" import { useAuth } from "@/store/auth.store" +import { usePaywall } from "@/store/paywall.store" import { isAtTunnelLimit, requestPaywall } from "@/lib/paywall" import { cn, formatDirectory, getAuthHeader } from "@/lib/utils" import { getCurrentProject } from "@/lib/projects" @@ -26,6 +27,8 @@ import User from "lucide-react-native/dist/esm/icons/user" import Wifi from "lucide-react-native/dist/esm/icons/wifi" import WifiOff from "lucide-react-native/dist/esm/icons/wifi-off" import X from "lucide-react-native/dist/esm/icons/x" +import Zap from "lucide-react-native/dist/esm/icons/zap" +import ChevronRight from "lucide-react-native/dist/esm/icons/chevron-right" import { THEME } from "@/lib/theme" import { useColorScheme } from "nativewind" import { Input } from "@/components/ui/input" @@ -506,6 +509,29 @@ export default function HomeScreen() { )} )} + + {atLimit && ( + usePaywall.getState().show("usage_nudge")} + className="flex-row items-center gap-2.5 rounded-xl border border-border bg-muted/50 px-3 py-2.5 active:bg-muted/70" + > + + + + + + {connections.length}/{tier === "free" ? 1 : connections.length} tunnels used + + + Upgrade for more parallel projects + + + + Upgrade + + + + )} c.id} - contentContainerStyle={filteredConnections.length === 0 ? undefined : { gap: 12, paddingBottom: 32 }} + contentContainerStyle={filteredConnections.length === 0 ? undefined : { gap: 12, paddingBottom: 100 }} refreshControl={ - {atLimit && filteredConnections.length > 0 && ( - - requestPaywall("usage_nudge")} - className="flex-row items-center gap-3 rounded-2xl border border-primary/30 bg-primary/5 p-3 active:opacity-80" - > - - - {connections.length}/{tier === "free" ? 1 : connections.length} tunnels used — need more? - - Upgrade to run more projects in parallel - - - Upgrade - - - - )} - {filteredConnections.length > 0 && ( { +export async function requestPaywall(trigger: PaywallTrigger, opts?: { force?: boolean }): Promise { const tier = useAuth.getState().user?.tier ?? "free" if (tier === "builder" || tier === "enterprise") return false - if (!(await shouldShowPaywall(trigger))) return false + if (!opts?.force && !(await shouldShowPaywall(trigger))) return false await pushStamp(SHOWS_KEY, Date.now()) usePaywall.getState().show(trigger) return true