mirror of
https://github.com/nextcloud/server.git
synced 2026-02-03 20:41:22 -05:00
chore: update @nextcloud/files to v4.0.0-rc.0
- update library - adjust sidebar tab handling Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
parent
60a43694cc
commit
d3813798bf
14 changed files with 104 additions and 121 deletions
|
|
@ -11,7 +11,6 @@ import { t } from '@nextcloud/l10n'
|
|||
import wrap from '@vue/web-component-wrapper'
|
||||
import { createPinia, PiniaVuePlugin } from 'pinia'
|
||||
import Vue from 'vue'
|
||||
import FilesSidebarTab from './views/FilesSidebarTab.vue'
|
||||
import { registerCommentsPlugins } from './comments-activity-tab.ts'
|
||||
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
|
@ -30,28 +29,20 @@ if (loadState('comments', 'activityEnabled', false) && OCA?.Activity?.registerSi
|
|||
iconSvgInline: MessageReplyText,
|
||||
order: 50,
|
||||
tagName,
|
||||
enabled() {
|
||||
if (!window.customElements.get(tagName)) {
|
||||
setupSidebarTab()
|
||||
}
|
||||
return true
|
||||
async onInit() {
|
||||
const { default: FilesSidebarTab } = await import('./views/FilesSidebarTab.vue')
|
||||
|
||||
Vue.use(PiniaVuePlugin)
|
||||
Vue.mixin({ pinia: createPinia() })
|
||||
const webComponent = wrap(Vue, FilesSidebarTab)
|
||||
// In Vue 2, wrap doesn't support disabling shadow. Disable with a hack
|
||||
Object.defineProperty(webComponent.prototype, 'attachShadow', {
|
||||
value() { return this },
|
||||
})
|
||||
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
|
||||
get() { return this },
|
||||
})
|
||||
window.customElements.define(tagName, webComponent)
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup the sidebar tab as a web component
|
||||
*/
|
||||
function setupSidebarTab() {
|
||||
Vue.use(PiniaVuePlugin)
|
||||
Vue.mixin({ pinia: createPinia() })
|
||||
const webComponent = wrap(Vue, FilesSidebarTab)
|
||||
// In Vue 2, wrap doesn't support disabling shadow. Disable with a hack
|
||||
Object.defineProperty(webComponent.prototype, 'attachShadow', {
|
||||
value() { return this },
|
||||
})
|
||||
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
|
||||
get() { return this },
|
||||
})
|
||||
window.customElements.define(tagName, webComponent)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,24 +11,16 @@ import Comments from './Comments.vue'
|
|||
|
||||
const props = defineProps<{
|
||||
node?: INode
|
||||
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
active?: boolean
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
folder?: IFolder
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
view?: IView
|
||||
}>()
|
||||
|
||||
defineExpose({ setActive })
|
||||
|
||||
const resourceId = computed(() => props.node?.fileid)
|
||||
|
||||
/**
|
||||
* Set this tab as active
|
||||
*
|
||||
* @param active - The active state
|
||||
*/
|
||||
function setActive(active: boolean) {
|
||||
return active
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@
|
|||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { ISidebarTab, SidebarComponent } from '@nextcloud/files'
|
||||
import type { ISidebarTab } from '@nextcloud/files'
|
||||
|
||||
import { NcIconSvgWrapper, NcLoadingIcon } from '@nextcloud/vue'
|
||||
import { ref, toRef, watch, watchEffect } from 'vue'
|
||||
import { ref, toRef, watch } from 'vue'
|
||||
import NcAppSidebarTab from '@nextcloud/vue/components/NcAppSidebarTab'
|
||||
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
|
||||
import logger from '../../logger.ts'
|
||||
import { useActiveStore } from '../../store/active.ts'
|
||||
import { useSidebarStore } from '../../store/sidebar.ts'
|
||||
|
||||
|
|
@ -29,19 +30,31 @@ const sidebar = useSidebarStore()
|
|||
const activeStore = useActiveStore()
|
||||
|
||||
const loading = ref(true)
|
||||
watch(toRef(props, 'tab'), async () => {
|
||||
loading.value = true
|
||||
await window.customElements.whenDefined(props.tab.tagName)
|
||||
loading.value = false
|
||||
}, { immediate: true })
|
||||
|
||||
const tabElement = ref<SidebarComponent>()
|
||||
watchEffect(async () => {
|
||||
if (tabElement.value) {
|
||||
// Mark as active
|
||||
await tabElement.value.setActive?.(props.active)
|
||||
watch(toRef(props, 'active'), async (active) => {
|
||||
if (!active) {
|
||||
return
|
||||
}
|
||||
})
|
||||
|
||||
logger.debug('sidebar: activating files sidebar tab ' + props.tab.id, { tab: props.tab })
|
||||
loading.value = true
|
||||
try {
|
||||
if (!initializedTabs.has(props.tab.tagName)) {
|
||||
initializedTabs.add(props.tab.tagName)
|
||||
logger.debug('sidebar: initializing ' + props.tab.id)
|
||||
await props.tab.onInit?.()
|
||||
}
|
||||
logger.debug('sidebar: waiting for sidebar tab component becoming defined ' + props.tab.id)
|
||||
await window.customElements.whenDefined(props.tab.tagName)
|
||||
logger.debug('sidebar: tab component defined and loaded ' + props.tab.id)
|
||||
loading.value = false
|
||||
} catch (error) {
|
||||
logger.error('Failed to get sidebar tab web component', { error })
|
||||
}
|
||||
}, { immediate: true })
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
const initializedTabs = new Set<string>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
|
@ -61,7 +74,7 @@ watchEffect(async () => {
|
|||
<component
|
||||
:is="tab.tagName"
|
||||
v-else
|
||||
ref="tabElement"
|
||||
:active.prop="active"
|
||||
:node.prop="sidebar.currentNode"
|
||||
:folder.prop="activeStore.activeFolder"
|
||||
:view.prop="activeStore.activeView" />
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
function getTabs(context?: ISidebarContext) {
|
||||
let tabs = getSidebarTabs()
|
||||
if (context) {
|
||||
tabs = tabs.filter((tab) => tab.enabled(context))
|
||||
tabs = tabs.filter((tab) => tab.enabled === undefined || tab.enabled(context))
|
||||
}
|
||||
return tabs.sort((a, b) => a.order - b.order)
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ export const useSidebarStore = defineStore('sidebar', () => {
|
|||
function getActions(context?: ISidebarContext) {
|
||||
let actions = getSidebarActions()
|
||||
if (context) {
|
||||
actions = actions.filter((tab) => tab.enabled(context))
|
||||
actions = actions.filter((action) => action.enabled === undefined || action.enabled(context))
|
||||
}
|
||||
return actions.sort((a, b) => a.order - b.order)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@
|
|||
|
||||
import ShareVariant from '@mdi/svg/svg/share-variant.svg?raw'
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
import { registerSidebarTab } from '@nextcloud/files'
|
||||
import { getSidebar } from '@nextcloud/files'
|
||||
import { n, t } from '@nextcloud/l10n'
|
||||
import wrap from '@vue/web-component-wrapper'
|
||||
import Vue from 'vue'
|
||||
import FilesSidebarTab from './views/FilesSidebarTab.vue'
|
||||
import ExternalShareActions from './services/ExternalShareActions.js'
|
||||
import ShareSearch from './services/ShareSearch.js'
|
||||
import TabSections from './services/TabSections.js'
|
||||
|
|
@ -27,32 +26,25 @@ Vue.prototype.n = n
|
|||
|
||||
const tagName = 'files_sharing-sidebar-tab'
|
||||
|
||||
registerSidebarTab({
|
||||
getSidebar().registerTab({
|
||||
id: 'sharing',
|
||||
displayName: t('files_sharing', 'Sharing'),
|
||||
iconSvgInline: ShareVariant,
|
||||
order: 10,
|
||||
tagName,
|
||||
enabled() {
|
||||
if (!window.customElements.get(tagName)) {
|
||||
setupSidebarTab()
|
||||
}
|
||||
return true
|
||||
|
||||
async onInit() {
|
||||
const { default: FilesSidebarTab } = await import('./views/FilesSidebarTab.vue')
|
||||
|
||||
const webComponent = wrap(Vue, FilesSidebarTab)
|
||||
// In Vue 2, wrap doesn't support diseabling shadow. Disable with a hack
|
||||
Object.defineProperty(webComponent.prototype, 'attachShadow', {
|
||||
value() { return this },
|
||||
})
|
||||
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
|
||||
get() { return this },
|
||||
})
|
||||
|
||||
window.customElements.define(tagName, webComponent)
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Setup the sidebar tab as a web component
|
||||
*/
|
||||
function setupSidebarTab() {
|
||||
const webComponent = wrap(Vue, FilesSidebarTab)
|
||||
// In Vue 2, wrap doesn't support diseabling shadow. Disable with a hack
|
||||
Object.defineProperty(webComponent.prototype, 'attachShadow', {
|
||||
value() { return this },
|
||||
})
|
||||
Object.defineProperty(webComponent.prototype, 'shadowRoot', {
|
||||
get() { return this },
|
||||
})
|
||||
|
||||
window.customElements.define(tagName, webComponent)
|
||||
}
|
||||
|
|
@ -12,6 +12,9 @@ import FileInfo from '../services/FileInfo.ts'
|
|||
|
||||
const props = defineProps<{
|
||||
node?: INode
|
||||
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
active?: boolean
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
folder?: IFolder
|
||||
// eslint-disable-next-line vue/no-unused-properties -- Required on the web component interface
|
||||
|
|
|
|||
|
|
@ -10,10 +10,10 @@ import { isPublicShare } from '@nextcloud/sharing/public'
|
|||
import { defineAsyncComponent, defineCustomElement } from 'vue'
|
||||
|
||||
const tagName = 'files-versions_sidebar-tab'
|
||||
const FilesVersionsSidebarTab = defineAsyncComponent(() => import('./views/FilesVersionsSidebarTab.vue'))
|
||||
|
||||
registerSidebarTab({
|
||||
id: 'files_versions',
|
||||
tagName,
|
||||
order: 90,
|
||||
displayName: t('files_versions', 'Versions'),
|
||||
iconSvgInline: BackupRestore,
|
||||
|
|
@ -24,23 +24,13 @@ registerSidebarTab({
|
|||
if (node.type !== FileType.File) {
|
||||
return false
|
||||
}
|
||||
// setup tab
|
||||
setupTab()
|
||||
return true
|
||||
},
|
||||
tagName,
|
||||
|
||||
async onInit() {
|
||||
const FilesVersionsSidebarTab = defineAsyncComponent(() => import('./views/FilesVersionsSidebarTab.vue'))
|
||||
window.customElements.define(tagName, defineCustomElement(FilesVersionsSidebarTab, {
|
||||
shadowRoot: false,
|
||||
}))
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* Setup the custom element for the Files Versions sidebar tab.
|
||||
*/
|
||||
function setupTab() {
|
||||
if (window.customElements.get(tagName)) {
|
||||
// already defined
|
||||
return
|
||||
}
|
||||
|
||||
window.customElements.define(tagName, defineCustomElement(FilesVersionsSidebarTab, {
|
||||
shadowRoot: false,
|
||||
}))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
:key="row.items[0].version.mtime"
|
||||
:can-view="canView"
|
||||
:can-compare="canCompare"
|
||||
:load-preview="isActive"
|
||||
:load-preview="active"
|
||||
:version="row.items[0].version"
|
||||
:node="node"
|
||||
:is-current="row.items[0].version.mtime === currentVersionMtime"
|
||||
|
|
@ -57,15 +57,16 @@ import logger from '../utils/logger.ts'
|
|||
import { deleteVersion, fetchVersions, restoreVersion, setVersionLabel } from '../utils/versions.ts'
|
||||
|
||||
const props = defineProps<{
|
||||
node?: INode
|
||||
folder?: IFolder
|
||||
view?: IView
|
||||
active: boolean
|
||||
node: INode
|
||||
|
||||
// eslint-disable-next-line vue/no-unused-properties -- required by SidebarTab but we do not need it
|
||||
folder: IFolder
|
||||
// eslint-disable-next-line vue/no-unused-properties -- required by SidebarTab but we do not need it
|
||||
view: IView
|
||||
}>()
|
||||
|
||||
defineExpose({ setActive })
|
||||
|
||||
const isMobile = useIsMobile()
|
||||
const isActive = ref<boolean>(false)
|
||||
const versions = ref<Version[]>([])
|
||||
const loading = ref(false)
|
||||
const showVersionLabelForm = ref(false)
|
||||
|
|
@ -138,15 +139,6 @@ const canCompare = computed(() => {
|
|||
&& window.OCA.Viewer?.mimetypesCompare?.includes(props.node?.mime)
|
||||
})
|
||||
|
||||
/**
|
||||
* This method is called by the files app if the sidebar tab state changes.
|
||||
*
|
||||
* @param active - The new active state
|
||||
*/
|
||||
function setActive(active: boolean) {
|
||||
isActive.value = active
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle restored event from Version.vue
|
||||
*
|
||||
|
|
|
|||
8
build/frontend-legacy/package-lock.json
generated
8
build/frontend-legacy/package-lock.json
generated
|
|
@ -19,7 +19,7 @@
|
|||
"@nextcloud/capabilities": "^1.2.1",
|
||||
"@nextcloud/dialogs": "^7.1.0",
|
||||
"@nextcloud/event-bus": "^3.3.3",
|
||||
"@nextcloud/files": "^4.0.0-beta.9",
|
||||
"@nextcloud/files": "^4.0.0-rc.0",
|
||||
"@nextcloud/initial-state": "^3.0.0",
|
||||
"@nextcloud/l10n": "^3.4.1",
|
||||
"@nextcloud/logger": "^3.0.3",
|
||||
|
|
@ -3244,9 +3244,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@nextcloud/files": {
|
||||
"version": "4.0.0-beta.9",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0-beta.9.tgz",
|
||||
"integrity": "sha512-Mbcl+eO2PEsOkBmQIxHtol6O8uzesJYQYb5kIZiqyfJ0yProSqJaMIBkBmAjHUwv+EOjswwRSXhlc8A4DfuVSg==",
|
||||
"version": "4.0.0-rc.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-zg/TQH4oQQYlntzkcWokjKIkTX39maiYXceDYrE3OnzCYZv0IKmOH3+pQer58/Z9QfsU8huTnzHblhzVNsJvAA==",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^2.5.3",
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
"@nextcloud/capabilities": "^1.2.1",
|
||||
"@nextcloud/dialogs": "^7.1.0",
|
||||
"@nextcloud/event-bus": "^3.3.3",
|
||||
"@nextcloud/files": "^4.0.0-beta.9",
|
||||
"@nextcloud/files": "^4.0.0-rc.0",
|
||||
"@nextcloud/initial-state": "^3.0.0",
|
||||
"@nextcloud/l10n": "^3.4.1",
|
||||
"@nextcloud/logger": "^3.0.3",
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ module.exports = {
|
|||
files_sharing: {
|
||||
additionalScripts: path.join(__dirname, 'apps/files_sharing/src', 'additionalScripts.js'),
|
||||
collaboration: path.join(__dirname, 'apps/files_sharing/src', 'collaborationresourceshandler.js'),
|
||||
files_sharing_tab: path.join(__dirname, 'apps/files_sharing/src', 'files_sharing_tab.js'),
|
||||
files_sharing_tab: path.join(__dirname, 'apps/files_sharing/src', 'files-sidebar.ts'),
|
||||
init: path.join(__dirname, 'apps/files_sharing/src', 'init.ts'),
|
||||
'init-public': path.join(__dirname, 'apps/files_sharing/src', 'init-public.ts'),
|
||||
main: path.join(__dirname, 'apps/files_sharing/src', 'main.ts'),
|
||||
|
|
|
|||
|
|
@ -55,6 +55,9 @@ describe('Files: Sidebar', { testIsolation: true }, () => {
|
|||
.findByRole('heading', { name: 'file' })
|
||||
.should('be.visible')
|
||||
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(600) // wait for a bit to avoid flakiness
|
||||
|
||||
triggerActionForFile('folder', 'details')
|
||||
cy.get('[data-cy-sidebar]')
|
||||
.should('be.visible')
|
||||
|
|
@ -89,7 +92,11 @@ describe('Files: Sidebar', { testIsolation: true }, () => {
|
|||
// open the sidebar
|
||||
triggerActionForFile('file', 'details')
|
||||
// validate it is open
|
||||
cy.get('[data-cy-sidebar]').should('be.visible')
|
||||
cy.get('[data-cy-sidebar]')
|
||||
.should('be.visible')
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(600) // wait for a bit to avoid flakiness
|
||||
|
||||
// delete the file
|
||||
triggerActionForFile('file', 'delete')
|
||||
cy.wait('@deleteFile', { timeout: 10000 })
|
||||
|
|
@ -116,6 +123,9 @@ describe('Files: Sidebar', { testIsolation: true }, () => {
|
|||
cy.get('[data-cy-sidebar]').should('be.visible')
|
||||
cy.url().should('contain', `apps/files/files/${otherFileId}`)
|
||||
|
||||
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
||||
cy.wait(600) // wait for a bit to avoid flakiness
|
||||
|
||||
triggerActionForFile('other', 'delete')
|
||||
cy.wait('@deleteFile')
|
||||
|
||||
|
|
|
|||
8
package-lock.json
generated
8
package-lock.json
generated
|
|
@ -18,7 +18,7 @@
|
|||
"@nextcloud/capabilities": "^1.2.1",
|
||||
"@nextcloud/dialogs": "^7.2.0",
|
||||
"@nextcloud/event-bus": "^3.3.3",
|
||||
"@nextcloud/files": "^4.0.0-beta.9",
|
||||
"@nextcloud/files": "^4.0.0-rc.0",
|
||||
"@nextcloud/initial-state": "^3.0.0",
|
||||
"@nextcloud/l10n": "^3.4.1",
|
||||
"@nextcloud/logger": "^3.0.3",
|
||||
|
|
@ -2443,9 +2443,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@nextcloud/files": {
|
||||
"version": "4.0.0-beta.9",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0-beta.9.tgz",
|
||||
"integrity": "sha512-Mbcl+eO2PEsOkBmQIxHtol6O8uzesJYQYb5kIZiqyfJ0yProSqJaMIBkBmAjHUwv+EOjswwRSXhlc8A4DfuVSg==",
|
||||
"version": "4.0.0-rc.0",
|
||||
"resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0-rc.0.tgz",
|
||||
"integrity": "sha512-zg/TQH4oQQYlntzkcWokjKIkTX39maiYXceDYrE3OnzCYZv0IKmOH3+pQer58/Z9QfsU8huTnzHblhzVNsJvAA==",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@nextcloud/auth": "^2.5.3",
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
"@nextcloud/capabilities": "^1.2.1",
|
||||
"@nextcloud/dialogs": "^7.2.0",
|
||||
"@nextcloud/event-bus": "^3.3.3",
|
||||
"@nextcloud/files": "^4.0.0-beta.9",
|
||||
"@nextcloud/files": "^4.0.0-rc.0",
|
||||
"@nextcloud/initial-state": "^3.0.0",
|
||||
"@nextcloud/l10n": "^3.4.1",
|
||||
"@nextcloud/logger": "^3.0.3",
|
||||
|
|
|
|||
Loading…
Reference in a new issue