import { useEffect, useState } from 'react' import { useMemoizedFn } from 'ahooks' import { useTranslation } from 'react-i18next' import { toast } from 'sonner' import { useNavigate } from '@tanstack/react-router' import { FolderOpenIcon, HistoryIcon, UploadIcon } from 'lucide-react' import { handleCloudImportAll } from '@/adapters/cloud-album' import { AppMainCard } from '@/components/common/app-main-card' import { FloatingPanelSheetContent } from '@/components/common/floating-panel-sheet-content' import { Button } from '@/components/ui/button' import { Sheet, SheetTrigger } from '@/components/ui/sheet' import { useIPCOn } from '@/hooks/useIPC' import { cn } from '@/lib/utils' import { appActions, settingsStoreActions, useAppStore, useAlbumStore } from '@/store' import { DESKTOP_HISTORY_PANEL_BREAKPOINT } from '@/utils/consts' import { AlbumSource } from '#/types/cloudAlbum' import { UploaderSwitcher } from './uploader-switcher' import { buildUrlDialogInitialValue, buildVisibleProviderOptions, resolveCurrentSwitcherValue, resolveLinkFormat, resolvePasteStyle } from './utils' import { HistoryPanel } from './history-panel' import { DashboardActionBar } from './dashboard-action-bar' import { UrlInputDialog } from './url-input-dialog' import { useDashboardHistory } from './hooks/use-dashboard-history' import { useDashboardCloudHistory } from './hooks/use-dashboard-cloud-history' import { useDashboardUpload } from './hooks/use-dashboard-upload' import { useDashboardDropHandler } from './hooks/use-dashboard-drop-handler' import type { LinkFormat } from '@/types/dashboard' function ProgressBar ({ value }: { value: number }) { return (
) } function useDesktopHistoryVisible () { const [visible, setVisible] = useState(() => { return typeof window !== 'undefined' && window.innerWidth >= DESKTOP_HISTORY_PANEL_BREAKPOINT }) useEffect(() => { const mql = window.matchMedia(`(min-width: ${DESKTOP_HISTORY_PANEL_BREAKPOINT}px)`) const sync = () => setVisible(mql.matches) sync() mql.addEventListener('change', sync) return () => mql.removeEventListener('change', sync) }, []) return visible } export function PicGoDashboard () { const navigate = useNavigate() const { t } = useTranslation() const [isHistoryOpen, setHistoryOpen] = useState(false) const [isHistorySheetThumbnailReady, setHistorySheetThumbnailReady] = useState(false) const isDesktopHistoryVisible = useDesktopHistoryVisible() const [urlDialogOpen, setUrlDialogOpen] = useState(false) const [urlDialogInitial, setUrlDialogInitial] = useState('') const localHistoryItems = useDashboardHistory() const cloudHistory = useDashboardCloudHistory() const albumSource = useAlbumStore.use.albumSource() const isCloudSource = albumSource === AlbumSource.CLOUD const historyItems = isCloudSource ? cloudHistory.items : localHistoryItems const historyLoading = isCloudSource ? cloudHistory.loading : false const { fileInputRef, isUploading, uploadProgress, startUpload, handleFileChange, uploadClipboardFiles, uploadFileList, uploadUrls } = useDashboardUpload() const { handleDrop, dispatchUrls } = useDashboardDropHandler({ uploadFileList, uploadUrls }) const providers = useAppStore.use.providers() const appConfig = useAppStore.use.appConfig() const providerOptions = buildVisibleProviderOptions(providers, appConfig) const currentSelection = resolveCurrentSwitcherValue(providerOptions, appConfig) const hasVisibleProviders = providerOptions.length > 0 const linkFormat = resolveLinkFormat(appConfig?.settings.pasteStyle) const handleSyncPicBed = useMemoizedFn(async () => { try { await Promise.all([appActions.refreshAppConfig(), appActions.refreshPicBeds()]) } catch (error) { console.error(error) } }) useIPCOn('syncPicBed', handleSyncPicBed) useEffect(() => { const timer = window.setTimeout(() => { setHistorySheetThumbnailReady(isHistoryOpen) }, 100) return () => window.clearTimeout(timer) }, [isHistoryOpen]) const handleLinkFormatChange = useMemoizedFn(async (nextFormat: LinkFormat) => { try { await settingsStoreActions.saveSettingsConfig({ pasteStyle: resolvePasteStyle(nextFormat) }) } catch (error) { toast.error(error instanceof Error ? error.message : t('OPERATION_FAILED')) } }) const handleUrlButtonClick = useMemoizedFn(async () => { setUrlDialogInitial(await buildUrlDialogInitialValue()) setUrlDialogOpen(true) }) return ( <>
event.preventDefault()} onDrop={(event) => { handleDrop(event).catch(console.error) }} >
{currentSelection ? (
) : null} {!hasVisibleProviders ? (
{t('DASHBOARD_NO_VISIBLE_PROVIDERS')}

{t('DASHBOARD_NO_VISIBLE_PROVIDERS_DESCRIPTION')}

) : (

{t('DASHBOARD_DROP_IMAGES_HERE')}

{t('DASHBOARD_OR')} {isUploading ? (
) : null}
)}
{isDesktopHistoryVisible ? ( ) : null} ) }