Improve error handling: failing to parse items/collections + syncmanager

master
Tom Hacohen 4 years ago
parent 74f4409f56
commit b8442532e8

@ -46,10 +46,8 @@ export default function CalendarsMain() {
} }
(async () => { (async () => {
const colEntries = await decryptCollections(collections); const colEntries = await decryptCollections(collections);
// FIXME: handle failure to decrypt collections
const entries = await decryptItems(items); const entries = await decryptItems(items);
// FIXME: handle failure to decrypt items
for (const collection of colEntries) { for (const collection of colEntries) {
const items = entries.get(collection.collection.uid)!; const items = entries.get(collection.collection.uid)!;

@ -66,7 +66,6 @@ export default function CollectionChangeEntries(props: PropsType) {
if (items) { if (items) {
decryptItems(items) decryptItems(items)
.then((entries) => setEntries(entries.get(collection.uid))); .then((entries) => setEntries(entries.get(collection.uid)));
// FIXME: handle failure to decrypt items
} }
}, [items]); }, [items]);

@ -20,6 +20,7 @@ import { getCollectionManager } from "../etebase-helpers";
import { CachedCollection } from "../Pim/helpers"; import { CachedCollection } from "../Pim/helpers";
import CollectionMemberAddDialog from "./CollectionMemberAddDialog"; import CollectionMemberAddDialog from "./CollectionMemberAddDialog";
import Alert from "@material-ui/lab/Alert";
interface PropsType { interface PropsType {
collection: CachedCollection; collection: CachedCollection;
@ -30,15 +31,19 @@ export default function CollectionMembers(props: PropsType) {
const [members_, setMembers] = React.useState<Etebase.CollectionMember[]>(); const [members_, setMembers] = React.useState<Etebase.CollectionMember[]>();
const [revokeUser, setRevokeUser] = React.useState<string | null>(null); const [revokeUser, setRevokeUser] = React.useState<string | null>(null);
const [addMemberOpen, setAddMemberOpen] = React.useState(false); const [addMemberOpen, setAddMemberOpen] = React.useState(false);
// FIXME: add error handling const [error, setError] = React.useState<Error>();
const { collection, metadata } = props.collection; const { collection, metadata } = props.collection;
async function fetchMembers() { async function fetchMembers() {
const colMgr = getCollectionManager(etebase); const colMgr = getCollectionManager(etebase);
const memberManager = colMgr.getMemberManager(collection); const memberManager = colMgr.getMemberManager(collection);
const members = await memberManager.list(); try {
setMembers(members.data); const members = await memberManager.list();
setMembers(members.data);
} catch (e) {
setError(e);
}
} }
React.useEffect(() => { React.useEffect(() => {
@ -70,6 +75,11 @@ export default function CollectionMembers(props: PropsType) {
<> <>
<AppBarOverride title={`${metadata.name} - Members`} /> <AppBarOverride title={`${metadata.name} - Members`} />
<Container style={{ maxWidth: "30rem" }}> <Container style={{ maxWidth: "30rem" }}>
{error && (
<Alert color="error">
{error.toString()}
</Alert>
)}
{members ? {members ?
<List> <List>
<ListItem rightIcon={<IconMemberAdd />} onClick={() => setAddMemberOpen(true)}> <ListItem rightIcon={<IconMemberAdd />} onClick={() => setAddMemberOpen(true)}>

@ -37,16 +37,16 @@ export default function ContactsMain() {
const items = useItems(etebase, colType); const items = useItems(etebase, colType);
React.useEffect(() => { React.useEffect(() => {
if (items) { if (!collections || !items) {
decryptItems(items) return;
.then((entries) => setEntries(entries));
// FIXME: handle failure to decrypt items
}
if (collections) {
decryptCollections(collections)
.then((entries) => setCachedCollections(entries));
// FIXME: handle failure to decrypt collections
} }
(async () => {
const colEntries = await decryptCollections(collections);
const entries = await decryptItems(items);
setCachedCollections(colEntries);
setEntries(entries);
})();
}, [items, collections]); }, [items, collections]);
if (!entries || !cachedCollections) { if (!entries || !cachedCollections) {

@ -11,8 +11,8 @@ import * as Etebase from "etebase";
import { PimType } from "../pim-types"; import { PimType } from "../pim-types";
import { getCollectionManager } from "../etebase-helpers"; import { getCollectionManager } from "../etebase-helpers";
import { asyncDispatch } from "../store"; import { asyncDispatch, store } from "../store";
import { itemBatch } from "../store/actions"; import { itemBatch, appendError } from "../store/actions";
export const defaultColor = "#8BC34A"; export const defaultColor = "#8BC34A";
@ -32,10 +32,14 @@ export function getDecryptCollectionsFunction(_colType?: string) {
const entries: CachedCollection[] = []; const entries: CachedCollection[] = [];
if (collections) { if (collections) {
for (const collection of collections) { for (const collection of collections) {
entries.push({ try {
collection, entries.push({
metadata: await collection.getMeta(), collection,
}); metadata: await collection.getMeta(),
});
} catch (e) {
store.dispatch(appendError(e));
}
} }
} }
@ -54,10 +58,14 @@ export function getDecryptItemsFunction<T extends PimType>(_colType: string, par
const cur = new Map(); const cur = new Map();
entries.set(colUid, cur); entries.set(colUid, cur);
for (const item of col.values()) { for (const item of col.values()) {
const contact = parseFunc(await item.getContent(Etebase.OutputFormat.String)); try {
contact.collectionUid = colUid; const contact = parseFunc(await item.getContent(Etebase.OutputFormat.String));
contact.itemUid = item.uid; contact.collectionUid = colUid;
cur.set(item.uid, contact); contact.itemUid = item.uid;
cur.set(item.uid, contact);
} catch (e) {
store.dispatch(appendError(e));
}
} }
} }
} }

@ -37,16 +37,16 @@ export default function TasksMain() {
const items = useItems(etebase, colType); const items = useItems(etebase, colType);
React.useEffect(() => { React.useEffect(() => {
if (items) { if (!collections || !items) {
decryptItems(items) return;
.then((entries) => setEntries(entries));
// FIXME: handle failure to decrypt items
}
if (collections) {
decryptCollections(collections)
.then((entries) => setCachedCollections(entries));
// FIXME: handle failure to decrypt collections
} }
(async () => {
const colEntries = await decryptCollections(collections);
const entries = await decryptItems(items);
setCachedCollections(colEntries);
setEntries(entries);
})();
}, [items, collections]); }, [items, collections]);
if (!entries || !cachedCollections) { if (!entries || !cachedCollections) {

@ -168,7 +168,7 @@ export const performSync = createAction(
export const appendError = createAction( export const appendError = createAction(
"APPEND_ERROR", "APPEND_ERROR",
(_etesync: Etebase.Account, error: Error | Error[]) => { (error: Error | Error[]) => {
return Array.isArray(error) ? error : [error]; return Array.isArray(error) ? error : [error];
} }
); );

@ -6,7 +6,7 @@ import * as Etebase from "etebase";
import { store, StoreState } from "../store"; import { store, StoreState } from "../store";
import { credentialsSelector } from "../credentials"; import { credentialsSelector } from "../credentials";
import { setSyncCollection, setSyncGeneral, setCacheCollection, unsetCacheCollection, setCacheItemMulti } from "../store/actions"; import { setSyncCollection, setSyncGeneral, setCacheCollection, unsetCacheCollection, setCacheItemMulti, appendError } from "../store/actions";
const cachedSyncManager = new Map<string, SyncManager>(); const cachedSyncManager = new Map<string, SyncManager>();
export class SyncManager { export class SyncManager {
@ -105,7 +105,7 @@ export class SyncManager {
case 401: // INVALID TOKEN case 401: // INVALID TOKEN
case 403: // FORBIDDEN case 403: // FORBIDDEN
case 503: // UNAVAILABLE case 503: // UNAVAILABLE
// FIXME store.dispatch(addNonFatalError(this.etebase, e)); store.dispatch(appendError(e));
return null; return null;
} }
} }

Loading…
Cancel
Save