feat(files): move "reload" and "share" breadcrumb actions to menu

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2026-01-20 17:57:49 +01:00 committed by backportbot[bot]
parent 903aab54b4
commit 3187ddedd7
2 changed files with 59 additions and 88 deletions

View file

@ -17,9 +17,10 @@
dir="auto"
:to="section.to"
:force-icon-text="index === 0 && !isNarrow"
force-menu
:open.sync="isMenuOpen"
:title="titleForSection(index, section)"
:aria-description="ariaForSection(section)"
@click.native="onClick(section.to)"
@dragover.native="onDragOver($event, section.dir)"
@drop="onDrop($event, section.dir)">
<template v-if="index === 0" #icon>
@ -27,6 +28,26 @@
:size="20"
:svg="viewIcon" />
</template>
<template v-if="index === sections.length - 1" #menu-icon>
<NcIconSvgWrapper :path="isMenuOpen ? mdiChevronUp : mdiChevronDown" />
</template>
<template v-if="index === sections.length - 1" #default>
<!-- Sharing button -->
<NcActionButton v-if="canShare" close-after-click @click="openSharingSidebar">
<template #icon>
<NcIconSvgWrapper :path="mdiAccountPlus" />
</template>
{{ t('files', 'Share') }}
</NcActionButton>
<!-- Reload button -->
<NcActionButton close-after-click @click="$emit('reload')">
<template #icon>
<NcIconSvgWrapper :path="mdiReload" />
</template>
{{ t('files', 'Reload content') }}
</NcActionButton>
</template>
</NcBreadcrumb>
<!-- Forward the actions slot -->
@ -40,12 +61,16 @@
import type { Node } from '@nextcloud/files'
import type { FileSource } from '../types.ts'
import { mdiAccountPlus, mdiChevronDown, mdiChevronUp, mdiReload } from '@mdi/js'
import HomeSvg from '@mdi/svg/svg/home.svg?raw'
import { getCapabilities } from '@nextcloud/capabilities'
import { showError } from '@nextcloud/dialogs'
import { Permission } from '@nextcloud/files'
import { translate as t } from '@nextcloud/l10n'
import { getSidebar, Permission } from '@nextcloud/files'
import { t } from '@nextcloud/l10n'
import { isPublicShare } from '@nextcloud/sharing/public'
import { basename } from 'path'
import { defineComponent } from 'vue'
import { computed, defineComponent, ref, watch } from 'vue'
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
import NcBreadcrumb from '@nextcloud/vue/components/NcBreadcrumb'
import NcBreadcrumbs from '@nextcloud/vue/components/NcBreadcrumbs'
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
@ -64,6 +89,7 @@ export default defineComponent({
name: 'BreadCrumbs',
components: {
NcActionButton,
NcBreadcrumbs,
NcBreadcrumb,
NcIconSvgWrapper,
@ -89,6 +115,20 @@ export default defineComponent({
const { isNarrow } = useFileListWidth()
const views = useViews()
const isMenuOpen = ref(false)
watch(() => activeStore.activeFolder, () => {
isMenuOpen.value = false
})
const isSharingEnabled = (getCapabilities() as { files_sharing?: boolean })?.files_sharing !== undefined
const isPublic = isPublicShare()
const canShare = computed(() => {
return isSharingEnabled
&& !isPublic
&& activeStore.activeFolder
&& (activeStore.activeFolder.permissions & Permission.SHARE) !== 0
})
return {
activeStore,
draggingStore,
@ -97,8 +137,23 @@ export default defineComponent({
selectionStore,
uploaderStore,
canShare,
isMenuOpen,
isNarrow,
views,
openSharingSidebar,
mdiAccountPlus,
mdiChevronDown,
mdiChevronUp,
mdiReload,
}
/**
* Open the sharing sidebar for the current folder
*/
function openSharingSidebar() {
getSidebar().open(activeStore.activeFolder!, 'sharing')
}
},
@ -193,12 +248,6 @@ export default defineComponent({
}
},
onClick(to) {
if (to?.query?.dir === this.$route.query.dir) {
this.$emit('reload')
}
},
onDragOver(event: DragEvent, path: string) {
if (!event.dataTransfer) {
return

View file

@ -8,21 +8,6 @@
<!-- Current folder breadcrumbs -->
<BreadCrumbs :path="directory" @reload="fetchContent">
<template #actions>
<!-- Sharing button -->
<NcButton
v-if="canShare && !isNarrow"
:aria-label="shareButtonLabel"
:class="{ 'files-list__header-share-button--shared': shareButtonType }"
:title="shareButtonLabel"
class="files-list__header-share-button"
variant="tertiary"
@click="openSharingSidebar">
<template #icon>
<LinkIcon v-if="shareButtonType === ShareType.Link" />
<AccountPlusIcon v-else :size="20" />
</template>
</NcButton>
<!-- Uploader -->
<UploadPicker
v-if="canUpload && !isQuotaExceeded && currentFolder"
@ -168,7 +153,6 @@ import type { Route } from 'vue-router'
import type { UserConfig } from '../types.ts'
import { getCurrentUser } from '@nextcloud/auth'
import { getCapabilities } from '@nextcloud/capabilities'
import { showError, showSuccess, showWarning } from '@nextcloud/dialogs'
import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus'
import { Folder, getFileListActions, Permission, sortNodes } from '@nextcloud/files'
@ -188,10 +172,8 @@ import NcButton from '@nextcloud/vue/components/NcButton'
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
import AccountPlusIcon from 'vue-material-design-icons/AccountPlusOutline.vue'
import IconAlertCircleOutline from 'vue-material-design-icons/AlertCircleOutline.vue'
import ListViewIcon from 'vue-material-design-icons/FormatListBulletedSquare.vue'
import LinkIcon from 'vue-material-design-icons/Link.vue'
import IconReload from 'vue-material-design-icons/Reload.vue'
import ViewGridIcon from 'vue-material-design-icons/ViewGridOutline.vue'
import BreadCrumbs from '../components/BreadCrumbs.vue'
@ -215,8 +197,6 @@ import { humanizeWebDAVError } from '../utils/davUtils.ts'
import { defaultView } from '../utils/filesViews.ts'
import { getSummaryFor } from '../utils/fileUtils.ts'
const isSharingEnabled = (getCapabilities() as { files_sharing?: boolean })?.files_sharing !== undefined
export default defineComponent({
name: 'FilesList',
@ -225,7 +205,6 @@ export default defineComponent({
DragAndDropNotice,
FileListFilters,
FilesListVirtual,
LinkIcon,
ListViewIcon,
NcAppContent,
NcActions,
@ -234,7 +213,6 @@ export default defineComponent({
NcEmptyContent,
NcIconSvgWrapper,
NcLoadingIcon,
AccountPlusIcon,
UploadPicker,
ViewGridIcon,
IconAlertCircleOutline,
@ -436,37 +414,6 @@ export default defineComponent({
return { ...this.$route, query: { dir } }
},
shareTypesAttributes(): number[] | undefined {
if (!this.currentFolder?.attributes?.['share-types']) {
return undefined
}
return Object.values(this.currentFolder?.attributes?.['share-types'] || {}).flat() as number[]
},
shareButtonLabel() {
if (!this.shareTypesAttributes) {
return t('files', 'Share')
}
if (this.shareButtonType === ShareType.Link) {
return t('files', 'Shared by link')
}
return t('files', 'Shared')
},
shareButtonType(): ShareType | null {
if (!this.shareTypesAttributes) {
return null
}
// If all types are links, show the link icon
if (this.shareTypesAttributes.some((type) => type === ShareType.Link)) {
return ShareType.Link
}
return ShareType.User
},
gridViewButtonLabel() {
return this.userConfig.grid_view
? t('files', 'Switch to list view')
@ -484,14 +431,6 @@ export default defineComponent({
return this.currentFolder?.attributes?.['quota-available-bytes'] === 0
},
/**
* Check if current folder has share permissions
*/
canShare() {
return isSharingEnabled && !this.isPublic
&& this.currentFolder && (this.currentFolder.permissions & Permission.SHARE) !== 0
},
showCustomEmptyView() {
return !this.loading && this.isEmptyDir && this.currentView?.emptyView !== undefined
},
@ -763,15 +702,6 @@ export default defineComponent({
}
},
openSharingSidebar() {
if (!this.currentFolder) {
logger.debug('No current folder found for opening sharing sidebar')
return
}
this.sidebar.open(this.currentFolder, 'sharing')
},
toggleGridView() {
this.userConfigStore.update('grid_view', !this.userConfig.grid_view)
},
@ -865,14 +795,6 @@ export default defineComponent({
flex: 0 0;
}
&-share-button {
color: var(--color-text-maxcontrast) !important;
&--shared {
color: var(--color-main-text) !important;
}
}
&-actions {
min-width: fit-content !important;
margin-inline: calc(var(--default-grid-baseline) * 2);