Skip to content

Commit

Permalink
fix(FilePicker): Add current folder to button factory as selected if …
Browse files Browse the repository at this point in the history
…`allowPickDirectory` is true

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Jun 8, 2024
1 parent fe8ca13 commit 3a23d9a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 32 deletions.
56 changes: 29 additions & 27 deletions lib/components/FilePicker/FilePicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
<div class="file-picker__main">
<!-- Header title / file list breadcrumbs -->
<FilePickerBreadcrumbs v-if="currentView === 'files'"
:path.sync="currentPath"
:path="currentPath"
:show-menu="allowPickDirectory"
@create-node="onCreateFolder" />
@create-node="onCreateFolder"
@update:path="navigatedPath = $event" />
<div v-else class="file-picker__view">
<h3>{{ viewHeadline }}</h3>
</div>
Expand Down Expand Up @@ -67,7 +68,7 @@ import FilePickerNavigation from './FilePickerNavigation.vue'
import { emit as emitOnEventBus } from '@nextcloud/event-bus'
import { NcDialog, NcEmptyContent } from '@nextcloud/vue'
import { computed, onMounted, ref, toRef } from 'vue'
import { computed, onMounted, ref, shallowReactive, toRef, watch } from 'vue'
import { showError } from '../../toast'
import { useDAVFiles } from '../../composables/dav'
import { useMimeFilter } from '../../composables/mime'
Expand Down Expand Up @@ -148,16 +149,17 @@ const isOpen = ref(true)
* Map buttons to Dialog buttons by wrapping the callback function to pass the selected files
*/
const dialogButtons = computed(() => {
const nodes = selectedFiles.length === 0 && props.allowPickDirectory && currentFolder.value ? [currentFolder.value] : selectedFiles
const buttons = typeof props.buttons === 'function'
? props.buttons(selectedFiles.value as Node[], currentPath.value, currentView.value)
? props.buttons(nodes, currentPath.value, currentView.value)
: props.buttons
return buttons.map((button) => ({
...button,
callback: () => {
// lock default close handling
isHandlingCallback = true
handleButtonClick(button.callback)
handleButtonClick(button.callback, nodes)
},
} as IFilePickerButton))
})
Expand All @@ -168,8 +170,7 @@ const dialogButtons = computed(() => {
*/
let isHandlingCallback = false
const handleButtonClick = async (callback: IFilePickerButton['callback']) => {
const nodes = selectedFiles.value.length === 0 && props.allowPickDirectory ? [await getFile(currentPath.value)] : selectedFiles.value as Node[]
const handleButtonClick = async (callback: IFilePickerButton['callback'], nodes: Node[]) => {
callback(nodes)
emit('close', nodes)
// Unlock close
Expand All @@ -189,7 +190,7 @@ const viewHeadline = computed(() => currentView.value === 'favorites' ? t('Favor
/**
* All currently selected files
*/
const selectedFiles = ref<Node[]>([])
const selectedFiles = shallowReactive<Node[]>([])
/**
* Last path navigated to using the file picker
Expand All @@ -200,28 +201,23 @@ const savedPath = ref(window?.sessionStorage.getItem('NC.FilePicker.LastPath') |
/**
* The path the user manually navigated to using this filepicker instance
*/
const navigatedPath = ref<string>()
const navigatedPath = ref('')
// Save the navigated path to the session storage on change
watch([navigatedPath], () => {
if (props.path === undefined && navigatedPath.value) {
window.sessionStorage.setItem('NC.FilePicker.LastPath', navigatedPath.value)
// Reset selected files
selectedFiles.splice(0, selectedFiles.length)
}
})
/**
* The current path that should be picked from
*/
const currentPath = computed({
const currentPath = computed(() =>
// Only use the path for the files view as favorites and recent only works on the root
get: () => currentView.value === 'files' ? navigatedPath.value || props.path || savedPath.value : '/',
/**
* Navigate to the new path and save it to the session storage
*
* @param path The new path
*/
set: (path: string) => {
if (props.path === undefined) {
window.sessionStorage.setItem('NC.FilePicker.LastPath', path)
}
navigatedPath.value = path
// Reset selected files
selectedFiles.value = []
},
})
currentView.value === 'files' ? navigatedPath.value || props.path || savedPath.value : '/',
)
/**
* A string used to filter files in current view
Expand All @@ -230,7 +226,13 @@ const filterString = ref('')
const { isSupportedMimeType } = useMimeFilter(toRef(props, 'mimetypeFilter')) // vue 3.3 will allow cleaner syntax of toRef(() => props.mimetypeFilter)
const { files, isLoading, loadFiles, getFile, createDirectory } = useDAVFiles(currentView, currentPath, isPublic)
const {
files,
folder: currentFolder,
isLoading,
loadFiles,
createDirectory,
} = useDAVFiles(currentView, currentPath, isPublic)
onMounted(() => loadFiles())
Expand Down Expand Up @@ -281,7 +283,7 @@ const noFilesDescription = computed(() => {
const onCreateFolder = async (name: string) => {
try {
const folder = await createDirectory(name)
currentPath.value = folder.path
navigatedPath.value = folder.path
// emit event bus to force files app to reload that file if needed
emitOnEventBus('files:node:created', files.value.filter((file) => file.basename === name)[0])
} catch (error) {
Expand Down
19 changes: 14 additions & 5 deletions lib/composables/dav.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type { FileStat, ResponseDataDetailed, SearchResult } from 'webdav'
import { davGetClient, davGetDefaultPropfind, davGetRecentSearch, davRemoteURL, davResultToNode, davRootPath, getFavoriteNodes } from '@nextcloud/files'
import { generateRemoteUrl } from '@nextcloud/router'
import { join } from 'path'
import { computed, onMounted, ref, watch } from 'vue'
import { computed, onMounted, ref, shallowRef, watch } from 'vue'
import { CancelablePromise } from 'cancelable-promise'

/**
Expand All @@ -39,8 +39,8 @@ import { CancelablePromise } from 'cancelable-promise'
export const useDAVFiles = function(
currentView: Ref<'files'|'recent'|'favorites'> | ComputedRef<'files'|'recent'|'favorites'>,
currentPath: Ref<string> | ComputedRef<string>,
isPublicEndpoint: Ref<boolean> | ComputedRef<boolean>
): { isLoading: Ref<boolean>, createDirectory: (name: string) => Promise<Folder>, files: Ref<Node[]>, loadFiles: () => Promise<void>, getFile: (path: string) => Promise<Node> } {
isPublicEndpoint: Ref<boolean> | ComputedRef<boolean>,
) {

const defaultRootPath = computed(() => isPublicEndpoint.value ? '/' : davRootPath)

Expand Down Expand Up @@ -114,7 +114,15 @@ export const useDAVFiles = function(
/**
* All files in current view and path
*/
const files = ref<Node[]>([] as Node[]) as Ref<Node[]>
const files = shallowRef<Node[]>([] as Node[]) as Ref<Node[]>

/**
* The current folder
*/
const folder = shallowRef<Folder>()
watch([currentPath], async () => {
folder.value = (files.value.find(({ path }) => path === currentPath.value) ?? await getFile(currentPath.value)) as Folder
}, { immediate: true })

/**
* Loading state of the files
Expand All @@ -136,7 +144,7 @@ export const useDAVFiles = function(

await client.value.createDirectory(join(defaultRootPath.value, path))
const directory = await getFile(path) as Folder
files.value.push(directory)
files.value = [...files.value, directory]
return directory
}

Expand Down Expand Up @@ -191,6 +199,7 @@ export const useDAVFiles = function(
return {
isLoading,
files,
folder,
loadFiles: loadDAVFiles,
getFile,
createDirectory,
Expand Down

0 comments on commit 3a23d9a

Please sign in to comment.