"use client" import { useEffect, useState } from "react" import Link from "next/link" import { useRouter } from "next/navigation" import { ChevronRight, Link2 } from "lucide-react" import { Icon } from "@iconify/react" import { DriveAddMountDialog } from "@/components/drive/drive-add-mount-dialog" import { DriveFolderIcon } from "@/lib/drive/drive-file-icon" import { DRIVE_ICON_BTN, DRIVE_SIDEBAR_CARET_SLOT_CLASS, DRIVE_SIDEBAR_ROW_BODY_CLASS, DRIVE_SIDEBAR_ROW_CLASS, } from "@/lib/drive/drive-chrome-classes" import { mailNavRowClass } from "@/lib/mail-chrome-classes" import { cn } from "@/lib/utils" import { displayFileName } from "@/lib/drive/display-file-name" import { driveFolderHref, mountRootKey } from "@/lib/drive/drive-sidebar-tree" import { useDriveMountList, useDriveMountMutations, useDriveMounts } from "@/lib/api/hooks/use-drive-queries" import type { DriveMount } from "@/lib/api/types" import { useIsMobile } from "@/hooks/use-mobile" import { useDriveUIStore } from "@/lib/stores/drive-ui-store" import { openDriveMountOAuthPopup, buildDriveMountOAuthRedirectURI } from "@/lib/drive/drive-mount-oauth" const INDENT_PX = 16 function mountIcon(backendType: string) { switch (backendType) { case "googledrive": case "google": return "logos:google-drive" case "dropbox": return "logos:dropbox" case "onedrive": case "microsoft": return "logos:microsoft-onedrive" case "webdav": case "dav": return "mdi:cloud-sync" default: return "mdi:harddisk" } } function MountConnectButton({ mount }: { mount: DriveMount }) { const { fetchOAuthURL } = useDriveMountMutations() const [pending, setPending] = useState(false) if (!mount.needs_oauth && mount.status !== "pending_oauth") { return null } return ( ) } function MountTree({ mount, active, pathSegments, }: { mount: DriveMount active: boolean pathSegments: string[] }) { const router = useRouter() const isMobile = useIsMobile() const expandedPaths = useDriveUIStore((s) => s.expandedSidebarPaths) const toggleSidebarPath = useDriveUIStore((s) => s.toggleSidebarPath) const rootKey = mountRootKey(mount.id) const isExpanded = expandedPaths.has(rootKey) const isRootSelected = active && pathSegments.length === 0 const rootHref = driveFolderHref("mount", "/", mount.id) const mountReady = mount.status === "active" const list = useDriveMountList(mount.id, "/", 1, isExpanded && mountReady) const directories = list.data?.files.filter((f) => f.type === "directory") ?? [] return (
{ if (!mountReady) { event.preventDefault() return } event.preventDefault() router.push(rootHref) if (isMobile) useDriveUIStore.getState().setSidebarCollapsed(true) }} > {mount.display_name} {mount.status === "error" ? ( ! ) : null}
{isExpanded && mountReady ? directories.map((child) => ( )) : null}
) } function MountFolderNode({ mount, folderPath, depth, active, currentPath, }: { mount: DriveMount folderPath: string depth: number active: boolean currentPath: string }) { const router = useRouter() const isMobile = useIsMobile() const expandedPaths = useDriveUIStore((s) => s.expandedSidebarPaths) const toggleSidebarPath = useDriveUIStore((s) => s.toggleSidebarPath) const isExpanded = expandedPaths.has(folderPath) const isSelected = active && currentPath === folderPath const href = driveFolderHref("mount", folderPath, mount.id) const list = useDriveMountList(mount.id, folderPath, 1, isExpanded) const directories = list.data?.files.filter((f) => f.type === "directory") ?? [] return (
{ e.preventDefault(); router.push(href); if (isMobile) useDriveUIStore.getState().setSidebarCollapsed(true) }}> {displayFileName(folderPath.split("/").pop() ?? folderPath)}
{isExpanded ? directories.map((child) => ( )) : null}
) } export function DriveSidebarMounts({ active, pathSegments, rootId, }: { active: boolean pathSegments: string[] rootId: string | null }) { const mounts = useDriveMounts() const items = mounts.data ?? [] if (items.length === 0) { return null } return ( <> {items.map((mount) => ( ))} ) } export function DriveConnectMountAction() { const [addOpen, setAddOpen] = useState(false) const { invalidate } = useDriveMountMutations() useEffect(() => { const onMessage = (event: MessageEvent) => { if (event.origin !== window.location.origin) return if (event.data?.type === "drive-mount-oauth-complete") { invalidate() } } window.addEventListener("message", onMessage) return () => window.removeEventListener("message", onMessage) }, [invalidate]) return ( <> ) }