Skip to content

Commit

Permalink
feat(share-settings): improve canvas sharing with robust re-share and…
Browse files Browse the repository at this point in the history
… error handling

- Implement memoized reshare function to generate fresh share links
- Add comprehensive error handling for share operations
- Enhance copy link button with loading state and retry mechanism
- Refactor share access change logic with better error management
- Prevent duplicate share link generation and handle edge cases
  • Loading branch information
pftom committed Mar 10, 2025
1 parent 855c0f4 commit 0838f43
Showing 1 changed file with 103 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,65 @@ const ShareSettings = React.memo(({ canvasId }: ShareSettingsProps) => {
[shareRecord],
);

// Memoized function to re-share latest content before copying link
const reshareAndCopyLink = useCallback(async () => {
if (access === 'off') return;

try {
setUpdateLoading(true);

// Get the most recent share data before performing operations
const latestSharesData = await getClient().listShares({
query: { entityId: canvasId, entityType: 'canvas' },
});
const latestShareRecord = latestSharesData?.data?.data?.[0];

// Delete existing share if any
if (latestShareRecord?.shareId) {
await getClient().deleteShare({
body: { shareId: latestShareRecord.shareId },
});
}

// Create new share with latest content
const { data, error } = await getClient().createShare({
body: {
entityId: canvasId,
entityType: 'canvas',
allowDuplication: true,
},
});

if (data?.success && !error) {
await refetchShares();
// Get the updated share link
const updatedShareData = await getClient().listShares({
query: { entityId: canvasId, entityType: 'canvas' },
});

const updatedShareRecord = updatedShareData?.data?.data?.[0];
if (updatedShareRecord?.shareId) {
const newShareLink = getShareLink('canvas', updatedShareRecord.shareId);
navigator.clipboard.writeText(newShareLink);
message.success(t('shareContent.copyLinkSuccess'));
}
} else {
message.error(t('shareContent.copyLinkError') || 'Failed to generate new share link');
}
} catch (err) {
console.error('Error resharing canvas:', err);
message.error(t('shareContent.copyLinkError') || 'Failed to generate new share link');
} finally {
setUpdateLoading(false);
}
}, [canvasId, access, refetchShares, t]);

const buttons = useMemo(
() => [
{
label: 'copyLink',
icon: <IconLink className="w-3.5 h-3.5 flex items-center justify-center" />,
onClick: (link: string) => {
navigator.clipboard.writeText(link);
message.success(t('shareContent.copyLinkSuccess'));
},
onClick: () => reshareAndCopyLink(),
disabled: access === 'off',
},
// TODO: do not delete this
Expand All @@ -114,7 +164,7 @@ const ShareSettings = React.memo(({ canvasId }: ShareSettingsProps) => {
// disabled: false,
// },
],
[access, t],
[access, reshareAndCopyLink, t],
);

useEffect(() => {
Expand All @@ -128,30 +178,55 @@ const ShareSettings = React.memo(({ canvasId }: ShareSettingsProps) => {
async (value: ShareAccess) => {
setUpdateLoading(true);
let success: boolean;
if (value === 'off') {
const { data, error } = await getClient().deleteShare({
body: { shareId: shareRecord?.shareId },
});
success = data.success && !error;
} else {
const { data, error } = await getClient().createShare({
body: {
entityId: canvasId,
entityType: 'canvas',
allowDuplication: true,
},

try {
// Get the most recent share data before performing operations
const latestSharesData = await getClient().listShares({
query: { entityId: canvasId, entityType: 'canvas' },
});
success = data.success && !error;
}
setUpdateLoading(false);
const latestShareRecord = latestSharesData?.data?.data?.[0];

if (value === 'off') {
if (latestShareRecord?.shareId) {
const { data, error } = await getClient().deleteShare({
body: { shareId: latestShareRecord.shareId },
});
success = data.success && !error;
} else {
// No share to delete
success = true;
}
} else {
const { data, error } = await getClient().createShare({
body: {
entityId: canvasId,
entityType: 'canvas',
allowDuplication: true,
},
});
success = data.success && !error;
}

if (success) {
message.success(t('shareContent.updateCanvasPermissionSuccess'));
setAccess(value);
refetchShares();
if (success) {
message.success(t('shareContent.updateCanvasPermissionSuccess'));
setAccess(value);
await refetchShares();
} else {
message.error(
t('shareContent.updateCanvasPermissionError') || 'Failed to update sharing settings',
);
}
} catch (err) {
console.error('Error updating canvas permission:', err);
message.error(
t('shareContent.updateCanvasPermissionError') || 'Failed to update sharing settings',
);
success = false;
} finally {
setUpdateLoading(false);
}
},
[canvasId, access],
[canvasId, t, refetchShares],
);

const handleAccessChange = useCallback(
Expand Down Expand Up @@ -201,8 +276,9 @@ const ShareSettings = React.memo(({ canvasId }: ShareSettingsProps) => {
type="primary"
key={button.label}
icon={button.icon}
disabled={button.disabled}
onClick={() => button.onClick(shareLink)}
disabled={button.disabled || updateLoading}
loading={button.label === 'copyLink' && updateLoading}
onClick={() => button.onClick()}
>
{t(`shareContent.${button.label}`)}
</Button>
Expand Down

0 comments on commit 0838f43

Please sign in to comment.