Skip to content

Commit ad7e8b5

Browse files
committed
refactor(files): migrate from deprecated useNavigation to activeStore
Small preparation for upcoming Vue 3 migration of the files app. Signed-off-by: Ferdinand Thiessen <[email protected]>
1 parent 8a05a3e commit ad7e8b5

17 files changed

+216
-262
lines changed

apps/files/src/actions/moveOrCopyAction.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
/**
1+
/*!
22
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
5+
56
import type { IFilePickerButton } from '@nextcloud/dialogs'
6-
import type { Folder, Node } from '@nextcloud/files'
7+
import type { IFolder, INode } from '@nextcloud/files'
78
import type { FileStat, ResponseDataDetailed, WebDAVClientError } from 'webdav'
89
import type { MoveCopyResult } from './moveOrCopyActionUtils.ts'
910

@@ -14,7 +15,7 @@ import { FilePickerClosed, getFilePickerBuilder, showError, showInfo, TOAST_PERM
1415
import { emit } from '@nextcloud/event-bus'
1516
import { FileAction, FileType, getUniqueName, NodeStatus, Permission } from '@nextcloud/files'
1617
import { defaultRootPath, getClient, getDefaultPropfind, resultToNode } from '@nextcloud/files/dav'
17-
import { translate as t } from '@nextcloud/l10n'
18+
import { t } from '@nextcloud/l10n'
1819
import { hasConflict, openConflictPicker } from '@nextcloud/upload'
1920
import { basename, join } from 'path'
2021
import Vue from 'vue'
@@ -28,7 +29,7 @@ import { canCopy, canMove, getQueue, MoveCopyAction } from './moveOrCopyActionUt
2829
* @param nodes The nodes to check against
2930
* @return The action that is possible for the given nodes
3031
*/
31-
function getActionForNodes(nodes: Node[]): MoveCopyAction {
32+
function getActionForNodes(nodes: INode[]): MoveCopyAction {
3233
if (canMove(nodes)) {
3334
if (canCopy(nodes)) {
3435
return MoveCopyAction.MOVE_OR_COPY
@@ -76,7 +77,7 @@ function createLoadingNotification(mode: MoveCopyAction, source: string, destina
7677
* @param overwrite Whether to overwrite the destination if it exists
7778
* @return A promise that resolves when the copy/move is done
7879
*/
79-
export async function handleCopyMoveNodeTo(node: Node, destination: Folder, method: MoveCopyAction.COPY | MoveCopyAction.MOVE, overwrite = false) {
80+
export async function handleCopyMoveNodeTo(node: INode, destination: IFolder, method: MoveCopyAction.COPY | MoveCopyAction.MOVE, overwrite = false) {
8081
if (!destination) {
8182
return
8283
}
@@ -217,13 +218,13 @@ export async function handleCopyMoveNodeTo(node: Node, destination: Folder, meth
217218
async function openFilePickerForAction(
218219
action: MoveCopyAction,
219220
dir = '/',
220-
nodes: Node[],
221+
nodes: INode[],
221222
): Promise<MoveCopyResult | false> {
222223
const { resolve, reject, promise } = Promise.withResolvers<MoveCopyResult | false>()
223224
const fileIDs = nodes.map((node) => node.fileid).filter(Boolean)
224225
const filePicker = getFilePickerBuilder(t('files', 'Choose destination'))
225226
.allowDirectories(true)
226-
.setFilter((n: Node) => {
227+
.setFilter((n: INode) => {
227228
// We don't want to show the current nodes in the file picker
228229
return !fileIDs.includes(n.fileid)
229230
})
@@ -234,7 +235,7 @@ async function openFilePickerForAction(
234235
.setMimeTypeFilter([])
235236
.setMultiSelect(false)
236237
.startAt(dir)
237-
.setButtonFactory((selection: Node[], path: string) => {
238+
.setButtonFactory((selection: INode[], path: string) => {
238239
const buttons: IFilePickerButton[] = []
239240
const target = basename(path)
240241

@@ -246,9 +247,9 @@ async function openFilePickerForAction(
246247
label: target ? t('files', 'Copy to {target}', { target }, { escape: false, sanitize: false }) : t('files', 'Copy'),
247248
variant: 'primary',
248249
icon: CopyIconSvg,
249-
async callback(destination: Node[]) {
250+
async callback(destination: INode[]) {
250251
resolve({
251-
destination: destination[0] as Folder,
252+
destination: destination[0] as IFolder,
252253
action: MoveCopyAction.COPY,
253254
} as MoveCopyResult)
254255
},
@@ -276,9 +277,9 @@ async function openFilePickerForAction(
276277
label: target ? t('files', 'Move to {target}', { target }, undefined, { escape: false, sanitize: false }) : t('files', 'Move'),
277278
variant: action === MoveCopyAction.MOVE ? 'primary' : 'secondary',
278279
icon: FolderMoveSvg,
279-
async callback(destination: Node[]) {
280+
async callback(destination: INode[]) {
280281
resolve({
281-
destination: destination[0] as Folder,
282+
destination: destination[0] as IFolder,
282283
action: MoveCopyAction.MOVE,
283284
} as MoveCopyResult)
284285
},

apps/files/src/actions/moveOrCopyActionUtils.ts

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
/**
1+
/*!
22
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
import type { Folder, Node } from '@nextcloud/files'
6+
import type { IFolder, INode } from '@nextcloud/files'
77
import type { ShareAttribute } from '../../../files_sharing/src/sharing.ts'
88

99
import { Permission } from '@nextcloud/files'
@@ -36,35 +36,38 @@ export enum MoveCopyAction {
3636
}
3737

3838
export type MoveCopyResult = {
39-
destination: Folder
39+
destination: IFolder
4040
action: MoveCopyAction.COPY | MoveCopyAction.MOVE
4141
}
4242

4343
/**
44+
* Check if the given nodes can be moved
4445
*
45-
* @param nodes
46+
* @param nodes - The nodes to check
4647
*/
47-
export function canMove(nodes: Node[]) {
48+
export function canMove(nodes: INode[]) {
4849
const minPermission = nodes.reduce((min, node) => Math.min(min, node.permissions), Permission.ALL)
4950
return Boolean(minPermission & Permission.DELETE)
5051
}
5152

5253
/**
54+
* Check if the given nodes can be downloaded
5355
*
54-
* @param nodes
56+
* @param nodes - The nodes to check
5557
*/
56-
export function canDownload(nodes: Node[]) {
58+
export function canDownload(nodes: INode[]) {
5759
return nodes.every((node) => {
5860
const shareAttributes = JSON.parse(node.attributes?.['share-attributes'] ?? '[]') as Array<ShareAttribute>
5961
return !shareAttributes.some((attribute) => attribute.scope === 'permissions' && attribute.value === false && attribute.key === 'download')
6062
})
6163
}
6264

6365
/**
66+
* Check if the given nodes can be copied
6467
*
65-
* @param nodes
68+
* @param nodes - The nodes to check
6669
*/
67-
export function canCopy(nodes: Node[]) {
70+
export function canCopy(nodes: INode[]) {
6871
// a shared file cannot be copied if the download is disabled
6972
if (!canDownload(nodes)) {
7073
return false

apps/files/src/components/BreadCrumbs.vue

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,10 @@ import NcBreadcrumb from '@nextcloud/vue/components/NcBreadcrumb'
5050
import NcBreadcrumbs from '@nextcloud/vue/components/NcBreadcrumbs'
5151
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
5252
import { useFileListWidth } from '../composables/useFileListWidth.ts'
53-
import { useNavigation } from '../composables/useNavigation.ts'
53+
import { useViews } from '../composables/useViews.ts'
5454
import logger from '../logger.ts'
5555
import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts'
56+
import { useActiveStore } from '../store/active.ts'
5657
import { useDragAndDropStore } from '../store/dragging.ts'
5758
import { useFilesStore } from '../store/files.ts'
5859
import { usePathsStore } from '../store/paths.ts'
@@ -76,22 +77,24 @@ export default defineComponent({
7677
},
7778
7879
setup() {
79-
const draggingStore = useDragAndDropStore()
80+
const activeStore = useActiveStore()
8081
const filesStore = useFilesStore()
8182
const pathsStore = usePathsStore()
83+
const draggingStore = useDragAndDropStore()
8284
const selectionStore = useSelectionStore()
8385
const uploaderStore = useUploaderStore()
86+
8487
const fileListWidth = useFileListWidth()
85-
const { currentView, views } = useNavigation()
88+
const views = useViews()
8689
8790
return {
91+
activeStore,
8892
draggingStore,
8993
filesStore,
9094
pathsStore,
9195
selectionStore,
9296
uploaderStore,
9397
94-
currentView,
9598
fileListWidth,
9699
views,
97100
}
@@ -134,7 +137,7 @@ export default defineComponent({
134137
135138
// used to show the views icon for the first breadcrumb
136139
viewIcon(): string {
137-
return this.currentView?.icon ?? HomeSvg
140+
return this.activeStore.activeView?.icon ?? HomeSvg
138141
},
139142
140143
selectedFiles() {
@@ -152,12 +155,12 @@ export default defineComponent({
152155
},
153156
154157
getFileSourceFromPath(path: string): FileSource | null {
155-
return (this.currentView && this.pathsStore.getPath(this.currentView.id, path)) ?? null
158+
return (this.activeStore.activeView && this.pathsStore.getPath(this.activeStore.activeView.id, path)) ?? null
156159
},
157160
158161
getDirDisplayName(path: string): string {
159162
if (path === '/') {
160-
return this.currentView?.name || t('files', 'Home')
163+
return this.activeStore.activeView?.name || t('files', 'Home')
161164
}
162165
163166
const source = this.getFileSourceFromPath(path)
@@ -169,7 +172,7 @@ export default defineComponent({
169172
if (dir === '/') {
170173
return {
171174
...this.$route,
172-
params: { view: this.currentView?.id },
175+
params: { view: this.activeStore.activeView?.id },
173176
query: {},
174177
}
175178
}
@@ -233,7 +236,8 @@ export default defineComponent({
233236
const fileTree = await dataTransferToFileTree(items)
234237
235238
// We might not have the target directory fetched yet
236-
const contents = await this.currentView?.getContents(path)
239+
const controller = new AbortController()
240+
const contents = await this.activeStore.activeView?.getContents(path, { signal: controller.signal })
237241
const folder = contents?.folder
238242
if (!folder) {
239243
showError(this.t('files', 'Target folder does not exist any more'))
@@ -275,14 +279,12 @@ export default defineComponent({
275279
} else if (index === 0) {
276280
return t('files', 'Go to the "{dir}" directory', section)
277281
}
278-
return null
279282
},
280283
281284
ariaForSection(section) {
282285
if (section?.to?.query?.dir === this.$route.query.dir) {
283286
return t('files', 'Reload current directory')
284287
}
285-
return null
286288
},
287289
288290
t,

apps/files/src/components/DragAndDropNotice.vue

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ import { UploadStatus } from '@nextcloud/upload'
3838
import debounce from 'debounce'
3939
import { defineComponent } from 'vue'
4040
import TrayArrowDownIcon from 'vue-material-design-icons/TrayArrowDown.vue'
41-
import { useNavigation } from '../composables/useNavigation.ts'
4241
import logger from '../logger.ts'
4342
import { dataTransferToFileTree, onDropExternalFiles } from '../services/DropService.ts'
43+
import { useActiveStore } from '../store/active.ts'
4444
4545
export default defineComponent({
4646
name: 'DragAndDropNotice',
@@ -57,10 +57,10 @@ export default defineComponent({
5757
},
5858
5959
setup() {
60-
const { currentView } = useNavigation()
60+
const activeStore = useActiveStore()
6161
6262
return {
63-
currentView,
63+
activeStore,
6464
}
6565
},
6666
@@ -177,7 +177,8 @@ export default defineComponent({
177177
const fileTree = await dataTransferToFileTree(items)
178178
179179
// We might not have the target directory fetched yet
180-
const contents = await this.currentView?.getContents(this.currentFolder.path)
180+
const controller = new AbortController()
181+
const contents = await this.activeStore.activeView?.getContents(this.currentFolder.path, { signal: controller.signal })
181182
const folder = contents?.folder
182183
if (!folder) {
183184
showError(this.t('files', 'Target folder does not exist any more'))
@@ -211,13 +212,7 @@ export default defineComponent({
211212
...this.$route.params,
212213
fileid: String(lastUpload.response!.headers['oc-fileid']),
213214
},
214-
215-
query: {
216-
...this.$route.query,
217-
},
218215
}
219-
// Remove open file from query
220-
delete location.query?.openfile
221216
this.$router.push(location)
222217
}
223218

apps/files/src/components/FilesListTableHeader.vue

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,15 @@ import type { Node } from '@nextcloud/files'
7575
import type { PropType } from 'vue'
7676
import type { FileSource } from '../types.ts'
7777
78-
import { translate as t } from '@nextcloud/l10n'
78+
import { t } from '@nextcloud/l10n'
7979
import { useHotKey } from '@nextcloud/vue/composables/useHotKey'
8080
import { defineComponent } from 'vue'
8181
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
8282
import FilesListTableHeaderButton from './FilesListTableHeaderButton.vue'
83-
import { useNavigation } from '../composables/useNavigation.ts'
83+
import { useRouteParameters } from '../composables/useRouteParameters.ts'
8484
import logger from '../logger.ts'
8585
import filesSortingMixin from '../mixins/filesSorting.ts'
86+
import { useActiveStore } from '../store/active.ts'
8687
import { useFilesStore } from '../store/files.ts'
8788
import { useSelectionStore } from '../store/selection.ts'
8889
@@ -126,15 +127,17 @@ export default defineComponent({
126127
},
127128
128129
setup() {
130+
const activeStore = useActiveStore()
129131
const filesStore = useFilesStore()
130132
const selectionStore = useSelectionStore()
131-
const { currentView } = useNavigation()
133+
const { directory } = useRouteParameters()
132134
133135
return {
136+
activeStore,
134137
filesStore,
135138
selectionStore,
136139
137-
currentView,
140+
directory,
138141
}
139142
},
140143
@@ -144,12 +147,12 @@ export default defineComponent({
144147
if (this.filesListWidth < 512) {
145148
return []
146149
}
147-
return this.currentView?.columns || []
150+
return this.activeStore.activeView?.columns || []
148151
},
149152
150153
dir() {
151154
// Remove any trailing slash but leave root slash
152-
return (this.$route?.query?.dir || '/').replace(/^(.+)\/$/, '$1')
155+
return this.directory.replace(/^(.+)\/$/, '$1')
153156
},
154157
155158
selectAllBind() {
@@ -195,19 +198,18 @@ export default defineComponent({
195198
},
196199
197200
methods: {
198-
ariaSortForMode(mode: string): 'ascending' | 'descending' | null {
201+
ariaSortForMode(mode: string): 'ascending' | 'descending' | undefined {
199202
if (this.sortingMode === mode) {
200203
return this.isAscSorting ? 'ascending' : 'descending'
201204
}
202-
return null
203205
},
204206
205207
classForColumn(column) {
206208
return {
207209
'files-list__column': true,
208210
'files-list__column--sortable': !!column.sort,
209211
'files-list__row-column-custom': true,
210-
[`files-list__row-${this.currentView?.id}-${column.id}`]: true,
212+
[`files-list__row-${this.activeStore.activeView?.id}-${column.id}`]: true,
211213
}
212214
},
213215

0 commit comments

Comments
 (0)