From b9352345a3040224c4881c116e8068932804803b Mon Sep 17 00:00:00 2001 From: bkellam Date: Thu, 27 Feb 2025 16:10:55 -0800 Subject: [PATCH] Add mobile unsupported splash screne --- packages/web/package.json | 1 + packages/web/src/actions.ts | 7 +++- .../mobileUnsupportedSplashScreen.tsx | 42 +++++++++++++++++++ packages/web/src/app/[domain]/layout.tsx | 14 +++++++ .../web/src/app/[domain]/upgrade/page.tsx | 6 +-- packages/web/src/lib/constants.ts | 4 +- packages/web/src/lib/posthogEvents.ts | 2 + yarn.lock | 21 ++++++---- 8 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 packages/web/src/app/[domain]/components/mobileUnsupportedSplashScreen.tsx diff --git a/packages/web/package.json b/packages/web/package.json index b262b52b..9e00cb49 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -118,6 +118,7 @@ "pretty-bytes": "^6.1.1", "psl": "^1.15.0", "react": "^18", + "react-device-detect": "^2.2.3", "react-dom": "^18", "react-hook-form": "^7.53.0", "react-hotkeys-hook": "^4.5.1", diff --git a/packages/web/src/actions.ts b/packages/web/src/actions.ts index 7bca2240..b0efce8c 100644 --- a/packages/web/src/actions.ts +++ b/packages/web/src/actions.ts @@ -15,7 +15,7 @@ import { GithubConnectionConfig, GitlabConnectionConfig, GiteaConnectionConfig, import { encrypt } from "@sourcebot/crypto" import { getConnection } from "./data/connection"; import { ConnectionSyncStatus, Prisma, OrgRole, RepoIndexingStatus, StripeSubscriptionStatus } from "@sourcebot/db"; -import { headers } from "next/headers" +import { cookies, headers } from "next/headers" import { getStripe } from "@/lib/stripe" import { getUser } from "@/data/user"; import { Session } from "next-auth"; @@ -26,6 +26,7 @@ import InviteUserEmail from "./emails/inviteUserEmail"; import { createTransport } from "nodemailer"; import { repositoryQuerySchema } from "./lib/schemas"; import { RepositoryQuery } from "./lib/types"; +import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME } from "./lib/constants"; const ajv = new Ajv({ validateFormats: false, @@ -1231,6 +1232,10 @@ export const getOrgInvites = async (domain: string) => }) ); +export const dismissMobileUnsupportedSplashScreen = async () => { + await cookies().set(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME, 'true'); +} + ////// Helpers /////// diff --git a/packages/web/src/app/[domain]/components/mobileUnsupportedSplashScreen.tsx b/packages/web/src/app/[domain]/components/mobileUnsupportedSplashScreen.tsx new file mode 100644 index 00000000..0cd016e7 --- /dev/null +++ b/packages/web/src/app/[domain]/components/mobileUnsupportedSplashScreen.tsx @@ -0,0 +1,42 @@ +'use client'; + +import { Button } from "@/components/ui/button"; +import { Card } from "@/components/ui/card"; +import { TriangleAlert } from "lucide-react"; +import { useCallback, useEffect } from "react"; +import { dismissMobileUnsupportedSplashScreen } from "@/actions"; +import useCaptureEvent from "@/hooks/useCaptureEvent"; + +export const MobileUnsupportedSplashScreen = () => { + const captureEvent = useCaptureEvent(); + + useEffect(() => { + captureEvent('wa_mobile_unsupported_splash_screen_displayed', {}); + }, [captureEvent]); + + const onDismissed = useCallback(() => { + dismissMobileUnsupportedSplashScreen(); + captureEvent('wa_mobile_unsupported_splash_screen_dismissed', {}); + }, [captureEvent]); + + return ( +
+ + +
+ Mobile is not supported. +
+

+ Sourcebot on mobile is still a work in progress. Please use a desktop computer to get the best experience. +

+ +
+
+ ) +} \ No newline at end of file diff --git a/packages/web/src/app/[domain]/layout.tsx b/packages/web/src/app/[domain]/layout.tsx index ace64db7..cc739d35 100644 --- a/packages/web/src/app/[domain]/layout.tsx +++ b/packages/web/src/app/[domain]/layout.tsx @@ -6,6 +6,10 @@ import { isServiceError } from "@/lib/utils"; import { OnboardGuard } from "./components/onboardGuard"; import { fetchSubscription } from "@/actions"; import { UpgradeGuard } from "./components/upgradeGuard"; +import { cookies, headers } from "next/headers"; +import { getSelectorsByUserAgent } from "react-device-detect"; +import { MobileUnsupportedSplashScreen } from "./components/mobileUnsupportedSplashScreen"; +import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME } from "@/lib/constants"; interface LayoutProps { children: React.ReactNode, @@ -65,5 +69,15 @@ export default async function Layout({ ) } + const headersList = await headers(); + const cookieStore = await cookies() + const userAgent = headersList.get('user-agent'); + const { isMobile } = getSelectorsByUserAgent(userAgent ?? ''); + + if (isMobile && !cookieStore.has(MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME)) { + return ( + + ) + } return children; } \ No newline at end of file diff --git a/packages/web/src/app/[domain]/upgrade/page.tsx b/packages/web/src/app/[domain]/upgrade/page.tsx index ace24b81..9d8a8660 100644 --- a/packages/web/src/app/[domain]/upgrade/page.tsx +++ b/packages/web/src/app/[domain]/upgrade/page.tsx @@ -24,15 +24,15 @@ export default async function Upgrade({ params: { domain } }: { params: { domain const isTrialing = !isServiceError(subscription) ? subscription.status === "trialing" : false; return ( -
+
{isTrialing && ( - +
Return to dashboard
)} - +