Skip to content

Commit

Permalink
fix(files): Ensure children are removed from folder and not duplicated
Browse files Browse the repository at this point in the history
* 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 authored and backportbot[bot] committed Sep 20, 2024
1 parent bade66e commit 5d6650f
Showing 1 changed file with 63 additions and 12 deletions.
75 changes: 63 additions & 12 deletions apps/files/src/store/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
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 @@ -58,6 +58,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 @@ -77,30 +128,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 @@ -114,7 +165,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

0 comments on commit 5d6650f

Please sign in to comment.