aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_sharing/src/files_actions/sharingStatusAction.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_sharing/src/files_actions/sharingStatusAction.ts')
-rw-r--r--apps/files_sharing/src/files_actions/sharingStatusAction.ts144
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)