Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
fix(files): Ensure children are removed from folder and not duplicated
* Resolves #47904

We need to make sure that we only add one source (unique!) once as a child,
this is ensured by simply use a native `Set`.
Also we need to remove children on from folders when the `files:node:deleted`
event is emitted.

Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed Sep 20, 2024
commit 020b3ee25eea62db60646b7477c2e6fceeacbd1f
75 changes: 63 additions & 12 deletions apps/files/src/store/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { FileSource, PathsStore, PathOptions, ServicesState } from '../types'
import type { FileSource, PathsStore, PathOptions, ServicesState, Service } from '../types'
import { defineStore } from 'pinia'
import { FileType, Folder, Node, getNavigation } from '@nextcloud/files'
import { subscribe } from '@nextcloud/event-bus'
Expand Down Expand Up @@ -41,6 +41,57 @@ export const usePathsStore = function(...args) {
Vue.set(this.paths[payload.service], payload.path, payload.source)
},

deletePath(service: Service, path: string) {
// skip if service does not exist
if (!this.paths[service]) {
return
}

Vue.delete(this.paths[service], path)
},

onDeletedNode(node: Node) {
const service = getNavigation()?.active?.id || 'files'

if (node.type === FileType.Folder) {
// Delete the path
this.deletePath(
service,
node.path,
)
}

// Remove node from children
if (node.dirname === '/') {
const root = files.getRoot(service) as Folder & { _children?: string[] }
// ensure sources are unique
const children = new Set(root._children ?? [])
children.delete(node.source)
Vue.set(root, '_children', [...children.values()])
return
}

if (this.paths[service][node.dirname]) {
const parentSource = this.paths[service][node.dirname]
const parentFolder = files.getNode(parentSource) as Folder & { _children?: string[] }

if (!parentFolder) {
logger.error('Parent folder not found', { parentSource })
return
}

logger.debug('Path exists, removing from children', { parentFolder, node })

// ensure sources are unique
const children = new Set(parentFolder._children ?? [])
children.delete(node.source)
Vue.set(parentFolder, '_children', [...children.values()])
return
}

logger.debug('Parent path does not exists, skipping children update', { node })
},

onCreatedNode(node: Node) {
const service = getNavigation()?.active?.id || 'files'
if (!node.fileid) {
Expand All @@ -60,30 +111,30 @@ export const usePathsStore = function(...args) {
// Update parent folder children if exists
// If the folder is the root, get it and update it
if (node.dirname === '/') {
const root = files.getRoot(service)
if (!root._children) {
Vue.set(root, '_children', [])
}
root._children.push(node.source)
const root = files.getRoot(service) as Folder & { _children?: string[] }
// ensure sources are unique
const children = new Set(root._children ?? [])
children.add(node.source)
Vue.set(root, '_children', [...children.values()])
return
}

// If the folder doesn't exists yet, it will be
// fetched later and its children updated anyway.
if (this.paths[service][node.dirname]) {
const parentSource = this.paths[service][node.dirname]
const parentFolder = files.getNode(parentSource) as Folder
const parentFolder = files.getNode(parentSource) as Folder & { _children?: string[] }
logger.debug('Path already exists, updating children', { parentFolder, node })

if (!parentFolder) {
logger.error('Parent folder not found', { parentSource })
return
}

if (!parentFolder._children) {
Vue.set(parentFolder, '_children', [])
}
parentFolder._children.push(node.source)
// ensure sources are unique
const children = new Set(parentFolder._children ?? [])
children.add(node.source)
Vue.set(parentFolder, '_children', [...children.values()])
return
}

Expand All @@ -97,7 +148,7 @@ export const usePathsStore = function(...args) {
if (!pathsStore._initialized) {
// TODO: watch folders to update paths?
subscribe('files:node:created', pathsStore.onCreatedNode)
// subscribe('files:node:deleted', pathsStore.onDeletedNode)
subscribe('files:node:deleted', pathsStore.onDeletedNode)
// subscribe('files:node:moved', pathsStore.onMovedNode)

pathsStore._initialized = true
Expand Down
2 changes: 1 addition & 1 deletion apps/files/src/views/FilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -658,7 +658,7 @@ export default defineComponent({
},
filterDirContent() {
let nodes = this.dirContents
let nodes: INode[] = this.dirContents
for (const filter of this.filtersStore.sortedFilters) {
nodes = filter.filter(nodes)
}
Expand Down