diff --git a/src/ui/ExportDialog.tsx b/src/ui/ExportDialog.tsx index bacaf53..21ab71a 100644 --- a/src/ui/ExportDialog.tsx +++ b/src/ui/ExportDialog.tsx @@ -71,6 +71,7 @@ const ConversationSelect: FC = ({ }) => { const { t } = useTranslation() const [query, setQuery] = useState('') + const lastClickedIndex = useRef(-1) const filtered = useMemo(() => { const q = query.trim().toLowerCase() @@ -89,7 +90,10 @@ const ConversationSelect: FC = ({ className="SelectSearch" placeholder={t('Search')} value={query} - onInput={e => setQuery(e.currentTarget.value)} + onInput={(e) => { + lastClickedIndex.current = -1 + setQuery(e.currentTarget.value) + }} />
= ({ disabled={disabled} checked={allFilteredSelected} onCheckedChange={(checked) => { + lastClickedIndex.current = -1 setSelected(checked ? filtered.slice(0, EXPORT_LIMIT) : []) }} /> @@ -122,13 +127,36 @@ const ConversationSelect: FC = ({
    {loading && conversations.length === 0 &&
  • {t('Loading')}...
  • } {error &&
  • {t('Error')}: {error}
  • } - {filtered.map((c) => { + {filtered.map((c, index) => { const isSelected = selected.some(x => x.id === c.id) + const itemDisabled = disabled || (atCap && !isSelected) return ( -
  • +
  • { + if (itemDisabled) return + if (e.shiftKey && lastClickedIndex.current !== -1) { + e.preventDefault() + const start = Math.min(lastClickedIndex.current, index) + const end = Math.max(lastClickedIndex.current, index) + const rangeItems = filtered.slice(start, end + 1) + const newSelected = [...selected] + for (const item of rangeItems) { + if (!newSelected.some(x => x.id === item.id)) { + if (newSelected.length >= EXPORT_LIMIT) break + newSelected.push(item) + } + } + setSelected(newSelected) + return + } + lastClickedIndex.current = index + }} + > { if (checked && atCap) return