- Updated .env.example to include configuration for OnlyOffice Document Server. - Modified the workspace configuration to remove the drive-suite path. - Adjusted TypeScript environment imports for consistency. - Enhanced Next.js configuration to disable canvas in Webpack. - Updated package.json to include new dependencies for OnlyOffice and PDF.js. - Added global styles for OnlyOffice theme integration in the CSS. - Created new layout and page components for the Drive feature, including public sharing and editing functionalities. - Updated metadata handling across various layouts to reflect the new app structure.
149 lines
4.9 KiB
TypeScript
149 lines
4.9 KiB
TypeScript
"use client"
|
|
|
|
import { useState } from "react"
|
|
import { useRouter } from "next/navigation"
|
|
import { Menu, Plus, Search, X } from "lucide-react"
|
|
import { Button } from "@/components/ui/button"
|
|
import { DriveMobileSearchSheet } from "@/components/drive/drive-mobile-search-sheet"
|
|
import { DriveNewSheet } from "@/components/drive/drive-new-sheet"
|
|
import type { DriveFileInfo } from "@/lib/api/types"
|
|
import { openDriveItem } from "@/lib/drive/drive-open-item"
|
|
import {
|
|
type DriveSearchScope,
|
|
buildDriveSearchUrl,
|
|
defaultDriveSearchScope,
|
|
fileBrowserViewForSearchScope,
|
|
} from "@/lib/drive/drive-search"
|
|
import type { DriveView } from "@/lib/drive/drive-url"
|
|
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
|
|
|
|
const ROUNDED_BAR_BTN =
|
|
"size-11 shrink-0 rounded-full border border-gray-200 bg-white/80 text-[#444746] shadow-md backdrop-blur hover:bg-white"
|
|
|
|
export function DriveMobileBottomBar({
|
|
search,
|
|
onSearchChange,
|
|
searchScope,
|
|
onSearchScopeChange,
|
|
folderPath,
|
|
contextView,
|
|
resultsMode = false,
|
|
parentPath,
|
|
}: {
|
|
search: string
|
|
onSearchChange: (q: string) => void
|
|
searchScope: DriveSearchScope
|
|
onSearchScopeChange: (scope: DriveSearchScope) => void
|
|
folderPath: string
|
|
contextView: DriveView
|
|
resultsMode?: boolean
|
|
parentPath: string
|
|
}) {
|
|
const router = useRouter()
|
|
const openPreview = useDriveUIStore((s) => s.openPreview)
|
|
const sidebarCollapsed = useDriveUIStore((s) => s.sidebarCollapsed)
|
|
const setSidebarCollapsed = useDriveUIStore((s) => s.setSidebarCollapsed)
|
|
const sidebarOpen = !sidebarCollapsed
|
|
const [searchOpen, setSearchOpen] = useState(false)
|
|
const [newOpen, setNewOpen] = useState(false)
|
|
|
|
const toggleSidebar = () => setSidebarCollapsed(!sidebarCollapsed)
|
|
const effectiveScope =
|
|
searchScope === "folder" && folderPath === "/"
|
|
? defaultDriveSearchScope(contextView, folderPath)
|
|
: searchScope
|
|
|
|
const submitSearch = () => {
|
|
const q = search.trim()
|
|
if (!q) return
|
|
router.push(
|
|
buildDriveSearchUrl({
|
|
query: q,
|
|
scope: effectiveScope,
|
|
folderPath: effectiveScope === "folder" ? folderPath : "/",
|
|
})
|
|
)
|
|
}
|
|
|
|
const openSuggestion = (item: DriveFileInfo, contextItems: DriveFileInfo[]) => {
|
|
openDriveItem(item, {
|
|
router,
|
|
openPreview,
|
|
view: fileBrowserViewForSearchScope(effectiveScope),
|
|
contextItems,
|
|
})
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<DriveMobileSearchSheet
|
|
open={searchOpen}
|
|
onClose={() => setSearchOpen(false)}
|
|
search={search}
|
|
onSearchChange={onSearchChange}
|
|
searchScope={searchScope}
|
|
onSearchScopeChange={onSearchScopeChange}
|
|
folderPath={folderPath}
|
|
contextView={contextView}
|
|
resultsMode={resultsMode}
|
|
onPickItem={openSuggestion}
|
|
onSubmitSearch={submitSearch}
|
|
/>
|
|
<DriveNewSheet parentPath={parentPath} open={newOpen} onOpenChange={setNewOpen} />
|
|
|
|
<div className="fixed inset-x-0 bottom-0 z-50 flex flex-col items-center pb-[env(safe-area-inset-bottom)] sm:hidden">
|
|
<div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-app-canvas/95 via-app-canvas/70 to-transparent" />
|
|
|
|
<div className="relative z-10 flex w-full items-center gap-2 px-3 pb-3 pt-2">
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
className={ROUNDED_BAR_BTN}
|
|
onClick={toggleSidebar}
|
|
aria-label={sidebarOpen ? "Fermer le menu" : "Ouvrir le menu"}
|
|
>
|
|
{sidebarOpen ? <X className="size-5" /> : <Menu className="size-5" />}
|
|
</Button>
|
|
|
|
{!sidebarOpen && (
|
|
<>
|
|
<button
|
|
type="button"
|
|
className="relative flex min-w-0 flex-1 items-center"
|
|
onClick={() => setSearchOpen(true)}
|
|
>
|
|
<div className="pointer-events-none absolute left-3 z-10 flex items-center text-gray-500">
|
|
<Search className="size-5" />
|
|
</div>
|
|
<div className="flex h-11 w-full items-center rounded-full border border-gray-200 bg-white/80 pl-10 pr-4 text-left text-sm shadow-md backdrop-blur">
|
|
<span
|
|
className={
|
|
search
|
|
? "truncate text-gray-900 dark:text-gray-100"
|
|
: "text-gray-400"
|
|
}
|
|
>
|
|
{search || "Rechercher dans Drive"}
|
|
</span>
|
|
</div>
|
|
</button>
|
|
|
|
<Button
|
|
type="button"
|
|
variant="ghost"
|
|
size="icon"
|
|
className={ROUNDED_BAR_BTN}
|
|
onClick={() => setNewOpen(true)}
|
|
aria-label="Nouveau"
|
|
>
|
|
<Plus className="size-5" />
|
|
</Button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|