diff --git a/next.config.mjs b/next.config.mjs index b17554b..fafecf9 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -32,6 +32,12 @@ const config = { port: '', pathname: '/**', }, + { + protocol: 'https', + hostname: '*.imgur.com', + port: '', + pathname: '/**', + }, { protocol: 'https', hostname: '*.githubusercontent.com', diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b695e95..9b2a930 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -16,13 +16,19 @@ datasource db { } model Video { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt - title String - video_url String - userId String - user User @relation(fields: [userId], references: [id], onDelete: Cascade) + id String @id @default(cuid()) + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + title String + video_url String + userId String + sharing Boolean @default(false) + deleteAfterExpiry Boolean @default(false) + shareExpiryAt DateTime? + linkShareSeo Boolean @default(false) + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + + @@index([userId]) } // Necessary for Next auth diff --git a/src/components/ShareModal.tsx b/src/components/ShareModal.tsx index 34cebca..73c1372 100644 --- a/src/components/ShareModal.tsx +++ b/src/components/ShareModal.tsx @@ -1,15 +1,36 @@ -import { Dialog, Switch, Transition } from "@headlessui/react"; +import { Dialog, Transition } from "@headlessui/react"; import { Fragment, useState } from "react"; import { ModernSwitch } from "~/components/ModernSwitch"; +import { api, type RouterOutputs } from "~/utils/api"; -export function ShareModal() { +interface Props { + video: RouterOutputs["video"]["get"]; +} + +export function ShareModal({ video }: Props) { + const utils = api.useContext(); const [open, setOpen] = useState(false); - const [sharing, setSharing] = useState(false); - const [es, sses] = useState(false); - const [as, ssgs] = useState(false); + const setSharingMutation = api.video.setSharing.useMutation({ + onMutate: async ({ videoId, sharing }) => { + await utils.video.get.cancel(); + const previousValue = utils.video.get.getData({ videoId }); + if (previousValue) { + utils.video.get.setData({ videoId }, { ...previousValue, sharing }); + } + return { previousValue }; + }, + }); - const [s, ss] = useState(false); + const [linkCopied, setLinkCopied] = useState(false); + + const handleCopy = () => { + void navigator.clipboard.writeText(window.location.href); + setLinkCopied(true); + setTimeout(() => { + setLinkCopied(false); + }, 5000); + }; return ( <> @@ -58,34 +79,52 @@ export function ShareModal() { Share link with anyone - + + setSharingMutation.mutate({ + videoId: video.id, + sharing: !video.sharing, + }) + } + /> - -
-
- Expire link + {video.sharing ? ( + <> + +
+ {/*
*/} + {/* Expire link*/} - -
-
- Delete video when expired - -
-
- Share link with search engines - -
-
- Embed code - -
-
+ {/* */} + {/*
*/} + {/*
*/} + {/* Delete video when expired*/} + {/* */} + {/*
*/} +
+ Share link with search engines + console.log("test")} + /> +
+ {/*
*/} + {/* Embed code*/} + {/* */} + {/*
*/} +
+ + ) : null} diff --git a/src/pages/share/[videoId].tsx b/src/pages/share/[videoId].tsx index 530cf6b..240d515 100644 --- a/src/pages/share/[videoId].tsx +++ b/src/pages/share/[videoId].tsx @@ -21,7 +21,7 @@ const VideoList: NextPage = () => { } ); - if (!isLoading && !video?.success) { + if (!isLoading && !video) { return (
@@ -50,29 +50,29 @@ const VideoList: NextPage = () => { Personal Library - + {video ? : null}
- {video?.video?.video_url && ( + {video?.video_url && ( )}
- {video?.video?.title ? ( + {video?.title ? (
- {video?.video?.title} + {video.title} - {getTime(video?.video?.createdAt)} + {getTime(video.createdAt)}
) : ( @@ -89,13 +89,14 @@ const VideoList: NextPage = () => { profile photo
- - {video?.video?.user?.name} - + {video.user.name} ) : ( <> diff --git a/src/server/api/routers/video.ts b/src/server/api/routers/video.ts index d4ab608..54b5ec9 100644 --- a/src/server/api/routers/video.ts +++ b/src/server/api/routers/video.ts @@ -4,6 +4,7 @@ import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc"; import { GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3"; import { env } from "~/env.mjs"; import { getSignedUrl } from "@aws-sdk/s3-request-presigner"; +import { TRPCError } from "@trpc/server"; export const videoRouter = createTRPCRouter({ getAll: protectedProcedure.query(async ({ ctx }) => { @@ -29,9 +30,7 @@ export const videoRouter = createTRPCRouter({ }); if (video?.userId !== ctx.session.user.id) { - return { - success: false, - }; + throw new TRPCError({ code: "FORBIDDEN" }); } const getObjectCommand = new GetObjectCommand({ @@ -43,10 +42,7 @@ export const videoRouter = createTRPCRouter({ video.video_url = signedUrl; - return { - success: true, - video, - }; + return video; }), getUploadUrl: protectedProcedure .input(z.object({ key: z.string() })) @@ -77,4 +73,21 @@ export const videoRouter = createTRPCRouter({ signedUrl, }; }), + setSharing: protectedProcedure + .input(z.object({ videoId: z.string(), sharing: z.boolean() })) + .mutation(async ({ ctx, input }) => { + const updateVideo = await ctx.prisma.video.update({ + where: { + id: input.videoId, + }, + data: { + sharing: input.sharing, + }, + }); + + return { + success: true, + updateVideo, + }; + }), });