Skip to content

Commit 896ce75

Browse files
committed
feat(FilePicker): Expose canNavigate option
This will gray out nodes and prevent navigation Signed-off-by: Louis Chmn <louis@chmn.me>
1 parent 6061f77 commit 896ce75

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed

lib/components/FilePicker/FileList.vue

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
:allow-pick-directory="allowPickDirectory"
6969
:show-checkbox="multiselect"
7070
:can-pick="(multiselect || selectedFiles.length === 0 || selectedFiles.includes(file)) && (canPick === undefined || canPick(file))"
71+
:can-navigate="file.type === FileType.Folder && (canNavigate === undefined || canNavigate(file))"
7172
:selected="selectedFiles.includes(file)"
7273
:node="file"
7374
:crop-image-previews="cropImagePreviews"
@@ -82,7 +83,7 @@
8283
<script setup lang="ts">
8384
import type { FilesSortingMode, INode } from '@nextcloud/files'
8485
import type { FileListViews } from '../../composables/filesSettings.ts'
85-
import type { IFilePickerCanPick } from '../types.ts'
86+
import type { IFilePickerCanNavigate, IFilePickerCanPick } from '../types.ts'
8687
8788
import { FileType, sortNodes } from '@nextcloud/files'
8889
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
@@ -130,6 +131,10 @@ const props = defineProps<{
130131
* Custom function to decide if a node can be picked
131132
*/
132133
canPick?: IFilePickerCanPick
134+
/**
135+
* Custom function to decide if a node can be navigated into
136+
*/
137+
canNavigate?: IFilePickerCanNavigate
133138
}>()
134139
135140
/// sorting related stuff

lib/components/FilePicker/FileListRow.vue

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
:class="[
1111
{
1212
'file-picker__row--selected': selected && !showCheckbox,
13+
'file-picker__row--not-navigatable': isDirectory && !canNavigate,
1314
},
1415
]"
1516
:data-filename="node.basename"
@@ -62,6 +63,8 @@ const props = defineProps<{
6263
showCheckbox: boolean
6364
/** Whether the node can be picked */
6465
canPick: boolean
66+
/** Whether the node can be navigated into */
67+
canNavigate: boolean
6568
/** The current node */
6669
node: INode
6770
/** Whether the preview should be cropped */
@@ -113,7 +116,9 @@ function toggleSelected() {
113116
*/
114117
function handleClick() {
115118
if (isDirectory.value) {
116-
emit('enterDirectory', props.node)
119+
if (props.canNavigate) {
120+
emit('enterDirectory', props.node)
121+
}
117122
} else {
118123
toggleSelected()
119124
}
@@ -143,6 +148,16 @@ function handleKeyDown(event: KeyboardEvent) {
143148
&--selected {
144149
background-color: var(--color-background-dark);
145150
}
151+
152+
&--not-navigatable {
153+
filter: saturate(0.7);
154+
opacity: 0.7;
155+
156+
* {
157+
cursor: default !important;
158+
}
159+
}
160+
146161
&:hover {
147162
background-color: var(--color-background-hover);
148163
}

lib/components/FilePicker/FilePicker.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
:loading="isLoading"
4545
:name="viewHeadline"
4646
:can-pick="canPickFn"
47+
:can-navigate="canNavigateFn"
4748
@update:path="currentView = 'files'" />
4849
<NcEmptyContent
4950
v-else-if="filterString"
@@ -68,7 +69,7 @@
6869
<script setup lang="ts">
6970
import type { Node } from '@nextcloud/files'
7071
import type { IFilesViewId } from '../../composables/views.ts'
71-
import type { IDialogButton, IFilePickerButton, IFilePickerButtonFactory, IFilePickerCanPick, IFilePickerFilter } from '../types.ts'
72+
import type { IDialogButton, IFilePickerButton, IFilePickerButtonFactory, IFilePickerCanNavigate, IFilePickerCanPick, IFilePickerFilter } from '../types.ts'
7273
7374
import { emit as emitOnEventBus } from '@nextcloud/event-bus'
7475
import { computed, onMounted, ref, shallowRef, toRef, watch } from 'vue'
@@ -114,6 +115,11 @@ const props = withDefaults(defineProps<{
114115
*/
115116
canPickFn?: IFilePickerCanPick
116117
118+
/**
119+
* Custom function to decide if a node can be navigated into
120+
*/
121+
canNavigateFn?: IFilePickerCanNavigate
122+
117123
/**
118124
* List of allowed mime types
119125
* You can use placeholders for e.g. allowing all subtypes of images `['image/*']`.
@@ -139,6 +145,7 @@ const props = withDefaults(defineProps<{
139145
disabledNavigation: false,
140146
filterFn: undefined,
141147
canPickFn: undefined,
148+
canNavigateFn: undefined,
142149
mimetypeFilter: () => [],
143150
multiselect: false,
144151
path: undefined,

lib/components/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,8 @@ export type IFilePickerFilter = (node: Node) => boolean
6363
* Type of functions to allow or not picking a node
6464
*/
6565
export type IFilePickerCanPick = (node: INode) => boolean
66+
67+
/**
68+
* Type of functions to allow or not navigating to node
69+
*/
70+
export type IFilePickerCanNavigate = (node: INode) => boolean

lib/filepicker-builder.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import type { Node } from '@nextcloud/files'
7-
import type { IFilePickerButton, IFilePickerButtonFactory, IFilePickerCanPick, IFilePickerFilter } from './components/types.ts'
7+
import type { IFilePickerButton, IFilePickerButtonFactory, IFilePickerCanNavigate, IFilePickerCanPick, IFilePickerFilter } from './components/types.ts'
88

99
import IconMove from '@mdi/svg/svg/folder-move.svg?raw'
1010
import IconCopy from '@mdi/svg/svg/folder-multiple.svg?raw'
@@ -38,6 +38,7 @@ export class FilePicker<IsMultiSelect extends boolean> {
3838
private path?: string
3939
private filter?: IFilePickerFilter
4040
private canPick?: IFilePickerCanPick
41+
private canNavigate?: IFilePickerCanNavigate
4142
private container?: string
4243
private disabledNavigation: boolean
4344

@@ -50,6 +51,7 @@ export class FilePicker<IsMultiSelect extends boolean> {
5051
path?: string,
5152
filter?: IFilePickerFilter,
5253
canPick?: IFilePickerCanPick,
54+
canNavigate?: IFilePickerCanNavigate,
5355
container?: string,
5456
disabledNavigation = false,
5557
) {
@@ -60,6 +62,7 @@ export class FilePicker<IsMultiSelect extends boolean> {
6062
this.path = path
6163
this.filter = filter
6264
this.canPick = canPick
65+
this.canNavigate = canNavigate
6366
this.buttons = buttons
6467
this.container = container
6568
this.disabledNavigation = disabledNavigation
@@ -82,6 +85,7 @@ export class FilePicker<IsMultiSelect extends boolean> {
8285
multiselect: this.multiSelect,
8386
filterFn: this.filter,
8487
canPickFn: this.canPick,
88+
canNavigateFn: this.canNavigate,
8589
disabledNavigation: this.disabledNavigation,
8690
}, {
8791
container: this.container,
@@ -117,6 +121,7 @@ export class FilePickerBuilder<IsMultiSelect extends boolean> {
117121
private path?: string
118122
private filter?: IFilePickerFilter
119123
private canPick?: IFilePickerCanPick
124+
private canNavigate?: IFilePickerCanNavigate
120125
private buttons: IFilePickerButton[] | IFilePickerButtonFactory = []
121126
private container?: string
122127
private disabledNavigation = false
@@ -284,6 +289,16 @@ export class FilePickerBuilder<IsMultiSelect extends boolean> {
284289
return this
285290
}
286291

292+
/**
293+
* Add function to allow or not picking a node
294+
*
295+
* @param canNavigate Function to decide if a node can be navigated into
296+
*/
297+
public setCanNavigate(canNavigate: IFilePickerCanNavigate) {
298+
this.canNavigate = canNavigate
299+
return this
300+
}
301+
287302
/**
288303
* Disable navigation (view selection)
289304
*/
@@ -305,6 +320,7 @@ export class FilePickerBuilder<IsMultiSelect extends boolean> {
305320
this.path,
306321
this.filter,
307322
this.canPick,
323+
this.canNavigate,
308324
this.container,
309325
this.disabledNavigation,
310326
)

0 commit comments

Comments
 (0)