mirror of
https://github.com/Nezumi-2711/next-gdrive-index.git
synced 2026-09-22 13:38:38 +00:00
Update file browser, file grid, file list, and password components
This commit is contained in:
@@ -103,7 +103,7 @@ export default function FileBrowser({ files, nextPageToken }: Props) {
|
|||||||
key={file.encryptedId}
|
key={file.encryptedId}
|
||||||
data={file}
|
data={file}
|
||||||
/>
|
/>
|
||||||
<Separator className='group-last:hidden' />
|
<Separator className='mt-1.5 group-last:hidden' />
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ export default function FileGrid({ data }: Props) {
|
|||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
name='Play'
|
name='Play'
|
||||||
className='absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full bg-muted-foreground fill-muted p-1.5 text-muted opacity-50'
|
className='absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full bg-muted-foreground fill-muted p-1.5 text-muted opacity-75'
|
||||||
size={32}
|
size={32}
|
||||||
/>
|
/>
|
||||||
<div className='absolute bottom-0 right-0 z-10 bg-background px-1 py-0.5 text-xs text-foreground'>
|
<div className='absolute bottom-0 right-0 z-10 bg-background px-1 py-0.5 text-xs text-foreground'>
|
||||||
|
|||||||
+19
-7
@@ -52,15 +52,27 @@ export default function FileList({ data }: Props) {
|
|||||||
>
|
>
|
||||||
<div className={cn("flex-shrink flex-grow", "flex items-center gap-3")}>
|
<div className={cn("flex-shrink flex-grow", "flex items-center gap-3")}>
|
||||||
{/* If it's media, show thumbnail */}
|
{/* If it's media, show thumbnail */}
|
||||||
<div className='flex-shrink-0 rounded-[var(--radius)] bg-muted/25'>
|
<div className='relative flex-shrink-0 rounded-[var(--radius)] bg-muted/25'>
|
||||||
{data.thumbnailLink &&
|
{data.thumbnailLink &&
|
||||||
(data.mimeType.startsWith("video") ||
|
(data.mimeType.startsWith("video") ||
|
||||||
data.mimeType.startsWith("image")) ? (
|
data.mimeType.startsWith("image")) ? (
|
||||||
<img
|
<>
|
||||||
src={`/api/thumb/${data.encryptedId}`}
|
<img
|
||||||
alt={data.name}
|
src={`/api/thumb/${data.encryptedId}`}
|
||||||
className='size-12 flex-shrink-0 flex-grow-0 rounded-[var(--radius)] object-cover'
|
alt={data.name}
|
||||||
/>
|
className='size-16 flex-shrink-0 flex-grow-0 rounded-[var(--radius)] object-cover tablet:size-12'
|
||||||
|
/>
|
||||||
|
|
||||||
|
{data.mimeType.startsWith("video") && (
|
||||||
|
<>
|
||||||
|
<Icon
|
||||||
|
name='Play'
|
||||||
|
className='absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2 rounded-full bg-muted-foreground fill-muted p-1.5 text-muted opacity-75'
|
||||||
|
size={24}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Icon
|
<Icon
|
||||||
name={
|
name={
|
||||||
@@ -68,7 +80,7 @@ export default function FileList({ data }: Props) {
|
|||||||
? "Folder"
|
? "Folder"
|
||||||
: getPreviewIcon(data.fileExtension || "", data.mimeType)
|
: getPreviewIcon(data.fileExtension || "", data.mimeType)
|
||||||
}
|
}
|
||||||
className='size-12 flex-shrink-0 flex-grow-0 p-3'
|
className='size-16 flex-shrink-0 flex-grow-0 p-3 tablet:size-12'
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+28
-6
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import Icon from "~/components/Icon";
|
import Icon from "~/components/Icon";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
@@ -18,10 +18,11 @@ export default function Password({ path, errorMessage }: Props) {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const [input, setInput] = useState<string>("");
|
const [input, setInput] = useState<string>("");
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [submitLoading, setSubmitLoading] = useState<boolean>(false);
|
||||||
|
const [loading, setLoading] = useState<boolean>(true);
|
||||||
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setLoading(true);
|
setSubmitLoading(true);
|
||||||
toast.loading("Checking password...", {
|
toast.loading("Checking password...", {
|
||||||
id: "password",
|
id: "password",
|
||||||
});
|
});
|
||||||
@@ -46,10 +47,31 @@ export default function Password({ path, errorMessage }: Props) {
|
|||||||
});
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setInput("");
|
setInput("");
|
||||||
setLoading(false);
|
setSubmitLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLoading(false);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (loading)
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn(
|
||||||
|
"mx-auto h-full w-full max-w-md",
|
||||||
|
"flex flex-grow flex-col items-center justify-center gap-3",
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name='LoaderCircle'
|
||||||
|
size={32}
|
||||||
|
className='animate-spin text-foreground'
|
||||||
|
/>
|
||||||
|
<p>Checking password...</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
@@ -89,9 +111,9 @@ export default function Password({ path, errorMessage }: Props) {
|
|||||||
<Button
|
<Button
|
||||||
className='gap-3'
|
className='gap-3'
|
||||||
type='submit'
|
type='submit'
|
||||||
disabled={loading}
|
disabled={submitLoading}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{submitLoading ? (
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
name='LoaderCircle'
|
name='LoaderCircle'
|
||||||
|
|||||||
Reference in New Issue
Block a user