summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--frontend/src/pages/Settings/components/Layout.tsx13
-rw-r--r--frontend/src/utilities/routers.ts40
2 files changed, 52 insertions, 1 deletions
diff --git a/frontend/src/pages/Settings/components/Layout.tsx b/frontend/src/pages/Settings/components/Layout.tsx
index d79cd2eec..87ed5e80b 100644
--- a/frontend/src/pages/Settings/components/Layout.tsx
+++ b/frontend/src/pages/Settings/components/Layout.tsx
@@ -3,9 +3,10 @@ import { Toolbox } from "@/components";
import { LoadingProvider } from "@/contexts";
import { useOnValueChange } from "@/utilities";
import { LOG } from "@/utilities/console";
+import { usePrompt } from "@/utilities/routers";
import { useUpdateLocalStorage } from "@/utilities/storage";
import { faSave } from "@fortawesome/free-solid-svg-icons";
-import { Container, Group, LoadingOverlay } from "@mantine/core";
+import { Badge, Container, Group, LoadingOverlay } from "@mantine/core";
import { useDocumentTitle, useForm } from "@mantine/hooks";
import { FunctionComponent, ReactNode, useCallback, useMemo } from "react";
import { enabledLanguageKey, languageProfileKey } from "../keys";
@@ -84,6 +85,11 @@ const Layout: FunctionComponent<Props> = (props) => {
return Object.keys(object).length;
}, [form.values.settings, form.values.storages]);
+ usePrompt(
+ totalStagedCount > 0,
+ `You have ${totalStagedCount} unsaved changes, are you sure you want to leave?`
+ );
+
useDocumentTitle(`${name} - Bazarr (Settings)`);
if (settings === undefined) {
@@ -101,6 +107,11 @@ const Layout: FunctionComponent<Props> = (props) => {
icon={faSave}
loading={isMutating}
disabled={totalStagedCount === 0}
+ rightIcon={
+ <Badge size="xs" radius="sm" hidden={totalStagedCount === 0}>
+ {totalStagedCount}
+ </Badge>
+ }
>
Save
</Toolbox.Button>
diff --git a/frontend/src/utilities/routers.ts b/frontend/src/utilities/routers.ts
new file mode 100644
index 000000000..b3c91c541
--- /dev/null
+++ b/frontend/src/utilities/routers.ts
@@ -0,0 +1,40 @@
+// A workaround of built-in hooks in React-Router v6
+// https://gist.github.com/rmorse/426ffcc579922a82749934826fa9f743
+
+import type { Blocker, History, Transition } from "history";
+import { useContext, useEffect } from "react";
+import { UNSAFE_NavigationContext } from "react-router-dom";
+
+export function useBlocker(blocker: Blocker, when = true) {
+ const navigator = useContext(UNSAFE_NavigationContext).navigator as History;
+
+ useEffect(() => {
+ if (!when) return;
+
+ const unblock = navigator.block((tx: Transition) => {
+ const autoUnblockingTx = {
+ ...tx,
+ retry() {
+ // Automatically unblock the transition so it can play all the way
+ // through before retrying it. TODO: Figure out how to re-enable
+ // this block if the transition is cancelled for some reason.
+ unblock();
+ tx.retry();
+ },
+ };
+
+ blocker(autoUnblockingTx);
+ });
+
+ return unblock;
+ }, [navigator, blocker, when]);
+}
+
+// TODO: Replace with Mantine's confirmation modal
+export function usePrompt(when: boolean, message: string) {
+ useBlocker((tx) => {
+ if (window.confirm(message)) {
+ tx.retry();
+ }
+ }, when);
+}