feat: Support remove file after downloaded

This commit is contained in:
jarvis2f 2025-02-10 10:58:07 +08:00
parent c30e318186
commit 1575a84a9b
5 changed files with 91 additions and 10 deletions

View file

@ -155,6 +155,7 @@ public class HttpVerticle extends AbstractVerticle {
router.post("/file/start-download-multiple").handler(this::handleFileStartDownloadMultiple);
router.post("/file/cancel-download").handler(this::handleFileCancelDownload);
router.post("/file/toggle-pause-download").handler(this::handleFileTogglePauseDownload);
router.post("/file/remove").handler(this::handleFileRemove);
router.post("/file/auto-download").handler(this::handleAutoDownload);
router.route()
@ -673,6 +674,24 @@ public class HttpVerticle extends AbstractVerticle {
.onFailure(ctx::fail);
}
private void handleFileRemove(RoutingContext ctx) {
TelegramVerticle telegramVerticle = getTelegramVerticle(ctx);
if (telegramVerticle == null) {
return;
}
JsonObject jsonObject = ctx.body().asJsonObject();
Integer fileId = jsonObject.getInteger("fileId");
if (fileId == null) {
ctx.fail(400);
return;
}
telegramVerticle.removeFile(fileId)
.onSuccess(r -> ctx.end())
.onFailure(ctx::fail);
}
private void handleAutoDownload(RoutingContext ctx) {
TelegramVerticle telegramVerticle = getTelegramVerticle(ctx);
if (telegramVerticle == null) {

View file

@ -17,7 +17,6 @@ import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.MultiMap;
import io.vertx.core.Promise;
import io.vertx.core.impl.NoStackTraceException;
import io.vertx.core.json.Json;
@ -452,6 +451,40 @@ public class TelegramVerticle extends AbstractVerticle {
.mapEmpty();
}
public Future<Void> removeFile(Integer fileId) {
return client.execute(new TdApi.GetFile(fileId))
.compose(file -> DataVerticle.fileRepository
.getByUniqueId(file.remote.uniqueId)
.map(fileRecord -> Tuple.tuple(file, fileRecord))
)
.compose(tuple2 -> {
TdApi.File file = tuple2.v1;
FileRecord fileRecord = tuple2.v2;
if (fileRecord == null) {
return Future.failedFuture("File not found");
}
if (fileRecord.isTransferStatus(FileRecord.TransferStatus.completed)) {
if (FileUtil.del(fileRecord.localPath())) {
log.debug("[%s] Remove file success: %s".formatted(this.getRootId(), fileRecord.localPath()));
}
}
if (file.local != null && StrUtil.isNotBlank(file.local.path)) {
return client.execute(new TdApi.DeleteFile(fileId))
.map(file);
}
return Future.succeededFuture(file);
})
.compose(file -> DataVerticle.fileRepository.deleteByUniqueId(file.remote.uniqueId).map(file))
.onSuccess(file -> sendEvent(EventPayload.build(EventPayload.TYPE_FILE_STATUS, new JsonObject()
.put("fileId", fileId)
.put("uniqueId", file.remote.uniqueId)
.put("removed", true)
)))
.mapEmpty();
}
public Future<Void> toggleAutoDownload(Long chatId, JsonObject params) {
return DataVerticle.settingRepository.<SettingAutoRecords>getByKey(SettingKey.autoDownload)
.compose(settingAutoRecords -> {

View file

@ -1,7 +1,7 @@
import { type DownloadStatus, type TelegramFile } from "@/lib/types";
import { useFileControl } from "@/hooks/use-file-control";
import { Button } from "@/components/ui/button";
import { ArrowDown, Loader2, Pause, SquareX, StepForward } from "lucide-react";
import {ArrowDown, FileX, Loader2, Pause, SquareX, StepForward} from "lucide-react";
import {
Tooltip,
TooltipContent,
@ -52,13 +52,9 @@ export default function FileControl({
!hovered &&
(file.downloadStatus === "downloading" || file.downloadStatus === "paused");
const { start, starting, togglePause, togglingPause, cancel, cancelling } =
const { start, starting, togglePause, togglingPause, cancel, cancelling, remove, removing } =
useFileControl(file);
if (file.downloadStatus === "completed") {
return null;
}
const statusMapping: Record<DownloadStatus, ActionButtonProps[]> = {
idle: [
{
@ -104,7 +100,14 @@ export default function FileControl({
loading: cancelling,
},
],
completed: [],
completed: [
{
onClick: () => remove(file.id),
tooltipText: "Remove",
icon: <FileX className="h-4 w-4" />,
loading: removing,
},
],
};
const actionButtons = (

View file

@ -21,6 +21,10 @@ export function useFileControl(file: TelegramFile) {
(key, { arg }: { arg: { fileId: number; isPaused: boolean } }) =>
POST(key, arg),
);
const { trigger: removeFile, isMutating: removing } = useSWRMutation(
"/file/remove",
(key, { arg }: { arg: { fileId: number } }) => POST(key, arg),
);
const downloadControl = {
cancel: (fileId: number) => {
@ -59,9 +63,15 @@ export function useFileControl(file: TelegramFile) {
});
}
},
remove: (fileId: number) => {
if (file && file.downloadStatus === "completed") {
void removeFile({ fileId });
}
},
cancelling,
starting,
togglingPause,
removing,
};
return {

View file

@ -30,8 +30,8 @@ export function useFiles(accountId: string, chatId: string) {
{
fileId: number;
downloadStatus: DownloadStatus;
localPath: string;
completionDate: number;
localPath?: string;
completionDate?: number;
downloadedSize: number;
transferStatus?: TransferStatus;
}
@ -89,8 +89,24 @@ export function useFiles(accountId: string, chatId: string) {
completionDate: number;
downloadedSize: number;
transferStatus?: TransferStatus;
removed?: boolean;
};
if (data.removed) {
setLatestFileStatus((prev) => ({
...prev,
[data.uniqueId]: {
fileId: data.fileId,
downloadStatus: "idle",
localPath: undefined,
completionDate: undefined,
downloadedSize: 0,
transferStatus: "idle",
},
}));
return;
}
setLatestFileStatus((prev) => ({
...prev,
[data.uniqueId]: {