Show error modal if deserialization fails. (#226)

This fixes #213. It is not particularly accessible, but since it (hopefully) shouldn't be displayed too often, I'm going to merge it anyways for now--better an inaccessible modal than failing silently.
pull/228/head
Atul Varma 2021-09-23 16:04:25 -04:00 zatwierdzone przez GitHub
rodzic 9572aab1ed
commit 64f7ca7852
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
2 zmienionych plików z 68 dodań i 2 usunięć

Wyświetl plik

@ -45,6 +45,30 @@ export function createPageWithStateSearchParams(
return search;
}
const DeserializationErrorModal: React.FC = () => {
const [show, setShow] = useState(true);
if (!show) return null;
// TODO: This isn't accessible at all; it ought to trap keyboard focus,
// disappear when the user presses ESC, and so on.
return (
<div className="page-error">
<div>
<p>
Sorry, an error occurred when trying to load the composition on this
page.
</p>
<p>
Either its data is corrupted, or displaying it is no longer supported.
</p>
<button onClick={() => setShow(false)}>OK</button>
</div>
</div>
);
};
/**
* Create a component that represents a page which exposes some
* aspect of its state in the current URL, so that it can be
@ -84,13 +108,16 @@ export function createPageWithShareableState<T>({
*/
const [isInOnChange, setIsInOnChange] = useState(false);
/** The default state from th URL, which we'll pass into our component. */
/** The default state from the URL, which we'll pass into our component. */
let defaults: T = defaultValue;
let didDeserializeThrow = false;
try {
defaults = deserialize(state || "");
} catch (e) {
console.log(`Error deserializing state: ${e}`);
didDeserializeThrow = true;
}
const onChange = useCallback(
@ -115,7 +142,12 @@ export function createPageWithShareableState<T>({
}
}, [isInOnChange, state, latestState, key]);
return <Component key={key} defaults={defaults} onChange={onChange} />;
return (
<>
{didDeserializeThrow && <DeserializationErrorModal />}
<Component key={key} defaults={defaults} onChange={onChange} />
</>
);
};
return PageWithShareableState;

Wyświetl plik

@ -116,3 +116,37 @@ ul.navbar li:last-child {
.error {
color: red;
}
.page-error {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.75);
}
.page-error div {
background: crimson;
color: white;
padding: 2em;
max-width: 50em;
}
.page-error div p:first-child {
margin-top: 0;
}
.page-error div p:last-child {
margin-bottom: 0;
}
.page-error div button {
display: block;
width: 66%;
margin: 3em auto 0 auto;
text-align: center;
}