diff options
Diffstat (limited to 'apps/files_sharing/src/files_actions/sharingStatusAction.ts')
-rw-r--r-- | apps/files_sharing/src/files_actions/sharingStatusAction.ts | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/apps/files_sharing/src/files_actions/sharingStatusAction.ts b/apps/files_sharing/src/files_actions/sharingStatusAction.ts new file mode 100644 index 00000000000..18fa46d2781 --- /dev/null +++ b/apps/files_sharing/src/files_actions/sharingStatusAction.ts @@ -0,0 +1,144 @@ +/** + * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ +import { getCurrentUser } from '@nextcloud/auth' +import { Node, View, registerFileAction, FileAction, Permission } from '@nextcloud/files' +import { translate as t } from '@nextcloud/l10n' +import { ShareType } from '@nextcloud/sharing' +import { isPublicShare } from '@nextcloud/sharing/public' + +import AccountGroupSvg from '@mdi/svg/svg/account-group-outline.svg?raw' +import AccountPlusSvg from '@mdi/svg/svg/account-plus-outline.svg?raw' +import LinkSvg from '@mdi/svg/svg/link.svg?raw' +import CircleSvg from '../../../../core/img/apps/circles.svg?raw' + +import { action as sidebarAction } from '../../../files/src/actions/sidebarAction' +import { generateAvatarSvg } from '../utils/AccountIcon' + +import './sharingStatusAction.scss' + +const isExternal = (node: Node) => { + return node.attributes?.['is-federated'] ?? false +} + +export const ACTION_SHARING_STATUS = 'sharing-status' +export const action = new FileAction({ + id: ACTION_SHARING_STATUS, + displayName(nodes: Node[]) { + const node = nodes[0] + const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[] + + if (shareTypes.length > 0 + || (node.owner !== getCurrentUser()?.uid || isExternal(node))) { + return t('files_sharing', 'Shared') + } + + return '' + }, + + title(nodes: Node[]) { + const node = nodes[0] + + if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) { + const ownerDisplayName = node?.attributes?.['owner-display-name'] + return t('files_sharing', 'Shared by {ownerDisplayName}', { ownerDisplayName }) + } + + const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[] + if (shareTypes.length > 1) { + return t('files_sharing', 'Shared multiple times with different people') + } + + const sharees = node.attributes.sharees?.sharee as { id: string, 'display-name': string, type: ShareType }[] | undefined + if (!sharees) { + // No sharees so just show the default message to create a new share + return t('files_sharing', 'Sharing options') + } + + const sharee = [sharees].flat()[0] // the property is sometimes weirdly normalized, so we need to compensate + switch (sharee.type) { + case ShareType.User: + return t('files_sharing', 'Shared with {user}', { user: sharee['display-name'] }) + case ShareType.Group: + return t('files_sharing', 'Shared with group {group}', { group: sharee['display-name'] ?? sharee.id }) + default: + return t('files_sharing', 'Shared with others') + } + }, + + iconSvgInline(nodes: Node[]) { + const node = nodes[0] + const shareTypes = Object.values(node?.attributes?.['share-types'] || {}).flat() as number[] + + // Mixed share types + if (Array.isArray(node.attributes?.['share-types']) && node.attributes?.['share-types'].length > 1) { + return AccountPlusSvg + } + + // Link shares + if (shareTypes.includes(ShareType.Link) + || shareTypes.includes(ShareType.Email)) { + return LinkSvg + } + + // Group shares + if (shareTypes.includes(ShareType.Group) + || shareTypes.includes(ShareType.RemoteGroup)) { + return AccountGroupSvg + } + + // Circle shares + if (shareTypes.includes(ShareType.Team)) { + return CircleSvg + } + + if (node.owner && (node.owner !== getCurrentUser()?.uid || isExternal(node))) { + return generateAvatarSvg(node.owner, isExternal(node)) + } + + return AccountPlusSvg + }, + + enabled(nodes: Node[]) { + if (nodes.length !== 1) { + return false + } + + // Do not leak information about users to public shares + if (isPublicShare()) { + return false + } + + const node = nodes[0] + const shareTypes = node.attributes?.['share-types'] + const isMixed = Array.isArray(shareTypes) && shareTypes.length > 0 + + // If the node is shared multiple times with + // different share types to the current user + if (isMixed) { + return true + } + + // If the node is shared by someone else + if (node.owner !== getCurrentUser()?.uid || isExternal(node)) { + return true + } + + return (node.permissions & Permission.SHARE) !== 0 + }, + + async exec(node: Node, view: View, dir: string) { + // You need read permissions to see the sidebar + if ((node.permissions & Permission.READ) !== 0) { + window.OCA?.Files?.Sidebar?.setActiveTab?.('sharing') + return sidebarAction.exec(node, view, dir) + } + return null + }, + + inline: () => true, + +}) + +registerFileAction(action) |