import { useMutation, useQuery } from "@tanstack/react-query"
import { useAtomValue, useStore } from "jotai"
import {
CheckIcon,
CopyIcon,
EllipsisIcon,
LinkIcon,
LockKeyholeIcon,
} from "lucide-react"
import { createContext, useContext, useRef } from "react"
import {
CrossfadeIcon,
type CrossfadeIconHandle,
} from "@/components/crossfade-icon"
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { copyToClipboardMutation } from "@/lib/clipboard"
import {
createShareMutationAtom,
deleteShareMutationAtom,
directorySharesQueryAtom,
fileSharesQueryAtom,
} from "@/sharing/api"
import type { DirectoryItem } from "@/vfs/vfs"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "../components/ui/tooltip"
import type { Share } from "./share"
type ItemShareDialogProps = {
item: DirectoryItem | null
open: boolean
onClose: () => void
}
const ItemShareDialogContext = createContext<{
item: DirectoryItem
}>(
null as unknown as {
item: DirectoryItem
},
)
export function ItemShareDialog({ item, open, onClose }: ItemShareDialogProps) {
let description: string
switch (item?.kind) {
case "file":
description = "Configure external access to this file."
break
case "directory":
description = "Configure external access to this directory."
break
default:
description = "Configure external access to this item."
break
}
return (
)
}
function PublicAccessSection({ item }: { item: DirectoryItem }) {
const fileSharesQuery = useAtomValue(fileSharesQueryAtom(item.id))
const directorySharesQuery = useAtomValue(directorySharesQueryAtom(item.id))
const { data: fileShares, isLoading: isLoadingFileShares } = useQuery({
...fileSharesQuery,
enabled: item.kind === "file",
})
const { data: directoryShares, isLoading: isLoadingDirectoryShares } =
useQuery({
...directorySharesQuery,
enabled: item.kind === "directory",
})
let shares: Share[] = []
if (fileShares) {
shares = fileShares
} else if (directoryShares) {
shares = directoryShares
}
let content: React.ReactNode = null
if (isLoadingFileShares || isLoadingDirectoryShares) {
content =
Loading...
} else if (shares.length === 0) {
content = (
No share link created
Only you can access this item.
)
} else {
content = (
{shares.map((share) => (
))}
)
}
return (
Public Access
{content}
)
}
function ShareLinkListItem({ share }: { share: Share }) {
const { item } = useContext(ItemShareDialogContext)
const copyLinkButtonRef = useRef(null)
const copyIconRef = useRef(null)
const { mutate: copyToClipboard } = useMutation({
...copyToClipboardMutation,
onSuccess: () => {
copyIconRef.current?.trigger()
},
})
const copyItemShareLinkToClipboard = () => {
let link: string
switch (item.kind) {
case "file":
link = `${window.location.origin}/shares/${share.id}/files/${item.id}`
break
case "directory":
link = `${window.location.origin}/shares/${share.id}/directories/${item.id}`
break
default:
link = ""
break
}
if (link) {
copyToClipboard(link)
}
}
return (
{/** biome-ignore lint/a11y/noStaticElementInteractions: this is strictly for convenience. the normal copy link button is still accessible. */}
{/** biome-ignore lint/a11y/useKeyWithClickEvents: this is strictly for convenience. the normal copy link button is still accessible. */}
{
copyLinkButtonRef.current?.click()
}}
>
{/** biome-ignore lint/a11y/noStaticElementInteractions: this is strictly for convenience. the normal copy link button is still accessible. */}
{/** biome-ignore lint/a11y/useKeyWithClickEvents: this is strictly for convenience. the normal copy link button is still accessible. */}
{
copyLinkButtonRef.current?.click()
}}
>
Share link
{share.expiresAt
? `Expires at ${share.expiresAt}`
: "Never expires"}