mirror of
https://github.com/nextcloud/server.git
synced 2026-06-10 17:23:59 -04:00
Merge pull request #51937 from nextcloud/perf/filter-propfind
perf(files_sharing): do not emit second propfind for account filter
This commit is contained in:
commit
39dc22b9dd
4 changed files with 84 additions and 72 deletions
|
|
@ -36,14 +36,11 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { IAccountData } from '../filters/AccountFilter.ts'
|
||||
import type { IAccountData } from '../files_filters/AccountFilter.ts'
|
||||
|
||||
import { translate as t } from '@nextcloud/l10n'
|
||||
import { ShareType } from '@nextcloud/sharing'
|
||||
import { mdiAccountMultiple } from '@mdi/js'
|
||||
import { useBrowserLocation } from '@vueuse/core'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useNavigation } from '../../../files/src/composables/useNavigation.ts'
|
||||
|
||||
import FileListFilter from '../../../files/src/components/FileListFilter/FileListFilter.vue'
|
||||
import NcActionButton from '@nextcloud/vue/components/NcActionButton'
|
||||
|
|
@ -61,8 +58,6 @@ const emit = defineEmits<{
|
|||
(event: 'update:accounts', value: IAccountData[]): void
|
||||
}>()
|
||||
|
||||
const { currentView } = useNavigation()
|
||||
const currentLocation = useBrowserLocation()
|
||||
const accountFilter = ref('')
|
||||
const availableAccounts = ref<IUserSelectData[]>([])
|
||||
const selectedAccounts = ref<IUserSelectData[]>([])
|
||||
|
|
@ -105,53 +100,6 @@ watch(selectedAccounts, () => {
|
|||
emit('update:accounts', accounts)
|
||||
})
|
||||
|
||||
/**
|
||||
* Update the accounts owning nodes or have nodes shared to them
|
||||
* @param path The path inside the current view to load for accounts
|
||||
*/
|
||||
async function updateAvailableAccounts(path: string = '/') {
|
||||
availableAccounts.value = []
|
||||
if (!currentView.value) {
|
||||
return
|
||||
}
|
||||
|
||||
const { contents } = await currentView.value.getContents(path)
|
||||
const available = new Map<string, IUserSelectData>()
|
||||
for (const node of contents) {
|
||||
const owner = node.owner
|
||||
if (owner && !available.has(owner)) {
|
||||
available.set(owner, {
|
||||
id: owner,
|
||||
user: owner,
|
||||
displayName: node.attributes['owner-display-name'] ?? node.owner,
|
||||
})
|
||||
}
|
||||
|
||||
const sharees = node.attributes.sharees?.sharee
|
||||
if (sharees) {
|
||||
// ensure sharees is an array (if only one share then it is just an object)
|
||||
for (const sharee of [sharees].flat()) {
|
||||
// Skip link shares and other without user
|
||||
if (sharee.id === '') {
|
||||
continue
|
||||
}
|
||||
if (sharee.type !== ShareType.User && sharee.type !== ShareType.Remote) {
|
||||
continue
|
||||
}
|
||||
// Add if not already added
|
||||
if (!available.has(sharee.id)) {
|
||||
available.set(sharee.id, {
|
||||
id: sharee.id,
|
||||
user: sharee.id,
|
||||
displayName: sharee['display-name'],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
availableAccounts.value = [...available.values()]
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset this filter
|
||||
*/
|
||||
|
|
@ -159,18 +107,21 @@ function resetFilter() {
|
|||
selectedAccounts.value = []
|
||||
accountFilter.value = ''
|
||||
}
|
||||
defineExpose({ resetFilter, toggleAccount })
|
||||
|
||||
// When the current view changes or the current directory,
|
||||
// then we need to rebuild the available accounts
|
||||
watch([currentView, currentLocation], () => {
|
||||
if (currentView.value) {
|
||||
// we have no access to the files router here...
|
||||
const path = (currentLocation.value.search ?? '?dir=/').match(/(?<=&|\?)dir=([^&#]+)/)?.[1]
|
||||
resetFilter()
|
||||
updateAvailableAccounts(decodeURIComponent(path ?? '/'))
|
||||
}
|
||||
}, { immediate: true })
|
||||
/**
|
||||
* Update list of available accounts in current view.
|
||||
*
|
||||
* @param accounts - Accounts to use
|
||||
*/
|
||||
function setAvailableAccounts(accounts: IAccountData[]): void {
|
||||
availableAccounts.value = accounts.map(({ uid, displayName }) => ({ displayName, id: uid, user: uid }))
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
resetFilter,
|
||||
setAvailableAccounts,
|
||||
toggleAccount,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
|||
|
|
@ -4,8 +4,11 @@
|
|||
*/
|
||||
import type { IFileListFilterChip, INode } from '@nextcloud/files'
|
||||
|
||||
import { subscribe } from '@nextcloud/event-bus'
|
||||
import { FileListFilter, registerFileListFilter } from '@nextcloud/files'
|
||||
import { ShareType } from '@nextcloud/sharing'
|
||||
import Vue from 'vue'
|
||||
|
||||
import FileListFilterAccount from '../components/FileListFilterAccount.vue'
|
||||
|
||||
export interface IAccountData {
|
||||
|
|
@ -13,18 +16,28 @@ export interface IAccountData {
|
|||
displayName: string
|
||||
}
|
||||
|
||||
type CurrentInstance = Vue & { resetFilter: () => void, toggleAccount: (account: string) => void }
|
||||
type CurrentInstance = Vue & {
|
||||
resetFilter: () => void
|
||||
setAvailableAccounts: (accounts: IAccountData[]) => void
|
||||
toggleAccount: (account: string) => void
|
||||
}
|
||||
|
||||
/**
|
||||
* File list filter to filter by owner / sharee
|
||||
*/
|
||||
class AccountFilter extends FileListFilter {
|
||||
|
||||
private availableAccounts: IAccountData[]
|
||||
private currentInstance?: CurrentInstance
|
||||
private filterAccounts?: IAccountData[]
|
||||
|
||||
constructor() {
|
||||
super('files_sharing:account', 100)
|
||||
this.availableAccounts = []
|
||||
|
||||
subscribe('files:list:updated', ({ contents }) => {
|
||||
this.updateAvailableAccounts(contents)
|
||||
})
|
||||
}
|
||||
|
||||
public mount(el: HTMLElement) {
|
||||
|
|
@ -33,11 +46,11 @@ class AccountFilter extends FileListFilter {
|
|||
}
|
||||
|
||||
const View = Vue.extend(FileListFilterAccount as never)
|
||||
this.currentInstance = new View({
|
||||
el,
|
||||
})
|
||||
.$on('update:accounts', this.setAccounts.bind(this))
|
||||
this.currentInstance = new View({ el })
|
||||
.$on('update:accounts', (accounts?: IAccountData[]) => this.setAccounts(accounts))
|
||||
.$mount() as CurrentInstance
|
||||
this.currentInstance
|
||||
.setAvailableAccounts(this.availableAccounts)
|
||||
}
|
||||
|
||||
public filter(nodes: INode[]): INode[] {
|
||||
|
|
@ -70,6 +83,11 @@ class AccountFilter extends FileListFilter {
|
|||
this.currentInstance?.resetFilter()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set accounts that should be filtered.
|
||||
*
|
||||
* @param accounts - Account to filter or undefined if inactive.
|
||||
*/
|
||||
public setAccounts(accounts?: IAccountData[]) {
|
||||
this.filterAccounts = accounts
|
||||
let chips: IFileListFilterChip[] = []
|
||||
|
|
@ -85,6 +103,49 @@ class AccountFilter extends FileListFilter {
|
|||
this.filterUpdated()
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the accounts owning nodes or have nodes shared to them.
|
||||
*
|
||||
* @param nodes - The current content of the file list.
|
||||
*/
|
||||
protected updateAvailableAccounts(nodes: INode[]): void {
|
||||
const available = new Map<string, IAccountData>()
|
||||
|
||||
for (const node of nodes) {
|
||||
const owner = node.owner
|
||||
if (owner && !available.has(owner)) {
|
||||
available.set(owner, {
|
||||
uid: owner,
|
||||
displayName: node.attributes['owner-display-name'] ?? node.owner,
|
||||
})
|
||||
}
|
||||
|
||||
// ensure sharees is an array (if only one share then it is just an object)
|
||||
const sharees: { id: string, 'display-name': string, type: ShareType }[] = [node.attributes.sharees?.sharee].flat().filter(Boolean)
|
||||
for (const sharee of [sharees].flat()) {
|
||||
// Skip link shares and other without user
|
||||
if (sharee.id === '') {
|
||||
continue
|
||||
}
|
||||
if (sharee.type !== ShareType.User && sharee.type !== ShareType.Remote) {
|
||||
continue
|
||||
}
|
||||
// Add if not already added
|
||||
if (!available.has(sharee.id)) {
|
||||
available.set(sharee.id, {
|
||||
uid: sharee.id,
|
||||
displayName: sharee['display-name'],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.availableAccounts = [...available.values()]
|
||||
if (this.currentInstance) {
|
||||
this.currentInstance.setAvailableAccounts(this.availableAccounts)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
4
dist/files_sharing-init.js
vendored
4
dist/files_sharing-init.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files_sharing-init.js.map
vendored
2
dist/files_sharing-init.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue