import fuzzysort from 'fuzzysort'; import { BookmarkFolder } from 'pl-api'; import React, { useCallback, useDeferredValue, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; import { ListItem } from 'pl-fe/components/list'; import { RadioGroup, RadioItem } from 'pl-fe/components/radio'; import Emoji from 'pl-fe/components/ui/emoji'; import HStack from 'pl-fe/components/ui/hstack'; import Icon from 'pl-fe/components/ui/icon'; import Modal from 'pl-fe/components/ui/modal'; import Spinner from 'pl-fe/components/ui/spinner'; import Stack from 'pl-fe/components/ui/stack'; import Toggle from 'pl-fe/components/ui/toggle'; import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import { useFeatures } from 'pl-fe/hooks/use-features'; import { NewFolderForm } from 'pl-fe/pages/status-lists/bookmark-folders'; import { useAddBookmarkToFolder, useBookmarkFolders, useRemoveBookmarkFromFolder, useStatusBookmarkFolders } from 'pl-fe/queries/statuses/use-bookmark-folders'; import { useBookmarkStatus } from 'pl-fe/queries/statuses/use-status-interactions'; import { makeGetStatus } from 'pl-fe/selectors'; import type { BaseModalProps } from 'pl-fe/features/ui/components/modal-root'; interface SelectBookmarkFolderModalProps { statusId: string; } const search = (bookmarkFolders: Array, term: string) => { if (!term) return bookmarkFolders; return fuzzysort.go(term, bookmarkFolders, { key: 'name' }).map(result => result.obj); }; const SelectBookmarkFolderModal: React.FC = ({ statusId, onClose }) => { const getStatus = useCallback(makeGetStatus(), []); const status = useAppSelector(state => getStatus(state, { id: statusId }))!; const features = useFeatures(); const [selectedFolder, setSelectedFolder] = useState(status.bookmark_folder); const [searchTerm, setSearchTerm] = useState(''); const deferredSearchTerm = useDeferredValue(searchTerm); const handleSearchChange: React.ChangeEventHandler = e => { setSearchTerm(e.target.value); }; const { isFetching, data: bookmarkFolders } = useBookmarkFolders(data => data); const { data: selectedBookmarkFolders, isPending: fetchingSelectedBookmarkFolders } = useStatusBookmarkFolders(statusId); const { mutate: addBookmarkToFolder, isPending: addingBookmarkToFolder } = useAddBookmarkToFolder(statusId); const { mutate: removeBookmarkFromFolder, isPending: removingBookmarkFromFolder } = useRemoveBookmarkFromFolder(statusId); const { mutate: bookmarkStatus } = useBookmarkStatus(status.id); const onChange: React.ChangeEventHandler = e => { const folderId = e.target.value; setSelectedFolder(folderId); bookmarkStatus(folderId, { onSuccess: () => onClose('SELECT_BOOKMARK_FOLDER'), }); }; const onClickClose = () => { onClose('SELECT_BOOKMARK_FOLDER'); }; const toggleBookmarkFolder = (folderId: string) => { if (selectedBookmarkFolders?.includes(folderId)) { removeBookmarkFromFolder(folderId); } else { addBookmarkToFolder(folderId); } }; const filteredFolders = useMemo(() => { if (!bookmarkFolders) return []; const filtered = search(bookmarkFolders, deferredSearchTerm); return filtered; }, [bookmarkFolders, deferredSearchTerm]); let items; if (features.bookmarkFoldersMultiple) { items = (filteredFolders).map((folder) => ( {folder.emoji ? ( ) : } {folder.name} } > toggleBookmarkFolder(folder.id)} disabled={fetchingSelectedBookmarkFolders || addingBookmarkToFolder || removingBookmarkFromFolder} /> )); } else { items = [ } checked={selectedFolder === null} value='' />, ]; if (!isFetching) { items.push(...((filteredFolders).map((folder) => ( {folder.emoji ? ( ) : } {folder.name} } checked={selectedFolder === folder.id} value={folder.id} /> )))); } } const body = isFetching ? : ( {items} ); return ( } onClose={onClickClose} > {body} ); }; export { type SelectBookmarkFolderModalProps, SelectBookmarkFolderModal as default };