aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files/src/store/paths.ts
blob: 2993cc9d7041691bf29720ea704d5a8cfffb35d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
/**
 * 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 { defineStore } from 'pinia'
import { FileType, Folder, Node, getNavigation } from '@nextcloud/files'
import { subscribe } from '@nextcloud/event-bus'
import Vue from 'vue'
import logger from '../logger'

import { useFilesStore } from './files'

export const usePathsStore = function(...args) {
	const files = useFilesStore(...args)

	const store = defineStore('paths', {
		state: () => ({
			paths: {} as ServicesState,
		} as PathsStore),

		getters: {
			getPath: (state) => {
				return (service: string, path: string): FileSource|undefined => {
					if (!state.paths[service]) {
						return undefined
					}
					return state.paths[service][path]
				}
			},
		},

		actions: {
			addPath(payload: PathOptions) {
				// If it doesn't exists, init the service state
				if (!this.paths[payload.service]) {
					Vue.set(this.paths, payload.service, {})
				}

				// Now we can set the provided path
				Vue.set(this.paths[payload.service], payload.path, payload.source)
			},

			onCreatedNode(node: Node) {
				const service = getNavigation()?.active?.id || 'files'
				if (!node.fileid) {
					logger.error('Node has no fileid', { node })
					return
				}

				// Only add path if it's a folder
				if (node.type === FileType.Folder) {
					this.addPath({
						service,
						path: node.path,
						source: node.source,
					})
				}

				// 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)
					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
					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)
					return
				}

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

	const pathsStore = store(...args)
	// Make sure we only register the listeners once
	if (!pathsStore._initialized) {
		// TODO: watch folders to update paths?
		subscribe('files:node:created', pathsStore.onCreatedNode)
		// subscribe('files:node:deleted', pathsStore.onDeletedNode)
		// subscribe('files:node:moved', pathsStore.onMovedNode)

		pathsStore._initialized = true
	}

	return pathsStore
}