feat(files_sharing): provide web-components based sidebar API
This fixes apps providing vue components, which is invalid and does not always work - and never work with Vue 3. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>pull/54788/head
parent
c5a093d842
commit
ee962f3a37
@ -0,0 +1,71 @@
|
||||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<template>
|
||||
<component :is="action.element"
|
||||
:key="action.id"
|
||||
ref="actionElement"
|
||||
:share.prop="share"
|
||||
:node.prop="node"
|
||||
:on-save.prop="onSave" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { INode } from '@nextcloud/files'
|
||||
import type { IShare } from '@nextcloud/sharing'
|
||||
import type { ISidebarAction } from '@nextcloud/sharing/ui'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
import { ref, toRaw, watchEffect } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
action: {
|
||||
type: Object as PropType<ISidebarAction>,
|
||||
required: true,
|
||||
},
|
||||
node: {
|
||||
type: Object as PropType<INode>,
|
||||
required: true,
|
||||
},
|
||||
share: {
|
||||
type: Object as PropType<IShare | undefined>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
defineExpose({ save })
|
||||
|
||||
const actionElement = ref()
|
||||
const savingCallback = ref()
|
||||
|
||||
watchEffect(() => {
|
||||
if (!actionElement.value) {
|
||||
return
|
||||
}
|
||||
|
||||
// This seems to be only needed in Vue 2 as the .prop modifier does not really work on the vue 2 version of web components
|
||||
// TODO: Remove with Vue 3
|
||||
actionElement.value.node = toRaw(props.node)
|
||||
actionElement.value.onSave = onSave
|
||||
actionElement.value.share = toRaw(props.share)
|
||||
})
|
||||
|
||||
/**
|
||||
* The share is reset thus save the state of the component.
|
||||
*/
|
||||
async function save() {
|
||||
await savingCallback.value?.()
|
||||
}
|
||||
|
||||
/**
|
||||
* Vue does not allow to call methods on wrapped web components
|
||||
* so we need to pass it per callback.
|
||||
*
|
||||
* @param callback - The callback to be called on save
|
||||
*/
|
||||
function onSave(callback: () => Promise<void>) {
|
||||
savingCallback.value = callback
|
||||
}
|
||||
</script>
|
||||
@ -0,0 +1,33 @@
|
||||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<template>
|
||||
<component :is="section.element" ref="sectionElement" :node.prop="node" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import type { INode } from '@nextcloud/files'
|
||||
import type { ISidebarSection } from '@nextcloud/sharing/ui'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
import { ref, watchEffect } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
node: {
|
||||
type: Object as PropType<INode>,
|
||||
required: true,
|
||||
},
|
||||
section: {
|
||||
type: Object as PropType<ISidebarSection>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
// TOOD: Remove with Vue 3
|
||||
const sectionElement = ref()
|
||||
watchEffect(() => {
|
||||
sectionElement.value.node = props.node
|
||||
})
|
||||
</script>
|
||||
@ -0,0 +1,33 @@
|
||||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="sharing-tab-external-section-legacy">
|
||||
<component :is="component" :file-info="fileInfo" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, type Component, type PropType } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
fileInfo: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
sectionCallback: {
|
||||
type: Function as PropType<(el: HTMLElement | undefined, fileInfo: unknown) => Component>,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const component = computed(() => props.sectionCallback(undefined, props.fileInfo))
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.sharing-tab-external-section-legacy {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue