import * as React from 'react'; import { NavigationType, Page } from '../../models'; import { CommandLineIcon, PencilIcon, TrashIcon, ChevronDownIcon, XMarkIcon, EyeIcon, LanguageIcon, CheckIcon } from '@heroicons/react/24/outline'; import { useRecoilState, useRecoilValue } from 'recoil'; import { MultiSelectedItemsAtom, PagedItems, SelectedItemActionAtom, SelectedMediaFolderSelector, SettingsSelector } from '../../state'; import { ActionsBarItem } from './ActionsBarItem'; import { LocalizationKey, localize } from '../../../localization'; import { Alert } from '../Modals/Alert'; import { messageHandler } from '@estruyf/vscode/dist/client'; import { DashboardMessage } from '../../DashboardMessage'; import { CustomScript, ScriptType } from '../../../models'; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '../../../components/shadcn/Dropdown'; import { useFilesContext } from '../../providers/FilesProvider'; import { COMMAND_NAME, GeneralCommands } from '../../../constants'; import { RenameIcon } from '../../../components/icons/RenameIcon'; import { openFile } from '../../utils'; export interface IActionsBarProps { view: NavigationType; } export const ActionsBar: React.FunctionComponent = ({ view }: React.PropsWithChildren) => { const [selectedFiles, setSelectedFiles] = useRecoilState(MultiSelectedItemsAtom); const [, setSelectedItemAction] = useRecoilState(SelectedItemActionAtom); const [showAlert, setShowAlert] = React.useState(false); const selectedFolder = useRecoilValue(SelectedMediaFolderSelector); const settings = useRecoilValue(SettingsSelector); const { files } = useFilesContext(); const pagedItems = useRecoilValue(PagedItems); const viewFile = React.useCallback(() => { if (selectedFiles.length === 1) { if (view === NavigationType.Contents) { openFile(selectedFiles[0]); } else if (view === NavigationType.Media) { setSelectedItemAction({ path: selectedFiles[0], action: 'view' }) } } }, [selectedFiles]); const onDeleteConfirm = React.useCallback(() => { for (const file of selectedFiles) { if (file) { if (view === NavigationType.Contents) { messageHandler.send(DashboardMessage.deleteFile, file); } else if (view === NavigationType.Media) { messageHandler.send(DashboardMessage.deleteMedia, { file: file, folder: selectedFolder }); } } } setSelectedFiles([]); setShowAlert(false); }, [selectedFiles]); const runCustomScript = React.useCallback((script: CustomScript) => { for (const file of selectedFiles) { messageHandler.send(DashboardMessage.runCustomScript, { script, path: file }); } }, [selectedFiles]); const selectAllItems = React.useCallback(() => { const allSelected = [...selectedFiles, ...pagedItems]; setSelectedFiles(Array.from(new Set(allSelected))); }, [selectedFiles, pagedItems]); const hasAllItemsSelectedOnPage = React.useMemo(() => { const selectedItemsOnPage = selectedFiles.filter((file) => pagedItems.includes(file)); return selectedItemsOnPage.length >= pagedItems.length; }, [selectedFiles, pagedItems]); const languageActions = React.useMemo(() => { const actions: React.ReactNode[] = []; if (view === NavigationType.Contents && files.length > 0 && selectedFiles.length === 1) { const selectedItem = selectedFiles[0]; const page = ((files || []) as Page[]).find((f: Page) => f.fmFilePath === selectedItem); if (page?.fmLocale) { const locale = page.fmLocale; const translations = page.fmTranslations; actions.push( { messageHandler.send(GeneralCommands.toVSCode.runCommand, { command: COMMAND_NAME.i18n.create, args: selectedItem }) }}> {localize(LocalizationKey.commonTranslate)} ) if (translations && Object.keys(translations).length > 0) { const crntLocale = translations[locale.locale]; const otherLocales = Object.entries(translations).filter(([key]) => key !== locale.locale); if (otherLocales.length > 0) { actions.push( {localize(LocalizationKey.commonLanguages)} openFile(crntLocale.path)}> {crntLocale.locale.title || crntLocale.locale.locale} { otherLocales.map(([key, value]) => ( openFile(value.path)} > {value.locale.title || value.locale.locale} )) } ) } } } } return actions; }, [files, selectedFiles]); const customScriptActions = React.useMemo(() => { if (!settings?.scripts) { return null; } const { scripts } = settings; let crntScripts: CustomScript[] = []; if (view === NavigationType.Contents) { crntScripts = (scripts || []) .filter((script) => (script.type === undefined || script.type === ScriptType.Content) && !script.bulk && !script.hidden); } else if (view === NavigationType.Media) { crntScripts = (scripts || []) .filter((script) => script.type === ScriptType.MediaFile && !script.hidden); } if (crntScripts.length > 0) { return ( {localize(LocalizationKey.commonScripts)} { crntScripts.map((script) => ( runCustomScript(script)} > {script.title} )) } ); } return null; }, [view, settings?.scripts, selectedFiles]); return ( <>
1} onClick={viewFile} title={localize(LocalizationKey.commonView)} > { view === NavigationType.Contents && ( 1} onClick={() => { messageHandler.send(DashboardMessage.rename, selectedFiles[0]); setSelectedFiles([]); }} title={localize(LocalizationKey.commonRename)} > ) } { view === NavigationType.Media && ( <> 1} onClick={() => setSelectedItemAction({ path: selectedFiles[0], action: 'edit' })} title={localize(LocalizationKey.commonEdit)} > ) } {languageActions} {customScriptActions} setShowAlert(true)} title={localize(LocalizationKey.commonDelete)} >
{ selectedFiles.length > 0 && ( setSelectedFiles([])} title={localize(LocalizationKey.dashboardHeaderActionsBarItemsSelected, selectedFiles.length)} > ) }
{localize(LocalizationKey.dashboardHeaderActionsBarSelectAll)}
{showAlert && ( setShowAlert(false)} trigger={onDeleteConfirm} /> ) } ); };