feat: show in progress upload in upload btn

This commit is contained in:
2025-10-12 17:09:42 +00:00
parent 0c7e4c43e7
commit b17de812b9
3 changed files with 33 additions and 46 deletions

View File

@@ -26,6 +26,8 @@ export const clearFileUploadAtom = atom(null, (get, set, id: string) => {
set(fileUploadsAtom, fileUploads) set(fileUploadsAtom, fileUploads)
}) })
export const hasFileUploadsAtom = atom( export const fileUploadCountAtom = atom(
(get) => Object.keys(get(fileUploadsAtom)).length > 0, (get) => Object.keys(get(fileUploadsAtom)).length,
) )
export const hasFileUploadsAtom = atom((get) => get(fileUploadCountAtom) > 0)

View File

@@ -1,12 +1,6 @@
import type { Doc } from "@fileone/convex/_generated/dataModel" import type { Doc } from "@fileone/convex/_generated/dataModel"
import { useMutation } from "@tanstack/react-query" import { useMutation } from "@tanstack/react-query"
import { import { atom, useAtom, useAtomValue, useSetAtom, useStore } from "jotai"
atom,
useAtom,
useAtomValue,
useSetAtom,
useStore,
} from "jotai"
import { atomEffect } from "jotai-effect" import { atomEffect } from "jotai-effect"
import { FilePlus2Icon, UploadCloudIcon, XIcon } from "lucide-react" import { FilePlus2Icon, UploadCloudIcon, XIcon } from "lucide-react"
import { nanoid } from "nanoid" import { nanoid } from "nanoid"
@@ -88,6 +82,7 @@ export function UploadFileDialog({
}, },
onSuccess: () => { onSuccess: () => {
toast.success("All files uploaded successfully") toast.success("All files uploaded successfully")
setPickedFiles([])
onClose() onClose()
}, },
}) })
@@ -115,6 +110,20 @@ export function UploadFileDialog({
uploadFiles(pickedFiles) uploadFiles(pickedFiles)
} }
let dialogTitle: string
let dialogDescription: string
if (isUploading) {
dialogTitle = "Uploading files"
dialogDescription =
"You can close the dialog while they are being uploaded in the background."
} else if (targetDirectory.name) {
dialogTitle = `Upload file to "${targetDirectory.name}"`
dialogDescription = "Drag and drop files here or click to select files"
} else {
dialogTitle = "Upload file"
dialogDescription = "Drag and drop files here or click to select files"
}
return ( return (
<Dialog <Dialog
open open
@@ -124,12 +133,8 @@ export function UploadFileDialog({
> >
<DialogContent className="sm:max-w-2xl"> <DialogContent className="sm:max-w-2xl">
<DialogHeader> <DialogHeader>
<DialogTitle> <DialogTitle>{dialogTitle}</DialogTitle>
{targetDirectory.name ? `Upload file to "${targetDirectory.name}"` : "Upload file"} <DialogDescription>{dialogDescription}</DialogDescription>
</DialogTitle>
<DialogDescription>
Drag and drop files here or click to select files
</DialogDescription>
</DialogHeader> </DialogHeader>
<form id={formId} onSubmit={handleSubmit}> <form id={formId} onSubmit={handleSubmit}>

View File

@@ -10,19 +10,16 @@ import { createFileRoute } from "@tanstack/react-router"
import type { Row, Table } from "@tanstack/react-table" import type { Row, Table } from "@tanstack/react-table"
import { import {
useMutation as useContextMutation, useMutation as useContextMutation,
useMutation as useConvexMutation,
useQuery as useConvexQuery, useQuery as useConvexQuery,
} from "convex/react" } from "convex/react"
import { atom, useAtom, useAtomValue, useSetAtom, useStore } from "jotai" import { atom, useAtom, useAtomValue, useSetAtom, useStore } from "jotai"
import { import {
ChevronDownIcon, ChevronDownIcon,
Loader2Icon,
PlusIcon, PlusIcon,
TextCursorInputIcon, TextCursorInputIcon,
TrashIcon, TrashIcon,
UploadCloudIcon,
} from "lucide-react" } from "lucide-react"
import { type ChangeEvent, useCallback, useContext, useRef } from "react" import { useCallback, useContext } from "react"
import { toast } from "sonner" import { toast } from "sonner"
import { DirectoryIcon } from "@/components/icons/directory-icon" import { DirectoryIcon } from "@/components/icons/directory-icon"
import { TextFileIcon } from "@/components/icons/text-file-icon" import { TextFileIcon } from "@/components/icons/text-file-icon"
@@ -47,6 +44,7 @@ import { FilePathBreadcrumb } from "@/directories/directory-page/file-path-bread
import { NewDirectoryDialog } from "@/directories/directory-page/new-directory-dialog" import { NewDirectoryDialog } from "@/directories/directory-page/new-directory-dialog"
import { RenameFileDialog } from "@/directories/directory-page/rename-file-dialog" import { RenameFileDialog } from "@/directories/directory-page/rename-file-dialog"
import { FilePreviewDialog } from "@/files/file-preview-dialog" import { FilePreviewDialog } from "@/files/file-preview-dialog"
import { fileUploadCountAtom } from "@/files/store"
import { UploadFileDialog } from "@/files/upload-file-dialog" import { UploadFileDialog } from "@/files/upload-file-dialog"
import type { FileDragInfo } from "@/files/use-file-drop" import type { FileDragInfo } from "@/files/use-file-drop"
@@ -334,34 +332,8 @@ function RenameMenuItem() {
// tags: upload, uploadfile, uploadfilebutton, fileupload, fileuploadbutton // tags: upload, uploadfile, uploadfilebutton, fileupload, fileuploadbutton
function UploadFileButton() { function UploadFileButton() {
const { directory } = useContext(DirectoryPageContext) const { directory } = useContext(DirectoryPageContext)
// const uploadFile = useUploadFile({
// targetDirectory: directory,
// })
// const { mutate: uploadFile, isPending: isUploading } = useMutation({
// mutationFn: async (file: File) => {
// const uploadUrl = await generateUploadUrl()
// const uploadResult = await fetch(uploadUrl, {
// method: "POST",
// body: file,
// headers: {
// "Content-Type": file.type,
// },
// })
// const { storageId } = await uploadResult.json()
// await saveFile({
// storageId,
// name: file.name,
// size: file.size,
// mimeType: file.type,
// directoryId: directory._id,
// })
// },
// onSuccess: () => {
// toast.success("File uploaded successfully.")
// },
// })
const setActiveDialogData = useSetAtom(activeDialogDataAtom) const setActiveDialogData = useSetAtom(activeDialogDataAtom)
const fileUploadCount = useAtomValue(fileUploadCountAtom)
const handleClick = () => { const handleClick = () => {
setActiveDialogData({ setActiveDialogData({
@@ -370,6 +342,14 @@ function UploadFileButton() {
}) })
} }
if (fileUploadCount > 0) {
return (
<Button size="sm" type="button" loading onClick={handleClick}>
Uploading {fileUploadCount} files
</Button>
)
}
return ( return (
<Button size="sm" type="button" onClick={handleClick}> <Button size="sm" type="button" onClick={handleClick}>
Upload files Upload files