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