feat: add confirm dialog for leaving the page if an upload is in progress
This commit is contained in:
42
frontend/src/hooks/confirm-leave.hook.ts
Normal file
42
frontend/src/hooks/confirm-leave.hook.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { useRouter } from "next/router";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
const useConfirmLeave = ({
|
||||||
|
message,
|
||||||
|
enabled,
|
||||||
|
}: {
|
||||||
|
message: string;
|
||||||
|
enabled: boolean;
|
||||||
|
}) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!enabled) return;
|
||||||
|
|
||||||
|
// Show confirmation dialog when route changes
|
||||||
|
const handleRouteChange = () => {
|
||||||
|
const confirmLeave = window.confirm(message);
|
||||||
|
if (!confirmLeave) {
|
||||||
|
router.events.emit("routeChangeError");
|
||||||
|
throw "Route change aborted.";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show confirmation when the user tries to leave or reload the page
|
||||||
|
const handleBeforeUnload = (event: BeforeUnloadEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = message;
|
||||||
|
return message;
|
||||||
|
};
|
||||||
|
|
||||||
|
router.events.on("routeChangeStart", handleRouteChange);
|
||||||
|
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
router.events.off("routeChangeStart", handleRouteChange);
|
||||||
|
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||||
|
};
|
||||||
|
}, [router, message, enabled]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useConfirmLeave;
|
||||||
@@ -286,6 +286,8 @@ export default {
|
|||||||
// /upload
|
// /upload
|
||||||
"upload.title": "Upload",
|
"upload.title": "Upload",
|
||||||
|
|
||||||
|
"upload.notify.confirm-leave":
|
||||||
|
"Are you sure you want to leave this page? Your upload will be canceled.",
|
||||||
"upload.notify.generic-error":
|
"upload.notify.generic-error":
|
||||||
"An error occurred while finishing your share.",
|
"An error occurred while finishing your share.",
|
||||||
"upload.notify.count-failed": "{count} files failed to upload. Trying again.",
|
"upload.notify.count-failed": "{count} files failed to upload. Trying again.",
|
||||||
|
|||||||
@@ -2,12 +2,13 @@ import { LoadingOverlay } from "@mantine/core";
|
|||||||
import { useModals } from "@mantine/modals";
|
import { useModals } from "@mantine/modals";
|
||||||
import { GetServerSidePropsContext } from "next";
|
import { GetServerSidePropsContext } from "next";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import Meta from "../../../components/Meta";
|
||||||
import showErrorModal from "../../../components/share/showErrorModal";
|
import showErrorModal from "../../../components/share/showErrorModal";
|
||||||
|
import EditableUpload from "../../../components/upload/EditableUpload";
|
||||||
|
import useConfirmLeave from "../../../hooks/confirm-leave.hook";
|
||||||
|
import useTranslate from "../../../hooks/useTranslate.hook";
|
||||||
import shareService from "../../../services/share.service";
|
import shareService from "../../../services/share.service";
|
||||||
import { Share as ShareType } from "../../../types/share.type";
|
import { Share as ShareType } from "../../../types/share.type";
|
||||||
import useTranslate from "../../../hooks/useTranslate.hook";
|
|
||||||
import EditableUpload from "../../../components/upload/EditableUpload";
|
|
||||||
import Meta from "../../../components/Meta";
|
|
||||||
|
|
||||||
export function getServerSideProps(context: GetServerSidePropsContext) {
|
export function getServerSideProps(context: GetServerSidePropsContext) {
|
||||||
return {
|
return {
|
||||||
@@ -18,9 +19,15 @@ export function getServerSideProps(context: GetServerSidePropsContext) {
|
|||||||
const Share = ({ shareId }: { shareId: string }) => {
|
const Share = ({ shareId }: { shareId: string }) => {
|
||||||
const t = useTranslate();
|
const t = useTranslate();
|
||||||
const modals = useModals();
|
const modals = useModals();
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
const [isLoading, setIsLoading] = useState(true);
|
||||||
const [share, setShare] = useState<ShareType>();
|
const [share, setShare] = useState<ShareType>();
|
||||||
|
|
||||||
|
useConfirmLeave({
|
||||||
|
message: t("upload.notify.confirm-leave"),
|
||||||
|
enabled: isLoading,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
shareService
|
shareService
|
||||||
.getFromOwner(shareId)
|
.getFromOwner(shareId)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import FileList from "../../components/upload/FileList";
|
|||||||
import showCompletedUploadModal from "../../components/upload/modals/showCompletedUploadModal";
|
import showCompletedUploadModal from "../../components/upload/modals/showCompletedUploadModal";
|
||||||
import showCreateUploadModal from "../../components/upload/modals/showCreateUploadModal";
|
import showCreateUploadModal from "../../components/upload/modals/showCreateUploadModal";
|
||||||
import useConfig from "../../hooks/config.hook";
|
import useConfig from "../../hooks/config.hook";
|
||||||
|
import useConfirmLeave from "../../hooks/confirm-leave.hook";
|
||||||
import useTranslate from "../../hooks/useTranslate.hook";
|
import useTranslate from "../../hooks/useTranslate.hook";
|
||||||
import useUser from "../../hooks/user.hook";
|
import useUser from "../../hooks/user.hook";
|
||||||
import shareService from "../../services/share.service";
|
import shareService from "../../services/share.service";
|
||||||
@@ -39,6 +40,11 @@ const Upload = ({
|
|||||||
const [files, setFiles] = useState<FileUpload[]>([]);
|
const [files, setFiles] = useState<FileUpload[]>([]);
|
||||||
const [isUploading, setisUploading] = useState(false);
|
const [isUploading, setisUploading] = useState(false);
|
||||||
|
|
||||||
|
useConfirmLeave({
|
||||||
|
message: t("upload.notify.confirm-leave"),
|
||||||
|
enabled: isUploading,
|
||||||
|
});
|
||||||
|
|
||||||
const chunkSize = useRef(parseInt(config.get("share.chunkSize")));
|
const chunkSize = useRef(parseInt(config.get("share.chunkSize")));
|
||||||
|
|
||||||
maxShareSize ??= parseInt(config.get("share.maxSize"));
|
maxShareSize ??= parseInt(config.get("share.maxSize"));
|
||||||
|
|||||||
Reference in New Issue
Block a user