mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-18 09:35:20 +02:00
96 lines
3.1 KiB
TypeScript
96 lines
3.1 KiB
TypeScript
|
import * as React from 'react';
|
||
|
import { ShareInvitation } from '@joplin/lib/services/share/reducer';
|
||
|
import { Button, Card, Icon } from 'react-native-paper';
|
||
|
import { _ } from '@joplin/lib/locale';
|
||
|
import { useCallback, useState } from 'react';
|
||
|
import ShareService from '@joplin/lib/services/share/ShareService';
|
||
|
import shim from '@joplin/lib/shim';
|
||
|
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
|
||
|
import Folder from '@joplin/lib/models/Folder';
|
||
|
import { FolderEntity } from '@joplin/lib/services/database/types';
|
||
|
import Logger from '@joplin/utils/Logger';
|
||
|
import { ViewStyle } from 'react-native';
|
||
|
|
||
|
interface Props {
|
||
|
invitation: ShareInvitation;
|
||
|
processing: boolean;
|
||
|
containerStyle: ViewStyle;
|
||
|
}
|
||
|
|
||
|
const AcceptedIcon = (props: { size: number }) => <Icon {...props} source='account-multiple-check'/>;
|
||
|
|
||
|
const useFolderTitle = (folderId: string) => {
|
||
|
const [folderTitle, setFolderTitle] = useState(undefined);
|
||
|
|
||
|
useAsyncEffect(async event => {
|
||
|
let folder: FolderEntity|null = null;
|
||
|
|
||
|
// If the share was just accepted, the folder might not exist yet.
|
||
|
// In this case, check for the shared item multiple times.
|
||
|
while (!folder && !event.cancelled) {
|
||
|
folder = await Folder.load(folderId);
|
||
|
if (folder) {
|
||
|
setFolderTitle(folder.title);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
await new Promise<void>(resolve => {
|
||
|
shim.setTimeout(() => resolve(), 1000);
|
||
|
});
|
||
|
}
|
||
|
}, [folderId]);
|
||
|
|
||
|
return folderTitle ?? '...';
|
||
|
};
|
||
|
|
||
|
const logger = Logger.create('AcceptedShareItem');
|
||
|
|
||
|
const AcceptedShareItem: React.FC<Props> = props => {
|
||
|
const invitation = props.invitation;
|
||
|
const sharer = invitation.share.user;
|
||
|
|
||
|
const [leaving, setLeaving] = useState(false);
|
||
|
// The "leave share" button can be briefly visible after leaving a share.
|
||
|
// When this is the case, keep track of hasLeft to prevent clicking it.
|
||
|
const [hasLeft, setHasLeft] = useState(false);
|
||
|
|
||
|
const onLeaveShare = useCallback(async () => {
|
||
|
try {
|
||
|
setLeaving(true);
|
||
|
if (await shim.showConfirmationDialog(_('This will remove the notebook from your collection and you will no longer have access to its content. Do you wish to continue?'))) {
|
||
|
await ShareService.instance().leaveSharedFolder(invitation.share.folder_id, sharer.id);
|
||
|
setHasLeft(true);
|
||
|
}
|
||
|
} catch (error) {
|
||
|
logger.error('Failed to leave share', error);
|
||
|
await shim.showMessageBox(
|
||
|
_('Failed to leave share. Please verify that Joplin is connected to the internet and able to sync.\nError: %s', error),
|
||
|
{ buttons: [_('OK')] },
|
||
|
);
|
||
|
} finally {
|
||
|
setLeaving(false);
|
||
|
}
|
||
|
}, [invitation, sharer]);
|
||
|
|
||
|
const folderId = invitation.share.folder_id;
|
||
|
const folderTitle = useFolderTitle(folderId);
|
||
|
|
||
|
return <Card style={props.containerStyle}>
|
||
|
<Card.Title
|
||
|
left={AcceptedIcon}
|
||
|
title={_('Notebook: %s (%s)', folderTitle, folderId)}
|
||
|
subtitle={_('Share from %s (%s)', sharer.full_name, sharer.email)}
|
||
|
/>
|
||
|
<Card.Actions>
|
||
|
<Button
|
||
|
icon='share-off'
|
||
|
onPress={onLeaveShare}
|
||
|
disabled={props.processing || leaving || hasLeft}
|
||
|
loading={leaving || !folderTitle}
|
||
|
>{_('Leave share')}</Button>
|
||
|
</Card.Actions>
|
||
|
</Card>;
|
||
|
};
|
||
|
|
||
|
export default AcceptedShareItem;
|