From d5fce55888865c27bcef8a27d11dbe447ec22f92 Mon Sep 17 00:00:00 2001 From: nikec Date: Sun, 8 Sep 2024 21:52:22 +0200 Subject: [PATCH] redirect url --- src/app/[owner]/[repo]/loading.tsx | 9 ---- src/app/[owner]/[repo]/page.tsx | 47 +++++++++++++++---- src/app/layout.tsx | 2 - src/app/page.tsx | 20 ++++---- src/components/controls/controls-download.tsx | 7 ++- src/components/controls/controls-url.tsx | 34 ++++++++++++++ src/components/controls/controls.tsx | 6 ++- src/lib/use-zod-params.ts | 7 +++ 8 files changed, 100 insertions(+), 32 deletions(-) delete mode 100644 src/app/[owner]/[repo]/loading.tsx create mode 100644 src/components/controls/controls-url.tsx create mode 100644 src/lib/use-zod-params.ts diff --git a/src/app/[owner]/[repo]/loading.tsx b/src/app/[owner]/[repo]/loading.tsx deleted file mode 100644 index 887ea09..0000000 --- a/src/app/[owner]/[repo]/loading.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Loader } from "lucide-react"; - -export default function Loading() { - return ( -
- -
- ); -} diff --git a/src/app/[owner]/[repo]/page.tsx b/src/app/[owner]/[repo]/page.tsx index 5f68d21..13dbc37 100644 --- a/src/app/[owner]/[repo]/page.tsx +++ b/src/app/[owner]/[repo]/page.tsx @@ -1,20 +1,28 @@ +import { Suspense } from "react"; import type { Metadata } from "next"; +import { redirect } from "next/navigation"; +import { Loader } from "lucide-react"; +import { createSearchParamsCache, parseAsBoolean } from "nuqs/server"; import { Controls } from "~/components/controls/controls"; +import { Header } from "~/components/header"; import { CONTROLS_SEARCH_PARAMS } from "~/lib/params/controls.params"; import { RepoPreview } from "./_components/repo-preview"; -type Params = { - owner: string; - repo: string; -}; +type Params = { owner: string; repo: string }; + +type SearchParams = Record; + +const searchParamsCache = createSearchParamsCache({ + redirect: parseAsBoolean.withDefault(false), +}); export async function generateMetadata({ params, searchParams, }: { params: Params; - searchParams: Record; + searchParams: SearchParams; }) { const theme = CONTROLS_SEARCH_PARAMS.theme.parseServerSide( searchParams.theme, @@ -35,11 +43,30 @@ export async function generateMetadata({ } satisfies Metadata; } -export default function Page({ params }: { params: Params }) { +export default function Page({ + params, + searchParams, +}: { + params: Params; + searchParams: SearchParams; +}) { + const { redirect: shouldRedirect } = searchParamsCache.parse(searchParams); + + if (shouldRedirect) { + redirect(`https://github.com/${params.owner}/${params.repo}`); + } + return ( -
- - -
+ <> +
+
+ } + > + + + +
+ ); } diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 655380b..84e9638 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,7 +3,6 @@ import { Inter } from "next/font/google"; import { Analytics } from "@vercel/analytics/react"; import { ThemeProvider } from "next-themes"; -import { Header } from "~/components/header"; import { Toaster } from "~/components/ui/sonner"; import { TooltipProvider } from "~/components/ui/tooltip"; @@ -33,7 +32,6 @@ export default function RootLayout({ -
{children} diff --git a/src/app/page.tsx b/src/app/page.tsx index 2cd00a0..9e243b4 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,15 +1,19 @@ +import { Header } from "~/components/header"; import { SearchForm } from "./_components/search-form"; import { SuggestedRepos } from "./_components/suggested-repos"; export default function Page() { return ( -
-

gnip

-

- Create snippets for your GitHub repositories. -

- - -
+ <> +
+
+

gnip

+

+ Create snippets for your GitHub repositories. +

+ + +
+ ); } diff --git a/src/components/controls/controls-download.tsx b/src/components/controls/controls-download.tsx index 13a4e06..0a08dd5 100644 --- a/src/components/controls/controls-download.tsx +++ b/src/components/controls/controls-download.tsx @@ -1,13 +1,14 @@ "use client"; -import { useParams } from "next/navigation"; import { ChevronDown, Download } from "lucide-react"; import { toast } from "sonner"; +import { z } from "zod"; import { EXPORT_SIZES } from "~/lib/const/export-size.const"; import { download } from "~/lib/download"; import { toBlob, toPng, toSvg } from "~/lib/image"; import { useControls } from "~/lib/params/controls.params"; +import { useZodParams } from "~/lib/use-zod-params"; import { Button } from "../ui/button"; import { DropdownMenu, @@ -23,8 +24,10 @@ import { } from "../ui/dropdown-menu"; import { Tooltip } from "../ui/tooltip"; +const paramsSchema = z.object({ repo: z.string() }); + export function ControlsDownload() { - const params = useParams(); + const params = useZodParams(paramsSchema.shape); const [{ size }, setControls] = useControls(); diff --git a/src/components/controls/controls-url.tsx b/src/components/controls/controls-url.tsx new file mode 100644 index 0000000..81bf652 --- /dev/null +++ b/src/components/controls/controls-url.tsx @@ -0,0 +1,34 @@ +"use client"; + +import { Link } from "lucide-react"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { useZodParams } from "~/lib/use-zod-params"; +import { Button } from "../ui/button"; +import { Tooltip } from "../ui/tooltip"; + +const paramsSchema = z.object({ owner: z.string(), repo: z.string() }); + +export function ControlsUrl() { + const params = useZodParams(paramsSchema.shape); + + function copyRedirectUrl() { + const url = `${window.location.origin}/${params.owner}/${params.repo}?redirect=true`; + navigator.clipboard.writeText(url); + toast.success("Redirect URL copied to clipboard"); + } + + return ( + + + + ); +} diff --git a/src/components/controls/controls.tsx b/src/components/controls/controls.tsx index 69a8ba1..054e5e2 100644 --- a/src/components/controls/controls.tsx +++ b/src/components/controls/controls.tsx @@ -6,6 +6,7 @@ import { ControlsDarkMode } from "./controls-dark-mode"; import { ControlsDownload } from "./controls-download"; import { ControlsPadding } from "./controls-padding"; import { ControlsTheme } from "./controls-theme"; +import { ControlsUrl } from "./controls-url"; export function Controls() { return ( @@ -18,7 +19,10 @@ export function Controls() { - +
+ + +
); } diff --git a/src/lib/use-zod-params.ts b/src/lib/use-zod-params.ts new file mode 100644 index 0000000..417284d --- /dev/null +++ b/src/lib/use-zod-params.ts @@ -0,0 +1,7 @@ +import { useParams } from "next/navigation"; +import { z } from "zod"; + +export const useZodParams = (schema: T) => { + const params = useParams(); + return z.object(schema).parse(params); +};