diff --git a/api/src/main/java/telegram/files/HttpVerticle.java b/api/src/main/java/telegram/files/HttpVerticle.java index 55f116f..be8e9e4 100644 --- a/api/src/main/java/telegram/files/HttpVerticle.java +++ b/api/src/main/java/telegram/files/HttpVerticle.java @@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.URLUtil; import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import io.vertx.core.*; @@ -413,10 +414,14 @@ public class HttpVerticle extends AbstractVerticle { ctx.fail(400); return; } + Map filter = new HashMap<>(); + ctx.request().params().forEach(filter::put); + filter.put("search", URLUtil.decode(filter.get("search"))); + long chatId = Convert.toLong(chatIdStr); getTelegramVerticle(telegramId) .ifPresentOrElse(telegramVerticle -> - telegramVerticle.getChatFiles(chatId, ctx.request().params()) + telegramVerticle.getChatFiles(chatId, filter) .onSuccess(ctx::json) .onFailure(ctx::fail), () -> ctx.fail(404)); diff --git a/api/src/main/java/telegram/files/TelegramVerticle.java b/api/src/main/java/telegram/files/TelegramVerticle.java index e8ebe80..1659850 100644 --- a/api/src/main/java/telegram/files/TelegramVerticle.java +++ b/api/src/main/java/telegram/files/TelegramVerticle.java @@ -175,12 +175,10 @@ public class TelegramVerticle extends AbstractVerticle { return this.convertChat(telegramChats.getChatList(activatedChatId, query, 100, archived)); } - public Future getChatFiles(long chatId, MultiMap filter) { + public Future getChatFiles(long chatId, Map filter) { String status = filter.get("status"); if (Arrays.asList("downloading", "paused", "completed", "error").contains(status)) { - Map filterMap = new HashMap<>(); - filter.forEach(filterMap::put); - return DataVerticle.fileRepository.getFiles(chatId, filterMap) + return DataVerticle.fileRepository.getFiles(chatId, filter) .compose(r -> { long[] messageIds = r.v1.stream().mapToLong(FileRecord::messageId).toArray(); return client.execute(new TdApi.GetMessages(chatId, messageIds)) diff --git a/web/src/components/file-filters.tsx b/web/src/components/file-filters.tsx index 90d63de..135a00a 100644 --- a/web/src/components/file-filters.tsx +++ b/web/src/components/file-filters.tsx @@ -13,6 +13,10 @@ import TableColumnFilter, { import { type RowHeight } from "@/components/table-row-height-switch"; import FileTypeFilter from "@/components/file-type-filter"; import dynamic from "next/dynamic"; +import { useDebouncedCallback } from "use-debounce"; +import { useEffect, useState } from "react"; +import { X } from "lucide-react"; +import { Button } from "./ui/button"; interface FileFiltersProps { telegramId: string; @@ -43,17 +47,37 @@ export function FileFilters({ rowHeight, setRowHeight, }: FileFiltersProps) { + const [search, setSearch] = useState(filters.search); + + const handleSearchChange = useDebouncedCallback((search: string) => { + onFiltersChange({ ...filters, search }); + }, 500); + + useEffect(() => { + handleSearchChange(search); + }, [search, handleSearchChange]); + return (
- - onFiltersChange({ ...filters, search: e.target.value }) - } - className="col-span-2 md:w-[300px]" - /> +
+ setSearch(e.target.value)} + className="relative col-span-2 md:w-[300px]" + /> + {search && ( + + )} +
{ + const params = new URLSearchParams({ + ...(filters.search && { search: window.encodeURIComponent(filters.search) }), + ...(filters.type && { type: filters.type }), + ...(filters.status && { status: filters.status }) + }); + if (page === 0) { - return `/telegram/${accountId}/chat/${chatId}/files?search=${filters.search}&type=${filters.type}&status=${filters.status}`; + return `/telegram/${accountId}/chat/${chatId}/files?${params.toString()}`; } if (!previousPageData) { return null; } - return `/telegram/${accountId}/chat/${chatId}/files?search=${filters.search}&type=${filters.type}&status=${filters.status}&fromMessageId=${previousPageData.nextFromMessageId}`; + params.set("fromMessageId", previousPageData.nextFromMessageId.toString()); + return `/telegram/${accountId}/chat/${chatId}/files?${params.toString()}`; }; const {