Skip to content

Commit ab35c11

Browse files
committed
refactor(files_sharing): migrate to new Files Sidebar API
Signed-off-by: Ferdinand Thiessen <[email protected]>
1 parent 2954881 commit ab35c11

File tree

5 files changed

+90
-67
lines changed

5 files changed

+90
-67
lines changed

apps/files_sharing/src/files_actions/sharingStatusAction.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
import type { Node } from '@nextcloud/files'
6+
import type { INode } from '@nextcloud/files'
77

88
import AccountGroupSvg from '@mdi/svg/svg/account-group-outline.svg?raw'
99
import AccountPlusSvg from '@mdi/svg/svg/account-plus-outline.svg?raw'
1010
import LinkSvg from '@mdi/svg/svg/link.svg?raw'
1111
import { getCurrentUser } from '@nextcloud/auth'
1212
import { showError } from '@nextcloud/dialogs'
13-
import { FileAction, Permission, registerFileAction } from '@nextcloud/files'
13+
import { FileAction, getSidebar, Permission, registerFileAction } from '@nextcloud/files'
1414
import { translate as t } from '@nextcloud/l10n'
1515
import { ShareType } from '@nextcloud/sharing'
1616
import { isPublicShare } from '@nextcloud/sharing/public'
1717
import CircleSvg from '../../../../core/img/apps/circles.svg?raw'
18-
import { action as sidebarAction } from '../../../files/src/actions/sidebarAction.ts'
1918
import { generateAvatarSvg } from '../utils/AccountIcon.ts'
2019

2120
import './sharingStatusAction.scss'
2221

2322
/**
23+
* Check if the node is external (federated)
2424
*
25-
* @param node
25+
* @param node - The node to check
2626
*/
27-
function isExternal(node: Node) {
27+
function isExternal(node: INode) {
2828
return node.attributes?.['is-federated'] ?? false
2929
}
3030

@@ -136,12 +136,12 @@ export const action = new FileAction({
136136
&& (node.permissions & Permission.READ) !== 0
137137
},
138138

139-
async exec({ nodes, view, folder, contents }) {
139+
async exec({ nodes }) {
140140
// You need read permissions to see the sidebar
141141
const node = nodes[0]
142142
if ((node.permissions & Permission.READ) !== 0) {
143-
window.OCA?.Files?.Sidebar?.setActiveTab?.('sharing')
144-
sidebarAction.exec({ nodes, view, folder, contents })
143+
const sidebar = getSidebar()
144+
sidebar.open(node, 'sharing')
145145
return null
146146
}
147147

apps/files_sharing/src/files_sharing_tab.js

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,61 +5,54 @@
55

66
import ShareVariant from '@mdi/svg/svg/share-variant.svg?raw'
77
import { getCSPNonce } from '@nextcloud/auth'
8+
import { registerSidebarTab } from '@nextcloud/files'
89
import { n, t } from '@nextcloud/l10n'
10+
import wrap from '@vue/web-component-wrapper'
911
import Vue from 'vue'
12+
import FilesSidebarTab from './views/FilesSidebarTab.vue'
1013
import ExternalShareActions from './services/ExternalShareActions.js'
1114
import ShareSearch from './services/ShareSearch.js'
1215
import TabSections from './services/TabSections.js'
1316

1417
__webpack_nonce__ = getCSPNonce()
1518

1619
// Init Sharing Tab Service
17-
if (!window.OCA.Sharing) {
18-
window.OCA.Sharing = {}
19-
}
20+
window.OCA.Sharing ??= {}
2021
Object.assign(window.OCA.Sharing, { ShareSearch: new ShareSearch() })
2122
Object.assign(window.OCA.Sharing, { ExternalShareActions: new ExternalShareActions() })
2223
Object.assign(window.OCA.Sharing, { ShareTabSections: new TabSections() })
2324

2425
Vue.prototype.t = t
2526
Vue.prototype.n = n
2627

27-
// Init Sharing tab component
28-
let TabInstance = null
29-
30-
window.addEventListener('DOMContentLoaded', function() {
31-
if (OCA.Files && OCA.Files.Sidebar) {
32-
OCA.Files.Sidebar.registerTab(new OCA.Files.Sidebar.Tab({
33-
id: 'sharing',
34-
name: t('files_sharing', 'Sharing'),
35-
iconSvg: ShareVariant,
36-
37-
async mount(el, fileInfo, context) {
38-
const SharingTab = (await import('./views/SharingTab.vue')).default
39-
const View = Vue.extend(SharingTab)
40-
41-
if (TabInstance) {
42-
TabInstance.$destroy()
43-
}
44-
TabInstance = new View({
45-
// Better integration with vue parent component
46-
parent: context,
47-
})
48-
// Only mount after we have all the info we need
49-
await TabInstance.update(fileInfo)
50-
TabInstance.$mount(el)
51-
},
52-
53-
update(fileInfo) {
54-
TabInstance.update(fileInfo)
55-
},
56-
57-
destroy() {
58-
if (TabInstance) {
59-
TabInstance.$destroy()
60-
TabInstance = null
61-
}
62-
},
63-
}))
64-
}
28+
const tagName = 'files_sharing-sidebar-tab'
29+
30+
registerSidebarTab({
31+
id: 'sharing',
32+
displayName: t('files_sharing', 'Sharing'),
33+
iconSvgInline: ShareVariant,
34+
order: 10,
35+
tagName,
36+
enabled() {
37+
if (!window.customElements.get(tagName)) {
38+
setupSidebarTab()
39+
}
40+
return true
41+
},
6542
})
43+
44+
/**
45+
* Setup the sidebar tab as a web component
46+
*/
47+
function setupSidebarTab() {
48+
const webComponent = wrap(Vue, FilesSidebarTab)
49+
// In Vue 2, wrap doesn't support diseabling shadow. Disable with a hack
50+
Object.defineProperty(webComponent.prototype, 'attachShadow', {
51+
value() { return this },
52+
})
53+
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
54+
get() { return this },
55+
})
56+
57+
window.customElements.define(tagName, webComponent)
58+
}

apps/files/src/services/FileInfo.ts renamed to apps/files_sharing/src/services/FileInfo.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
/**
1+
/*!
22
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
/* eslint-disable jsdoc/require-jsdoc */
7-
8-
import type { Attribute, Node } from '@nextcloud/files'
6+
import type { Attribute, INode } from '@nextcloud/files'
97

108
interface RawLegacyFileInfo {
119
id: number
@@ -30,11 +28,16 @@ export type LegacyFileInfo = RawLegacyFileInfo & {
3028
get: (key: keyof RawLegacyFileInfo) => unknown
3129
isDirectory: () => boolean
3230
canEdit: () => boolean
33-
node: Node
31+
node: INode
3432
canDownload: () => boolean
3533
}
3634

37-
export default function(node: Node): LegacyFileInfo {
35+
/**
36+
* Convert Node to legacy file info
37+
*
38+
* @param node - The Node to convert
39+
*/
40+
export default function(node: INode): LegacyFileInfo {
3841
const rawFileInfo: RawLegacyFileInfo = {
3942
id: node.fileid!,
4043
path: node.dirname,
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<script setup lang="ts">
2+
import type { IFolder, INode, IView } from '@nextcloud/files'
3+
4+
import { computed } from 'vue'
5+
import SharingTab from './SharingTab.vue'
6+
import FileInfo from '../services/FileInfo.ts'
7+
8+
const props = defineProps<{
9+
node?: INode
10+
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
11+
folder?: IFolder
12+
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
13+
view?: IView
14+
}>()
15+
16+
const fileInfo = computed(() => props.node && FileInfo(props.node))
17+
</script>
18+
19+
<template>
20+
<SharingTab v-if="fileInfo" :file-info="fileInfo" />
21+
</template>

apps/files_sharing/src/views/SharingTab.vue

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ export default {
230230
231231
mixins: [ShareDetails],
232232
233+
props: {
234+
fileInfo: {
235+
type: Object,
236+
required: true,
237+
},
238+
},
239+
233240
data() {
234241
return {
235242
config: new Config(),
@@ -238,8 +245,6 @@ export default {
238245
expirationInterval: null,
239246
loading: true,
240247
241-
fileInfo: null,
242-
243248
// reshare Share object
244249
reshare: null,
245250
sharedWithMe: {},
@@ -328,18 +333,19 @@ export default {
328333
},
329334
},
330335
331-
methods: {
332-
/**
333-
* Update current fileInfo and fetch new data
334-
*
335-
* @param {object} fileInfo the current file FileInfo
336-
*/
337-
async update(fileInfo) {
338-
this.fileInfo = fileInfo
339-
this.resetState()
340-
this.getShares()
336+
watch: {
337+
fileInfo: {
338+
immediate: true,
339+
handler(newValue, oldValue) {
340+
if (oldValue?.id === undefined || oldValue?.id !== newValue?.id) {
341+
this.resetState()
342+
this.getShares()
343+
}
344+
},
341345
},
346+
},
342347
348+
methods: {
343349
/**
344350
* Get the existing shares infos
345351
*/

0 commit comments

Comments
 (0)