diff options
author | LASER-Yi <[email protected]> | 2022-08-23 12:45:27 +0800 |
---|---|---|
committer | LASER-Yi <[email protected]> | 2022-08-23 12:45:27 +0800 |
commit | 8eef455cc59193be0266612c42a66e5b413b3c38 (patch) | |
tree | 40e6a30e5dc310097b12389fb23bf55676454752 | |
parent | 0d39928a7b7b82d933d74c2593b04326b21774f9 (diff) | |
download | bazarr-1.1.1-beta.18.tar.gz bazarr-1.1.1-beta.18.zip |
Add support of showing confirmation when leaving settings page with unsaved changesv1.1.1-beta.18
-rw-r--r-- | frontend/src/pages/Settings/components/Layout.tsx | 13 | ||||
-rw-r--r-- | frontend/src/utilities/routers.ts | 40 |
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); +} |