Skip to content

Commit

Permalink
cleaning up save error messages 🌀
Browse files Browse the repository at this point in the history
  • Loading branch information
dysbulic committed Jul 25, 2024
1 parent 56707ef commit a9e45c4
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 54 deletions.
72 changes: 46 additions & 26 deletions packages/web/components/Player/Profile/ComposeDBPromptModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
UnorderedList,
useToast,
} from '@metafam/ds';
import { ComposeDBProfile, profileMapping } from '@metafam/utils';
import { ComposeDBProfile, Maybe, profileMapping } from '@metafam/utils';
import React, { useCallback, useEffect, useMemo, useState } from 'react';

import { MetaLink } from '#components/Link';
Expand All @@ -24,31 +24,26 @@ import { Player } from '#graphql/autogen/hasura-sdk';
import { CeramicError } from '#lib/errors';
import { useWeb3 } from '#lib/hooks';
import { useComputeComposeDBImageMetadata } from '#lib/hooks/ceramic/useComputeComposeDBImageMetadata';
import { useSaveToComposeDB } from '#lib/hooks/ceramic/useSaveToComposeDB';
import { errorHandler } from '#utils/errorHandler';
import { EmptyProfileError, useSaveToComposeDB } from '#lib/hooks/ceramic/useSaveToComposeDB';
import { hasuraToComposeDBProfile } from '#utils/playerHelpers';
import { useEthersProvider } from '#lib/hooks/useEthersProvider';

export type ComposeDBPromptModalProps = {
player: Player;
isOpen: boolean;
onClose: () => void;
handleMigrationCompleted: (streamID: string) => void;
onCompleted: (streamID: Maybe<string>) => void;
};

const initialStatus = 'Loading profile image data…';

export const ComposeDBPromptModal: React.FC<ComposeDBPromptModalProps> = ({
player,
isOpen,
onClose,
handleMigrationCompleted,
onCompleted,
}) => {
const toast = useToast({
isClosable: true,
duration: 12000,
});
const [status, setStatus] = useState(initialStatus);
const { chainId } = useWeb3();

const { imageMetadata: profileImageMetadata } =
Expand All @@ -65,29 +60,39 @@ export const ComposeDBPromptModal: React.FC<ComposeDBPromptModalProps> = ({
return isAvatarLoaded && isBackgroundLoaded;
}, [backgroundImageMetadata, player.profile, profileImageMetadata]);

const prompt = {
migrateProfile: 'Port your profile data:',
loadImages: 'Loading profile image data…',
pushing: 'Pushing data to Ceramic…',
authenticating: 'Authenticating DID…',
get initial() {
return areImagesLoaded ? this.migrateProfile : this.loadImages;
}
}
const [status, setStatus] = useState(prompt.initial);

useEffect(() => {
if (areImagesLoaded) {
setStatus('Port your profile data');
setStatus(prompt.migrateProfile);
}
}, [areImagesLoaded]);

const { save: saveToComposeDB, status: saveStatus } = useSaveToComposeDB();

const persist = useCallback(
(values: ComposeDBProfile) => {
setStatus('Pushing Data to Ceramic…');
setStatus(prompt.pushing);
return saveToComposeDB(values);
},
[saveToComposeDB],
);

useEffect(() => {
if (saveStatus === 'authenticating') {
setStatus('Authenticating DID…');
setStatus(prompt.authenticating);
}
}, [saveStatus]);

const provider = useEthersProvider()
const onClick = useCallback(async () => {
if (!player.profile) {
toast({
Expand All @@ -97,34 +102,49 @@ export const ComposeDBPromptModal: React.FC<ComposeDBPromptModalProps> = ({
});
return;
}
let failure = null
let streamId = null
try {
const composeDBPayload = hasuraToComposeDBProfile(player.profile, {
profileImageURL: profileImageMetadata,
backgroundImageURL: backgroundImageMetadata,
});

const streamID = await persist(composeDBPayload);
streamId = await persist(composeDBPayload);

handleMigrationCompleted(streamID);
onClose();
toast({
title: 'ComposeDB Migration Complete',
description: `Your profile streamID is ${streamID}`,
description: `Your profile stream id is "${streamId}".`,
status: 'success',
});
failure = false
} catch (err) {
const heading = err instanceof CeramicError ? 'Ceramic Error' : 'Error';
toast({
title: heading,
description: (err as Error).message,
status: 'error',
});
errorHandler(err as Error);
setStatus(initialStatus);
if(err instanceof EmptyProfileError) {
failure = false
toast({
title: 'ComposeDB Migration Skipped',
description: err.message,
status: 'info',
});
} else {
failure = true
const heading = err instanceof CeramicError ? 'Ceramic Error' : 'Error';
toast({
title: heading,
description: (err as Error).message,
status: 'error',
});
setStatus(prompt.initial);
}
} finally {
if(!failure) {
onCompleted(streamId);
onClose();
}
}
}, [
backgroundImageMetadata,
handleMigrationCompleted,
onCompleted,
onClose,
persist,
player.profile,
Expand Down
4 changes: 2 additions & 2 deletions packages/web/components/Setup/SetupProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const SetupProfile: React.FC<PropsWithChildren> = ({ children }) => {
const { isOpen, onClose } = useDisclosure({ defaultIsOpen: true });
const { user } = useUser();

const handleMigrationCompleted = useCallback(() => {
const onCompleted = useCallback(() => {
router.push('/me');
}, [router]);

Expand All @@ -31,7 +31,7 @@ export const SetupProfile: React.FC<PropsWithChildren> = ({ children }) => {
{user?.profile && !user.ceramicProfileId ? (
<ComposeDBPromptModal
player={user}
{...{ isOpen, handleMigrationCompleted, onClose }}
{...{ isOpen, onCompleted, onClose }}
/>
) : null}
</PageContainer>
Expand Down
2 changes: 1 addition & 1 deletion packages/web/contexts/ComposeDBContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export const ComposeDBContextProvider: React.FC<PropsWithChildren> = ({
} finally {
setConnecting(false);
}
}, [createSession, disconnect ]);
}, [createSession, disconnect]);

return (
<ComposeDBContext.Provider
Expand Down
43 changes: 22 additions & 21 deletions packages/web/lib/hooks/ceramic/useSaveToComposeDB.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ import { useComposeDB } from '#lib/hooks/ceramic/useComposeDB';

export type SaveToComposeDBStatus = 'authenticating' | 'querying' | undefined;

export class EmptyProfileError extends Error {
constructor() {
super('No changes to be saved.');
}
}

export const useSaveToComposeDB = () => {
const { composeDBClient, connect } = useComposeDB();

Expand All @@ -31,6 +37,9 @@ export const useSaveToComposeDB = () => {

const save = useCallback(
async (values: ComposeDBProfile) => {
if(Object.keys(values).length === 0) {
throw new EmptyProfileError();
}
if (!composeDBClient) {
throw new CeramicError(
'Unable to connect to the Ceramic API to save changes.',
Expand Down Expand Up @@ -73,21 +82,20 @@ export const useSaveToComposeDB = () => {

// if a node was just created, persist in Hasura
if (!user.ceramicProfileId) {
const queryResponse = response.data?.[
user.ceramicProfileId ? 'updateProfile' : 'createProfile'
const { document: { id: documentId } } = response.data?.[
user.ceramicProfileId ? 'updateProfile' : 'setProfile'
] as ComposeDBCreateProfileResponseData;
const documentId = queryResponse?.document.id;
if (documentId) {
const { data } = await linkNode({ documentId });
if (!data?.linkCeramicProfileNode?.verified) {
throw new CeramicError(
`Could not link Ceramic node "${documentId}" to player`,
`Could not link Ceramic node "${documentId}" to player.`,
);
}
return documentId;
}
throw new CeramicError(
'No document ID was available in the createProfile response!',
'No document id was available in the profile response!',
);
}
return user.ceramicProfileId;
Expand All @@ -99,23 +107,16 @@ export const useSaveToComposeDB = () => {
};

const buildQuery = (existingCeramicNodeId?: Maybe<string>) => {
const query = existingCeramicNodeId
? `
mutation updateProfile($input: UpdateProfileInput!) {
updateProfile(input: $input) {
document {
id
}
}
}`
: `
mutation createProfile($input: CreateProfileInput!) {
createProfile(input: $input) {
document {
id
const type = !!existingCeramicNodeId ? 'update' : 'set'
const capitalized = `${type[0].toUpperCase()}${type.slice(1)}`
const query = `
mutation ${type}Profile($input: ${capitalized}ProfileInput!) {
${type}Profile(input: $input) {
document {
id
}
}
}
}`;

`
return query;
};
10 changes: 6 additions & 4 deletions packages/web/pages/player/[username].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ const PlayerPageContent: React.FC<{ ens?: string }> = ({ ens }) => {
[user, fetching, player.id],
);

const handleMigrationCompleted = useCallback(
(streamID: string) => {
hydrateFromComposeDB(streamID);
const onCompleted = useCallback(
(streamId: Maybe<string>) => {
if(streamId) {
hydrateFromComposeDB(streamId);
}
},
[hydrateFromComposeDB],
);
Expand Down Expand Up @@ -237,7 +239,7 @@ const PlayerPageContent: React.FC<{ ens?: string }> = ({ ens }) => {
{isOwnProfile && user?.profile && !user.ceramicProfileId ? (
<ComposeDBPromptModal
player={user}
{...{ isOpen, handleMigrationCompleted, onClose }}
{...{ isOpen, onCompleted, onClose }}
/>
) : null}
</PageContainer>
Expand Down

0 comments on commit a9e45c4

Please sign in to comment.