diff options
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 20 | ||||
-rw-r--r-- | apps/files/src/services/RouterService.ts | 37 | ||||
-rw-r--r-- | apps/files/src/views/FilesList.vue | 4 | ||||
-rw-r--r-- | apps/files_sharing/src/components/FileListFilterAccount.vue | 41 | ||||
-rw-r--r-- | package.json | 1 |
5 files changed, 78 insertions, 25 deletions
diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index 9a35e9ff855..782e2bd3587 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -4,7 +4,7 @@ --> <template> <VirtualList ref="table" - :data-component="userConfig.grid_view ? FileEntryGrid : FileEntry" + :data-component="fileEntryComponent" :data-key="'source'" :data-sources="nodes" :grid-mode="userConfig.grid_view" @@ -132,8 +132,6 @@ export default defineComponent({ data() { return { - FileEntry, - FileEntryGrid, headers: getFileListHeaders(), scrollToIndex: 0, openFileId: null as number|null, @@ -141,6 +139,13 @@ export default defineComponent({ }, computed: { + /** + * The Vue component to use for file list entries + */ + fileEntryComponent() { + return this.userConfig.grid_view ? FileEntryGrid : FileEntry + }, + userConfig(): UserConfig { return this.userConfigStore.userConfig }, @@ -218,6 +223,11 @@ export default defineComponent({ }, methods: { + reset() { + this.scrollToIndex = 0 + this.openFileId = null + }, + // Open the file sidebar if we have the room for it // but don't open the sidebar for the current folder openSidebarForFile(fileId) { @@ -236,6 +246,10 @@ export default defineComponent({ if (fileId) { const index = this.nodes.findIndex(node => node.fileid === fileId) if (warn && index === -1 && fileId !== this.currentFolder.fileid) { + logger.error('File to scroll to not found', { + folder: this.currentFolder, + fileId, + }) showError(this.t('files', 'File not found')) } this.scrollToIndex = Math.max(0, index) diff --git a/apps/files/src/services/RouterService.ts b/apps/files/src/services/RouterService.ts index 84516465495..65113eb32d7 100644 --- a/apps/files/src/services/RouterService.ts +++ b/apps/files/src/services/RouterService.ts @@ -4,14 +4,47 @@ */ import type { Route } from 'vue-router' import type VueRouter from 'vue-router' -import type { Dictionary, Location } from 'vue-router/types/router' +import type { Dictionary, Location } from 'vue-router/types/router.d.ts' +import { TypedEventTarget } from 'typescript-event-target' -export default class RouterService { +interface NavigationEventData { + name: Route['name'] + params: Route['params'] + query: Route['query'] +} + +class NavigationEvent extends CustomEvent<NavigationEventData> { + + constructor({ name, params, query }: Route) { + super('navigation', { + detail: { + name, + // Do not let API users mess with internal state of our VueRouter (e.g. if they use Vue it could conflict) + params: structuredClone(params), + query: structuredClone(query), + }, + }) + } + +} + +interface RouterEventMap { + navigation: NavigationEvent +} + +export default class RouterService extends TypedEventTarget<RouterEventMap> { private _router: VueRouter constructor(router: VueRouter) { + super() this._router = router + this._router.beforeEach((to, from, next) => { + // emit event + this.dispatchTypedEvent('navigation', new NavigationEvent(to)) + // continue + next() + }) } get name(): string | null | undefined { diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index a127fd4c35c..bca95d0d25a 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -397,7 +397,7 @@ export default defineComponent({ showCustomEmptyView() { return !this.loading && this.isEmptyDir && this.currentView?.emptyView !== undefined - } + }, }, watch: { @@ -657,7 +657,7 @@ export default defineComponent({ filterDirContent() { let nodes = this.dirContents for (const filter of this.filtersStore.sortedFilters) { - nodes = filter.filter(nodes) + nodes = filter.filter(nodes) as Node[] } this.dirContentsFiltered = nodes }, diff --git a/apps/files_sharing/src/components/FileListFilterAccount.vue b/apps/files_sharing/src/components/FileListFilterAccount.vue index 68383735532..e0c77c1a900 100644 --- a/apps/files_sharing/src/components/FileListFilterAccount.vue +++ b/apps/files_sharing/src/components/FileListFilterAccount.vue @@ -40,9 +40,7 @@ import type { IAccountData } from '../filters/AccountFilter.ts' import { translate as t } from '@nextcloud/l10n' import { mdiAccountMultiple } from '@mdi/js' -import { useBrowserLocation } from '@vueuse/core' -import { computed, ref, watch } from 'vue' -import { useNavigation } from '../../../files/src/composables/useNavigation.ts' +import { computed, onMounted, ref, watch } from 'vue' import FileListFilter from '../../../files/src/components/FileListFilter/FileListFilter.vue' import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js' @@ -50,6 +48,7 @@ import NcActionInput from '@nextcloud/vue/dist/Components/NcActionInput.js' import NcAvatar from '@nextcloud/vue/dist/Components/NcAvatar.js' import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js' import { ShareType } from '@nextcloud/sharing' +import { getNavigation, View } from '@nextcloud/files' interface IUserSelectData { id: string @@ -61,12 +60,12 @@ const emit = defineEmits<{ (event: 'update:accounts', value: IAccountData[]): void }>() -const { currentView } = useNavigation() -const currentLocation = useBrowserLocation() const accountFilter = ref('') const availableAccounts = ref<IUserSelectData[]>([]) const selectedAccounts = ref<IUserSelectData[]>([]) +const currentView = ref<View | null>(null) + /** * Currently shown accounts (filtered) */ @@ -107,14 +106,21 @@ watch(selectedAccounts, () => { /** * Update the accounts owning nodes or have nodes shared to them - * @param path The path inside the current view to load for accounts */ -async function updateAvailableAccounts(path: string = '/') { +async function updateAvailableAccounts() { availableAccounts.value = [] + // Skip while loading if (!currentView.value) { return } + const path: string = [window.OCP.Files.Router.query.dir].flat()[0] || '/' + + // Skip for tags as they do not have an owner + if (currentView.value.id === 'tags' && path === '/') { + return + } + const { contents } = await currentView.value.getContents(path) const available = new Map<string, IUserSelectData>() for (const node of contents) { @@ -152,6 +158,16 @@ async function updateAvailableAccounts(path: string = '/') { availableAccounts.value = [...available.values()] } +(window.OCP.Files.Router as unknown as EventTarget).addEventListener('navigation', () => { + currentView.value = getNavigation().active + updateAvailableAccounts() +}) + +onMounted(() => { + currentView.value = getNavigation().active + updateAvailableAccounts() +}) + /** * Reset this filter */ @@ -160,17 +176,6 @@ function resetFilter() { accountFilter.value = '' } defineExpose({ resetFilter, toggleAccount }) - -// When the current view changes or the current directory, -// then we need to rebuild the available accounts -watch([currentView, currentLocation], () => { - if (currentView.value) { - // we have no access to the files router here... - const path = (currentLocation.value.search ?? '?dir=/').match(/(?<=&|\?)dir=([^&#]+)/)?.[1] - resetFilter() - updateAvailableAccounts(decodeURIComponent(path ?? '/')) - } -}, { immediate: true }) </script> <style scoped lang="scss"> diff --git a/package.json b/package.json index 47e06c8c48c..0b93ccf45df 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,7 @@ "snap.js": "^2.0.9", "strengthify": "github:nextcloud/strengthify#0.5.9", "throttle-debounce": "^5.0.2", + "typescript-event-target": "^1.1.1", "underscore": "1.13.6", "url-search-params-polyfill": "^8.1.1", "v-click-outside": "^3.2.0", |