✨ feat: Improve multiple file download function.
This commit is contained in:
parent
da459e2253
commit
95481b89f0
2 changed files with 94 additions and 14 deletions
|
|
@ -13,6 +13,7 @@ import io.vertx.core.http.CookieSameSite;
|
||||||
import io.vertx.core.http.HttpMethod;
|
import io.vertx.core.http.HttpMethod;
|
||||||
import io.vertx.core.http.HttpServerOptions;
|
import io.vertx.core.http.HttpServerOptions;
|
||||||
import io.vertx.core.http.HttpServerResponse;
|
import io.vertx.core.http.HttpServerResponse;
|
||||||
|
import io.vertx.core.json.JsonArray;
|
||||||
import io.vertx.core.json.JsonObject;
|
import io.vertx.core.json.JsonObject;
|
||||||
import io.vertx.ext.healthchecks.HealthCheckHandler;
|
import io.vertx.ext.healthchecks.HealthCheckHandler;
|
||||||
import io.vertx.ext.healthchecks.HealthChecks;
|
import io.vertx.ext.healthchecks.HealthChecks;
|
||||||
|
|
@ -140,6 +141,7 @@ public class HttpVerticle extends AbstractVerticle {
|
||||||
|
|
||||||
router.get("/file/preview").handler(this::handleFilePreview);
|
router.get("/file/preview").handler(this::handleFilePreview);
|
||||||
router.post("/file/start-download").handler(this::handleFileStartDownload);
|
router.post("/file/start-download").handler(this::handleFileStartDownload);
|
||||||
|
router.post("/file/start-download-multiple").handler(this::handleFileStartDownloadMultiple);
|
||||||
router.post("/file/cancel-download").handler(this::handleFileCancelDownload);
|
router.post("/file/cancel-download").handler(this::handleFileCancelDownload);
|
||||||
router.post("/file/toggle-pause-download").handler(this::handleFileTogglePauseDownload);
|
router.post("/file/toggle-pause-download").handler(this::handleFileTogglePauseDownload);
|
||||||
router.post("/file/auto-download").handler(this::handleAutoDownload);
|
router.post("/file/auto-download").handler(this::handleAutoDownload);
|
||||||
|
|
@ -315,11 +317,11 @@ public class HttpVerticle extends AbstractVerticle {
|
||||||
}
|
}
|
||||||
TelegramVerticle telegramVerticle = telegramVerticleOptional.get();
|
TelegramVerticle telegramVerticle = telegramVerticleOptional.get();
|
||||||
telegramVerticle.close(true)
|
telegramVerticle.close(true)
|
||||||
.onSuccess(r -> {
|
.onSuccess(r -> {
|
||||||
telegramVerticles.remove(telegramVerticle);
|
telegramVerticles.remove(telegramVerticle);
|
||||||
sessionTelegramVerticles.entrySet().removeIf(e -> e.getValue().equals(telegramVerticle));
|
sessionTelegramVerticles.entrySet().removeIf(e -> e.getValue().equals(telegramVerticle));
|
||||||
ctx.end();
|
ctx.end();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleTelegrams(RoutingContext ctx) {
|
private void handleTelegrams(RoutingContext ctx) {
|
||||||
|
|
@ -511,6 +513,36 @@ public class HttpVerticle extends AbstractVerticle {
|
||||||
.onFailure(ctx::fail);
|
.onFailure(ctx::fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleFileStartDownloadMultiple(RoutingContext ctx) {
|
||||||
|
TelegramVerticle telegramVerticle = getTelegramVerticle(ctx);
|
||||||
|
if (telegramVerticle == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject jsonObject = ctx.body().asJsonObject();
|
||||||
|
Long chatId = jsonObject.getLong("chatId");
|
||||||
|
JsonArray files = jsonObject.getJsonArray("files");
|
||||||
|
if (chatId == null || CollUtil.isEmpty(files)) {
|
||||||
|
ctx.fail(400);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future.any(files.stream()
|
||||||
|
.map(f -> {
|
||||||
|
JsonObject file = (JsonObject) f;
|
||||||
|
Long messageId = file.getLong("messageId");
|
||||||
|
Integer fileId = file.getInteger("fileId");
|
||||||
|
return telegramVerticle.startDownload(chatId, messageId, fileId);
|
||||||
|
})
|
||||||
|
.toList())
|
||||||
|
.onSuccess(ctx::json)
|
||||||
|
.onFailure(r -> {
|
||||||
|
log.error(r, "Failed to start download multiple files");
|
||||||
|
ctx.json(JsonObject.of("error", "Part of the files failed to start download"));
|
||||||
|
ctx.response().setStatusCode(400).end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void handleFileCancelDownload(RoutingContext ctx) {
|
private void handleFileCancelDownload(RoutingContext ctx) {
|
||||||
TelegramVerticle telegramVerticle = getTelegramVerticle(ctx);
|
TelegramVerticle telegramVerticle = getTelegramVerticle(ctx);
|
||||||
if (telegramVerticle == null) {
|
if (telegramVerticle == null) {
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import {
|
||||||
FileAudioIcon,
|
FileAudioIcon,
|
||||||
FileIcon,
|
FileIcon,
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
|
LoaderCircle,
|
||||||
LoaderPinwheel,
|
LoaderPinwheel,
|
||||||
VideoIcon,
|
VideoIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
|
|
@ -51,6 +52,8 @@ import FileNotFount from "@/components/file-not-found";
|
||||||
import FileExtra from "@/components/file-extra";
|
import FileExtra from "@/components/file-extra";
|
||||||
import useIsMobile from "@/hooks/use-is-mobile";
|
import useIsMobile from "@/hooks/use-is-mobile";
|
||||||
import FileStatus from "@/components/file-status";
|
import FileStatus from "@/components/file-status";
|
||||||
|
import useSWRMutation from "swr/mutation";
|
||||||
|
import { POST } from "@/lib/api";
|
||||||
|
|
||||||
interface FileListProps {
|
interface FileListProps {
|
||||||
accountId: string;
|
accountId: string;
|
||||||
|
|
@ -112,6 +115,28 @@ export function FileList({ accountId, chatId }: FileListProps) {
|
||||||
);
|
);
|
||||||
const { filters, handleFilterChange, isLoading, files, handleLoadMore } =
|
const { filters, handleFilterChange, isLoading, files, handleLoadMore } =
|
||||||
useFiles(accountId, chatId);
|
useFiles(accountId, chatId);
|
||||||
|
const {
|
||||||
|
trigger: startDownloadMultiple,
|
||||||
|
isMutating: startDownloadMultipleMutating,
|
||||||
|
} = useSWRMutation(
|
||||||
|
"/file/start-download-multiple",
|
||||||
|
(
|
||||||
|
key,
|
||||||
|
{
|
||||||
|
arg,
|
||||||
|
}: {
|
||||||
|
arg: {
|
||||||
|
chatId: number;
|
||||||
|
files: Array<{ messageId: number; fileId: number }>;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
) => POST(key, arg),
|
||||||
|
{
|
||||||
|
onSuccess: () => {
|
||||||
|
setSelectedFiles(new Set());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const observer = new IntersectionObserver(
|
const observer = new IntersectionObserver(
|
||||||
|
|
@ -182,7 +207,13 @@ export function FileList({ accountId, chatId }: FileListProps) {
|
||||||
if (selectedFiles.size === files.length) {
|
if (selectedFiles.size === files.length) {
|
||||||
setSelectedFiles(new Set());
|
setSelectedFiles(new Set());
|
||||||
} else {
|
} else {
|
||||||
setSelectedFiles(new Set(files.map((file) => file.id)));
|
setSelectedFiles(
|
||||||
|
new Set(
|
||||||
|
files
|
||||||
|
.filter((file) => file.downloadStatus === "idle")
|
||||||
|
.map((file) => file.id),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -296,16 +327,32 @@ export function FileList({ accountId, chatId }: FileListProps) {
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
//TODO implement download selected
|
void startDownloadMultiple({
|
||||||
|
chatId: Number(chatId),
|
||||||
|
files: Array.from(selectedFiles).map((id) => {
|
||||||
|
const file = files.find((f) => f.id === id);
|
||||||
|
return {
|
||||||
|
messageId: file?.messageId ?? 0,
|
||||||
|
fileId: file?.id ?? 0,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
disabled={Array.from(selectedFiles).every(
|
disabled={
|
||||||
(id) =>
|
selectedFiles.size === 0 || startDownloadMultipleMutating
|
||||||
files.find((f) => f.id === id)?.downloadStatus ===
|
}
|
||||||
"downloading",
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<Download className="mr-2 h-4 w-4" />
|
{startDownloadMultipleMutating ? (
|
||||||
Download Selected
|
<LoaderCircle
|
||||||
|
className="mr-2 h-4 w-4 animate-spin"
|
||||||
|
style={{ strokeWidth: "0.8px" }}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Download className="mr-2 h-4 w-4" />
|
||||||
|
Download Selected
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -350,6 +397,7 @@ export function FileList({ accountId, chatId }: FileListProps) {
|
||||||
<Checkbox
|
<Checkbox
|
||||||
checked={selectedFiles.has(file.id)}
|
checked={selectedFiles.has(file.id)}
|
||||||
onCheckedChange={() => handleSelectFile(file.id)}
|
onCheckedChange={() => handleSelectFile(file.id)}
|
||||||
|
disabled={file.downloadStatus !== "idle"}
|
||||||
/>
|
/>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
{columns.map((col) =>
|
{columns.map((col) =>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue