Skip to content

Commit 251503b

Browse files
committed
fix(files): fetch nodes if we have multiple of the same fileid in the store
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
1 parent 1d7893d commit 251503b

File tree

1 file changed

+47
-4
lines changed

1 file changed

+47
-4
lines changed

apps/files/src/store/files.ts

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,30 @@
22
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
5-
import type { Folder, Node } from '@nextcloud/files'
5+
66
import type { FilesStore, RootsStore, RootOptions, Service, FilesState, FileSource } from '../types'
7+
import type { FileStat, ResponseDataDetailed } from 'webdav'
8+
import type { Folder, Node } from '@nextcloud/files'
79

810
import { defineStore } from 'pinia'
9-
import { subscribe } from '@nextcloud/event-bus'
11+
import { subscribe, emit } from '@nextcloud/event-bus'
12+
import { davGetDefaultPropfind, davResultToNode, davRootPath } from '@nextcloud/files'
1013
import logger from '../logger'
1114
import Vue from 'vue'
1215

16+
import { client } from '../services/WebdavClient.ts'
17+
18+
window.emitEvent = emit
19+
20+
const fetchNode = async (node: Node): Promise<Node> => {
21+
const propfindPayload = davGetDefaultPropfind()
22+
const result = await client.stat(`${davRootPath}${node.path}`, {
23+
details: true,
24+
data: propfindPayload,
25+
}) as ResponseDataDetailed<FileStat>
26+
return davResultToNode(result.data)
27+
}
28+
1329
export const useFilesStore = function(...args) {
1430
const store = defineStore('files', {
1531
state: (): FilesState => ({
@@ -31,6 +47,13 @@ export const useFilesStore = function(...args) {
3147
.map(source => state.files[source])
3248
.filter(Boolean),
3349

50+
/**
51+
* Get files or folders by their file ID
52+
* Multiple nodes can have the same file ID but different sources
53+
* (e.g. in a shared context)
54+
*/
55+
getNodesById: (state) => (fileId: number): Node[] => Object.values(state.files).filter(node => node.fileid === fileId),
56+
3457
/**
3558
* Get the root folder of a service
3659
*/
@@ -73,8 +96,28 @@ export const useFilesStore = function(...args) {
7396
this.updateNodes([node])
7497
},
7598

76-
onUpdatedNode(node: Node) {
77-
this.updateNodes([node])
99+
async onUpdatedNode(node: Node) {
100+
if (!node.fileid) {
101+
logger.error('Trying to update/set a node without fileid', { node })
102+
return
103+
}
104+
105+
// If we have multiple nodes with the same file ID, we need to update all of them
106+
const nodes = this.getNodesById(node.fileid)
107+
if (nodes.length > 1) {
108+
await Promise.all(nodes.map(fetchNode)).then(this.updateNodes)
109+
logger.debug(nodes.length + ' nodes updated in store', { fileid: node.fileid })
110+
return
111+
}
112+
113+
// If we have only one node with the file ID, we can update it directly
114+
if (node.source === nodes[0].source) {
115+
this.updateNodes([node])
116+
return
117+
}
118+
119+
// Otherwise, it means we receive an event for a node that is not in the store
120+
fetchNode(node).then(n => this.updateNodes([n]))
78121
},
79122
},
80123
})

0 commit comments

Comments
 (0)