Fix endless toast errors in Settings (#2146)

This commit is contained in:
WithoutPants
2021-12-22 10:43:30 +11:00
committed by GitHub
parent cfcc6aff6a
commit 523edfb575
2 changed files with 49 additions and 15 deletions

View File

@@ -92,10 +92,24 @@ export const SettingsContext: React.FC = ({ children }) => {
>(); >();
const [updateDLNAConfig] = useConfigureDLNA(); const [updateDLNAConfig] = useConfigureDLNA();
const [updateSuccess, setUpdateSuccess] = useState(false); const [updateSuccess, setUpdateSuccess] = useState<boolean | undefined>();
const [apiKey, setApiKey] = useState(""); const [apiKey, setApiKey] = useState("");
// cannot use Toast.error directly with the debounce functions
// since they are refreshed every time the Toast context is updated.
const [saveError, setSaveError] = useState<unknown>();
useEffect(() => {
if (!saveError) {
return;
}
Toast.error(saveError);
setSaveError(undefined);
setUpdateSuccess(false);
}, [saveError, Toast]);
useEffect(() => { useEffect(() => {
// only initialise once - assume we have control over these settings and // only initialise once - assume we have control over these settings and
// they aren't modified elsewhere // they aren't modified elsewhere
@@ -113,7 +127,7 @@ export const SettingsContext: React.FC = ({ children }) => {
const resetSuccess = useMemo( const resetSuccess = useMemo(
() => () =>
debounce(() => { debounce(() => {
setUpdateSuccess(false); setUpdateSuccess(undefined);
}, 4000), }, 4000),
[] []
); );
@@ -128,6 +142,7 @@ export const SettingsContext: React.FC = ({ children }) => {
() => () =>
debounce(async (input: GQL.ConfigGeneralInput) => { debounce(async (input: GQL.ConfigGeneralInput) => {
try { try {
setUpdateSuccess(undefined);
await updateGeneralConfig({ await updateGeneralConfig({
variables: { variables: {
input, input,
@@ -137,10 +152,10 @@ export const SettingsContext: React.FC = ({ children }) => {
setPendingGeneral(undefined); setPendingGeneral(undefined);
onSuccess(); onSuccess();
} catch (e) { } catch (e) {
Toast.error(e); setSaveError(e);
} }
}, 500), }, 500),
[Toast, updateGeneralConfig, onSuccess] [updateGeneralConfig, onSuccess]
); );
useEffect(() => { useEffect(() => {
@@ -177,6 +192,7 @@ export const SettingsContext: React.FC = ({ children }) => {
() => () =>
debounce(async (input: GQL.ConfigInterfaceInput) => { debounce(async (input: GQL.ConfigInterfaceInput) => {
try { try {
setUpdateSuccess(undefined);
await updateInterfaceConfig({ await updateInterfaceConfig({
variables: { variables: {
input, input,
@@ -186,10 +202,10 @@ export const SettingsContext: React.FC = ({ children }) => {
setPendingInterface(undefined); setPendingInterface(undefined);
onSuccess(); onSuccess();
} catch (e) { } catch (e) {
Toast.error(e); setSaveError(e);
} }
}, 500), }, 500),
[Toast, updateInterfaceConfig, onSuccess] [updateInterfaceConfig, onSuccess]
); );
useEffect(() => { useEffect(() => {
@@ -226,6 +242,7 @@ export const SettingsContext: React.FC = ({ children }) => {
() => () =>
debounce(async (input: GQL.ConfigDefaultSettingsInput) => { debounce(async (input: GQL.ConfigDefaultSettingsInput) => {
try { try {
setUpdateSuccess(undefined);
await updateDefaultsConfig({ await updateDefaultsConfig({
variables: { variables: {
input, input,
@@ -235,10 +252,10 @@ export const SettingsContext: React.FC = ({ children }) => {
setPendingDefaults(undefined); setPendingDefaults(undefined);
onSuccess(); onSuccess();
} catch (e) { } catch (e) {
Toast.error(e); setSaveError(e);
} }
}, 500), }, 500),
[Toast, updateDefaultsConfig, onSuccess] [updateDefaultsConfig, onSuccess]
); );
useEffect(() => { useEffect(() => {
@@ -275,6 +292,7 @@ export const SettingsContext: React.FC = ({ children }) => {
() => () =>
debounce(async (input: GQL.ConfigScrapingInput) => { debounce(async (input: GQL.ConfigScrapingInput) => {
try { try {
setUpdateSuccess(undefined);
await updateScrapingConfig({ await updateScrapingConfig({
variables: { variables: {
input, input,
@@ -284,10 +302,10 @@ export const SettingsContext: React.FC = ({ children }) => {
setPendingScraping(undefined); setPendingScraping(undefined);
onSuccess(); onSuccess();
} catch (e) { } catch (e) {
Toast.error(e); setSaveError(e);
} }
}, 500), }, 500),
[Toast, updateScrapingConfig, onSuccess] [updateScrapingConfig, onSuccess]
); );
useEffect(() => { useEffect(() => {
@@ -324,6 +342,7 @@ export const SettingsContext: React.FC = ({ children }) => {
() => () =>
debounce(async (input: GQL.ConfigDlnaInput) => { debounce(async (input: GQL.ConfigDlnaInput) => {
try { try {
setUpdateSuccess(undefined);
await updateDLNAConfig({ await updateDLNAConfig({
variables: { variables: {
input, input,
@@ -333,10 +352,10 @@ export const SettingsContext: React.FC = ({ children }) => {
setPendingDLNA(undefined); setPendingDLNA(undefined);
onSuccess(); onSuccess();
} catch (e) { } catch (e) {
Toast.error(e); setSaveError(e);
} }
}, 500), }, 500),
[Toast, updateDLNAConfig, onSuccess] [updateDLNAConfig, onSuccess]
); );
useEffect(() => { useEffect(() => {
@@ -369,6 +388,14 @@ export const SettingsContext: React.FC = ({ children }) => {
} }
function maybeRenderLoadingIndicator() { function maybeRenderLoadingIndicator() {
if (updateSuccess === false) {
return (
<div className="loading-indicator failed">
<Icon icon="times-circle" className="fa-fw" />
</div>
);
}
if ( if (
pendingGeneral || pendingGeneral ||
pendingInterface || pendingInterface ||
@@ -387,7 +414,7 @@ export const SettingsContext: React.FC = ({ children }) => {
if (updateSuccess) { if (updateSuccess) {
return ( return (
<div className="loading-indicator"> <div className="loading-indicator success">
<Icon icon="check-circle" className="fa-fw" /> <Icon icon="check-circle" className="fa-fw" />
</div> </div>
); );

View File

@@ -381,13 +381,20 @@
} }
.fa-icon { .fa-icon {
animation: fadeOut 2s forwards;
animation-delay: 2s;
color: $success; color: $success;
height: 2rem; height: 2rem;
margin: 0; margin: 0;
width: 2rem; width: 2rem;
} }
&.success .fa-icon {
animation: fadeOut 2s forwards;
animation-delay: 2s;
}
&.failed .fa-icon {
color: $danger;
}
} }
@keyframes fadeOut { @keyframes fadeOut {