diff --git a/packages/web-app-files/src/components/Search/List.vue b/packages/web-app-files/src/components/Search/List.vue index c72afe95c74..3e8069b8480 100644 --- a/packages/web-app-files/src/components/Search/List.vue +++ b/packages/web-app-files/src/components/Search/List.vue @@ -153,7 +153,8 @@ import { SearchResult, useCapabilityStore, useConfigStore, - useResourcesStore + useResourcesStore, + useSearch } from '@ownclouders/web-pkg' import { NoContentMessage } from '@ownclouders/web-pkg' import { ResourceTable } from '@ownclouders/web-pkg' @@ -247,6 +248,7 @@ export default defineComponent({ const { y: fileListHeaderY } = useFileListHeaderPosition() const clientService = useClientService() const { getMatchingSpace } = useGetMatchingSpace() + const { buildSearchTerm } = useSearch() const resourcesStore = useResourcesStore() const { initResourceList, clearResourceList, setAncestorMetaData } = resourcesStore @@ -342,28 +344,21 @@ export default defineComponent({ return { type: 'file', extension: item.icon, isFolder: item.icon == 'folder' } as Resource } - const buildSearchTerm = (manuallyUpdateFilterChip = false) => { - const query: string[] = [] - - const humanSearchTerm = unref(searchTerm) + const doSearch = (manuallyUpdateFilterChip = false) => { const isTitleOnlySearch = queryItemAsString(unref(titleOnlyParam)) == 'true' - const useFullTextSearch = unref(fullTextSearchEnabled) && !isTitleOnlySearch - - if (!!humanSearchTerm) { - let nameQuery = `name:"*${humanSearchTerm}*"` - - if (useFullTextSearch) { - nameQuery = `(name:"*${humanSearchTerm}*" OR content:"${humanSearchTerm}")` - } - - query.push(nameQuery) - } - - const humanScopeQuery = unref(scopeQuery) - const isScopedSearch = unref(doUseScope) === 'true' - if (isScopedSearch && humanScopeQuery) { - query.push(`scope:${humanScopeQuery}`) - } + const tags = queryItemAsString(unref(tagParam)) + const lastModified = queryItemAsString(unref(lastModifiedParam)) + const mediaType = queryItemAsString(unref(mediaTypeParam)) + + const query = buildSearchTerm({ + term: unref(searchTerm), + isTitleOnlySearch, + tags, + lastModified, + mediaType, + scope: queryItemAsString(unref(scopeQuery)), + useScope: unref(doUseScope) === 'true' + }) const updateFilter = (v: Ref>) => { if (manuallyUpdateFilterChip && unref(v)) { @@ -377,28 +372,19 @@ export default defineComponent({ } } - const humanTagsParams = queryItemAsString(unref(tagParam)) - if (humanTagsParams) { - const tags = humanTagsParams.split('+').map((t) => `"${t}"`) - query.push(`tag:(${tags.join(' OR ')})`) + if (tags) { updateFilter(tagFilter) } - const lastModifiedParams = queryItemAsString(unref(lastModifiedParam)) - if (lastModifiedParams) { - query.push(`mtime:${lastModifiedParams}`) + if (lastModified) { updateFilter(lastModifiedFilter) } - const mediaTypeParams = queryItemAsString(unref(mediaTypeParam)) - if (mediaTypeParams) { - const mediatypes = mediaTypeParams.split('+').map((t) => `"${t}"`) - query.push(`mediatype:(${mediatypes.join(' OR ')})`) + if (mediaType) { updateFilter(mediaTypeFilter) } + return query - .sort((a, b) => Number(a.startsWith('scope:')) - Number(b.startsWith('scope:'))) - .join(' AND ') } const breadcrumbs = computed(() => { @@ -429,7 +415,7 @@ export default defineComponent({ if (capabilityStore.filesTags) { await loadAvailableTagsTask.perform() } - emit('search', buildSearchTerm()) + emit('search', doSearch()) }) watch( @@ -458,7 +444,7 @@ export default defineComponent({ } } - emit('search', buildSearchTerm(true)) + emit('search', doSearch(true)) }, { deep: true } ) diff --git a/packages/web-app-preview/src/App.vue b/packages/web-app-preview/src/App.vue index 0bef76d939a..3674922dbad 100644 --- a/packages/web-app-preview/src/App.vue +++ b/packages/web-app-preview/src/App.vue @@ -81,7 +81,7 @@ import { Ref } from 'vue' import { RouteLocationRaw } from 'vue-router' -import { isShareSpaceResource, Resource } from '@ownclouders/web-client' +import { Resource } from '@ownclouders/web-client' import { AppFileHandlingResult, AppFolderHandlingResult, @@ -94,7 +94,9 @@ import { useRoute, useRouteQuery, useRouter, - usePreviewService + usePreviewService, + useGetMatchingSpace, + isLocationSharesActive } from '@ownclouders/web-pkg' import MediaControls from './components/MediaControls.vue' import MediaAudio from './components/Sources/MediaAudio.vue' @@ -145,6 +147,7 @@ export default defineComponent({ const { isFileTypeAudio, isFileTypeImage, isFileTypeVideo } = useFileTypes() const previewService = usePreviewService() const { dimensions } = usePreviewDimensions() + const { getMatchingSpace } = useGetMatchingSpace() const activeIndex = ref() const cachedFiles = ref>({}) @@ -152,6 +155,10 @@ export default defineComponent({ const isAutoPlayEnabled = ref(true) const preview = ref() + const space = computed(() => { + return getMatchingSpace(unref(activeFilteredFile)) + }) + const sortBy = computed(() => { if (!unref(contextRouteQuery)) { return 'name' @@ -209,7 +216,7 @@ export default defineComponent({ if (cachedFile.isImage) { cachedFile.url = await previewService.loadPreview( { - space: unref(props.currentFileContext.space), + space: unref(space), resource: file, dimensions: unref(dimensions), processor: ProcessorType.enum.fit @@ -219,7 +226,7 @@ export default defineComponent({ ) return } - cachedFile.url = await props.getUrlForResource(unref(props.currentFileContext.space), file) + cachedFile.url = await props.getUrlForResource(unref(space), file) } catch (e) { console.error(e) cachedFile.isError.value = true @@ -235,10 +242,7 @@ export default defineComponent({ return } - const { params, query } = createFileRouteOptions( - unref(props.currentFileContext.space), - unref(activeFilteredFile) - ) + const { params, query } = createFileRouteOptions(unref(space), unref(activeFilteredFile)) router.replace({ ...unref(route), params: { ...unref(route).params, ...params }, @@ -259,7 +263,7 @@ export default defineComponent({ folderLoaded.value = true } - ;(instance.proxy as any).setActiveFile(unref(props.currentFileContext.driveAliasAndItem)) + ;(instance.proxy as any).setActiveFile() }, { immediate: true } ) @@ -302,7 +306,8 @@ export default defineComponent({ isAutoPlayEnabled, preview, isFileTypeImage, - loadFileIntoCache + loadFileIntoCache, + space } }, @@ -336,32 +341,24 @@ export default defineComponent({ }, methods: { - setActiveFile(driveAliasAndItem: string) { + setActiveFile() { for (let i = 0; i < this.filteredFiles.length; i++) { - if (isShareSpaceResource(unref(this.currentFileContext.space))) { - // with share space resources, we don't have an underlying space, so match the file id - if (this.filteredFiles[i].remoteItemId === this.fileId) { - this.activeIndex = i - return - } - - this.activeIndex = 0 - continue - } + const filterAttr = isLocationSharesActive(this.$router, 'files-shares-with-me') + ? 'remoteItemId' + : 'fileId' - if ( - unref(this.currentFileContext.space)?.getDriveAliasAndItem(this.filteredFiles[i]) === - driveAliasAndItem - ) { + if (this.filteredFiles[i][filterAttr] === this.fileId) { this.activeIndex = i return } + + this.activeIndex = 0 } }, // react to PopStateEvent () handleLocalHistoryEvent() { const result = this.$router.resolve(document.location as unknown as RouteLocationRaw) - this.setActiveFile(queryItemAsString(result.params.driveAliasAndItem)) + this.setActiveFile() }, goToNext() { if (this.activeIndex + 1 >= this.filteredFiles.length) { diff --git a/packages/web-app-preview/tests/unit/app.spec.ts b/packages/web-app-preview/tests/unit/app.spec.ts index bf52dee202a..78809623a6f 100644 --- a/packages/web-app-preview/tests/unit/app.spec.ts +++ b/packages/web-app-preview/tests/unit/app.spec.ts @@ -1,12 +1,19 @@ import App from '../../src/App.vue' import { nextTick } from 'vue' import { defaultComponentMocks, defaultPlugins, shallowMount } from '@ownclouders/web-test-helpers' -import { FileContext } from '@ownclouders/web-pkg' +import { FileContext, queryItemAsString } from '@ownclouders/web-pkg' import { mock } from 'vitest-mock-extended' +vi.mock('@ownclouders/web-pkg', async (importOriginal) => ({ + ...(await importOriginal()), + queryItemAsString: vi.fn(), + createFileRouteOptions: vi.fn(() => ({ params: {}, query: {} })) +})) + const activeFiles = [ { id: '1', + fileId: '1', name: 'bear.png', mimeType: 'image/png', path: 'personal/admin/bear.png', @@ -14,6 +21,7 @@ const activeFiles = [ }, { id: '2', + fileId: '2', name: 'elephant.png', mimeType: 'image/png', path: 'personal/admin/elephant.png', @@ -21,6 +29,7 @@ const activeFiles = [ }, { id: '3', + fileId: '3', name: 'wale_sounds.flac', mimeType: 'audio/flac', path: 'personal/admin/wale_sounds.flac', @@ -28,6 +37,7 @@ const activeFiles = [ }, { id: '4', + fileId: '4', name: 'lonely_sloth_very_sad.gif', mimeType: 'image/gif', path: 'personal/admin/lonely_sloth_very_sad.gif', @@ -35,6 +45,7 @@ const activeFiles = [ }, { id: '5', + fileId: '5', name: 'tiger_eats_plants.mp4', mimeType: 'video/mp4', path: 'personal/admin/tiger_eats_plants.mp4', @@ -42,6 +53,7 @@ const activeFiles = [ }, { id: '6', + fileId: '6', name: 'happy_hippo.gif', mimeType: 'image/gif', path: 'personal/admin/happy_hippo.gif', @@ -49,6 +61,7 @@ const activeFiles = [ }, { id: '7', + fileId: '7', name: 'sleeping_dog.gif', mimeType: 'image/gif', path: 'personal/admin/sleeping_dog.gif', @@ -56,6 +69,7 @@ const activeFiles = [ }, { id: '8', + fileId: '8', name: 'cat_murr_murr.gif', mimeType: 'image/gif', path: 'personal/admin/cat_murr_murr.gif', @@ -63,6 +77,7 @@ const activeFiles = [ }, { id: '9', + fileId: '9', name: 'labrador.gif', mimeType: 'image/gif', path: 'personal/admin/labrador.gif', @@ -77,7 +92,7 @@ describe('Preview app', () => { await nextTick() wrapper.vm.cachedFiles = {} - wrapper.vm.setActiveFile('personal/admin/sleeping_dog.gif') + wrapper.vm.goToNext() await nextTick() @@ -94,16 +109,13 @@ describe('Preview app', () => { function createShallowMountWrapper() { const mocks = defaultComponentMocks() mocks.$previewService.loadPreview.mockResolvedValue('') + vi.mocked(queryItemAsString).mockImplementationOnce(() => '1') + return { wrapper: shallowMount(App, { props: { currentFileContext: mock({ - path: 'personal/admin/bear.png', - space: { - getDriveAliasAndItem: vi.fn().mockImplementation((file) => { - return activeFiles.find((filteredFile) => filteredFile.id == file.id)?.path - }) - } + path: 'personal/admin/bear.png' }), activeFiles, isFolderLoading: true, diff --git a/packages/web-app-search/src/portals/SearchBar.vue b/packages/web-app-search/src/portals/SearchBar.vue index 0e2db72d318..4168503a156 100644 --- a/packages/web-app-search/src/portals/SearchBar.vue +++ b/packages/web-app-search/src/portals/SearchBar.vue @@ -90,6 +90,7 @@ class="preview-component" :provider="provider" :search-result="providerSearchResultValue" + :term="term" /> diff --git a/packages/web-client/src/helpers/resource/functions.ts b/packages/web-client/src/helpers/resource/functions.ts index ca8067b4f07..dc2375b5210 100644 --- a/packages/web-client/src/helpers/resource/functions.ts +++ b/packages/web-client/src/helpers/resource/functions.ts @@ -1,7 +1,13 @@ import path, { basename, dirname } from 'path' import { urlJoin } from '../../utils' import { DavPermission, DavProperty } from '../../webdav/constants' -import { Resource, ResourceIndicator, TrashResource, WebDavResponseResource } from './types' +import { + Resource, + ResourceIndicator, + SearchResource, + TrashResource, + WebDavResponseResource +} from './types' import { camelCase } from 'lodash-es' const fileExtensions = { @@ -12,6 +18,10 @@ export const isTrashResource = (resource: Resource): resource is TrashResource = return Object.hasOwn(resource, 'ddate') } +export const isSearchResource = (resource: Resource): resource is SearchResource => { + return Object.hasOwn(resource, 'highlights') +} + export const extractDomSelector = (str: string): string => { return str.replace(/[^A-Za-z0-9\-_]/g, '') } diff --git a/packages/web-pkg/src/components/Search/ResourcePreview.vue b/packages/web-pkg/src/components/Search/ResourcePreview.vue index 84a2f0e1e6a..05e8a8e79c9 100644 --- a/packages/web-pkg/src/components/Search/ResourcePreview.vue +++ b/packages/web-pkg/src/components/Search/ResourcePreview.vue @@ -29,6 +29,7 @@ import { isSpaceResource, Resource } from '@ownclouders/web-client' import ResourceListItem from '../FilesList/ResourceListItem.vue' import { SearchResultValue } from './types' import { storeToRefs } from 'pinia' +import { RouteLocationPathRaw } from 'vue-router' const visibilityObserver = new VisibilityObserver() @@ -44,6 +45,10 @@ export default defineComponent({ isClickable: { type: Boolean, default: true + }, + term: { + type: String, + default: '' } }, setup(props) { @@ -115,7 +120,21 @@ export default defineComponent({ return null } - return action.route({ space: unref(space), resources: [unref(resource)] }) + const route = action.route({ + space: unref(space), + resources: [unref(resource)] + }) as RouteLocationPathRaw + + // add search term to query param + route.query = { + ...route.query, + contextRouteQuery: { + ...((route.query?.contextRouteQuery as any) || {}), + term: props.term + } + } + + return route }) return { diff --git a/packages/web-pkg/src/composables/appDefaults/useAppFolderHandling.ts b/packages/web-pkg/src/composables/appDefaults/useAppFolderHandling.ts index b876ff42528..8683d1eef07 100644 --- a/packages/web-pkg/src/composables/appDefaults/useAppFolderHandling.ts +++ b/packages/web-pkg/src/composables/appDefaults/useAppFolderHandling.ts @@ -1,16 +1,18 @@ import { Ref, ref, unref, MaybeRef } from 'vue' import { dirname } from 'path' -import { ClientService } from '../../services' +import { ClientService, folderService } from '../../services' import { useAppFileHandling } from './useAppFileHandling' -import { buildIncomingShareResource, Resource } from '@ownclouders/web-client' +import { isSearchResource, Resource } from '@ownclouders/web-client' import { FileContext } from './types' import { RouteLocationNormalizedLoaded } from 'vue-router' import { useFileRouteReplace } from '../router/useFileRouteReplace' import { DavProperty } from '@ownclouders/web-client/webdav' import { useAuthService } from '../authContext/useAuthService' import { isMountPointSpaceResource } from '@ownclouders/web-client' -import { useResourcesStore, useSharesStore, useSpacesStore } from '../piniaStores' +import { useResourcesStore, useSpacesStore } from '../piniaStores' import { storeToRefs } from 'pinia' +import { useRouteQuery } from '../router' +import { useSearch } from '../search' interface AppFolderHandlingOptions { currentRoute: Ref @@ -29,12 +31,13 @@ export function useAppFolderHandling({ clientService }: AppFolderHandlingOptions): AppFolderHandlingResult { const isFolderLoading = ref(false) - const { webdav, graphAuthenticated } = clientService + const { webdav } = clientService const { replaceInvalidFileRoute } = useFileRouteReplace() const { getFileInfo } = useAppFileHandling({ clientService }) const authService = useAuthService() const spacesStore = useSpacesStore() - const sharesStore = useSharesStore() + const { buildSearchTerm, search } = useSearch() + const currentRouteQuery = useRouteQuery('contextRouteQuery') const resourcesStore = useResourcesStore() const { activeResources } = storeToRefs(resourcesStore) @@ -45,21 +48,34 @@ export function useAppFolderHandling({ try { context = unref(context) - if (context.routeName === 'files-shares-with-me') { - // FIXME: this is a somewhat hacky solution to load the shared with me files. - // ideally we should check if there is a current folder and if not, use the - // folder loader to load files. unfortunately, it currently lives in the files app. - const driveItems = await graphAuthenticated.driveItems.listSharedWithMe() - - const resources = driveItems.map((driveItem) => - buildIncomingShareResource({ driveItem, graphRoles: sharesStore.graphRoles }) - ) + if ((unref(currentRouteQuery) as any)?.term) { + // run search query to load all results + const searchTerm = buildSearchTerm({ term: (unref(currentRouteQuery) as any)?.term }) + const { values } = await search(searchTerm, 200) + const resources = values + .filter(({ data }) => isSearchResource(data as Resource)) + .map((v) => v.data as Resource) resourcesStore.initResourceList({ currentFolder: null, resources }) isFolderLoading.value = false return } + const flatFileLists = [ + 'files-shares-with-me', + 'files-shares-with-others', + 'files-shares-via-link', + 'files-common-favorites' + ] + + if (flatFileLists.includes(unref(context.routeName))) { + // use the folder loader to load the resources for flat file lists + const loaderTask = folderService.getTask() + await loaderTask.perform() + isFolderLoading.value = false + return + } + resourcesStore.clearResourceList() const space = unref(context.space) const pathResource = await getFileInfo(context, { diff --git a/packages/web-pkg/src/composables/search/useSearch.ts b/packages/web-pkg/src/composables/search/useSearch.ts index 6ce5ca4cc9a..473f6640dcc 100644 --- a/packages/web-pkg/src/composables/search/useSearch.ts +++ b/packages/web-pkg/src/composables/search/useSearch.ts @@ -4,7 +4,12 @@ import { DavProperties } from '@ownclouders/web-client/webdav' import { call, urlJoin } from '@ownclouders/web-client' import { useClientService } from '../clientService' import { isProjectSpaceResource } from '@ownclouders/web-client' -import { useConfigStore, useResourcesStore, useSpacesStore } from '../piniaStores' +import { + useCapabilityStore, + useConfigStore, + useResourcesStore, + useSpacesStore +} from '../piniaStores' import { SearchResource } from '@ownclouders/web-client' import { useTask } from 'vue-concurrency' @@ -13,7 +18,9 @@ export const useSearch = () => { const clientService = useClientService() const spacesStore = useSpacesStore() const resourcesStore = useResourcesStore() + const capabilityStore = useCapabilityStore() + const fullTextSearchEnabled = computed(() => capabilityStore.searchContent?.enabled) const areHiddenFilesShown = computed(() => resourcesStore.areHiddenFilesShown) const projectSpaces = computed(() => spacesStore.spaces.filter(isProjectSpaceResource)) const getProjectSpace = (id: string) => { @@ -64,8 +71,66 @@ export const useSearch = () => { return await searchTask.perform(term, searchLimit) } + const buildSearchTerm = ({ + term, + isTitleOnlySearch, + tags, + lastModified, + mediaType, + scope, + useScope + }: { + term: string + isTitleOnlySearch?: boolean + tags?: string + lastModified?: string + mediaType?: string + scope?: string + useScope?: boolean + }) => { + const query: string[] = [] + + const humanSearchTerm = term + // const isTitleOnlySearch = queryItemAsString(unref(titleOnlyParam)) == 'true' + const useFullTextSearch = unref(fullTextSearchEnabled) && !isTitleOnlySearch + + if (!!humanSearchTerm) { + let nameQuery = `name:"*${humanSearchTerm}*"` + + if (useFullTextSearch) { + nameQuery = `(name:"*${humanSearchTerm}*" OR content:"${humanSearchTerm}")` + } + + query.push(nameQuery) + } + + // const humanScopeQuery = unref(scopeQuery) + // const isScopedSearch = unref(doUseScope) === 'true' + if (useScope && scope) { + query.push(`scope:${scope}`) + } + + if (tags) { + const tagArr = tags.split('+').map((t) => `"${t}"`) + query.push(`tag:(${tagArr.join(' OR ')})`) + } + + if (lastModified) { + query.push(`mtime:${lastModified}`) + } + + if (mediaType) { + const mediatypes = mediaType.split('+').map((t) => `"${t}"`) + query.push(`mediatype:(${mediatypes.join(' OR ')})`) + } + return query + .sort((a, b) => Number(a.startsWith('scope:')) - Number(b.startsWith('scope:'))) + .join(' AND ') + } + return { - search + search, + buildSearchTerm } } diff --git a/packages/web-pkg/src/services/folder/loaders/loaderFavorites.ts b/packages/web-pkg/src/services/folder/loaders/loaderFavorites.ts index 953be1398cb..e2cf97dff5b 100644 --- a/packages/web-pkg/src/services/folder/loaders/loaderFavorites.ts +++ b/packages/web-pkg/src/services/folder/loaders/loaderFavorites.ts @@ -3,6 +3,7 @@ import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { buildResource } from '@ownclouders/web-client' import { isLocationCommonActive } from '../../../router' +import { unref } from 'vue' export class FolderLoaderFavorites implements FolderLoader { public isEnabled(): boolean { @@ -10,7 +11,11 @@ export class FolderLoaderFavorites implements FolderLoader { } public isActive(router: Router): boolean { - return isLocationCommonActive(router, 'files-common-favorites') + const currentRoute = unref(router.currentRoute) + return ( + isLocationCommonActive(router, 'files-common-favorites') || + currentRoute?.query?.contextRouteName === 'files-common-favorites' + ) } public getTask(context: TaskContext): FolderLoaderTask { diff --git a/packages/web-pkg/src/services/folder/loaders/loaderSharedViaLink.ts b/packages/web-pkg/src/services/folder/loaders/loaderSharedViaLink.ts index 5b9a446a1d0..5d1a1d03596 100644 --- a/packages/web-pkg/src/services/folder/loaders/loaderSharedViaLink.ts +++ b/packages/web-pkg/src/services/folder/loaders/loaderSharedViaLink.ts @@ -3,6 +3,7 @@ import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { isLocationSharesActive } from '../../../router' import { buildOutgoingShareResource, call } from '@ownclouders/web-client' +import { unref } from 'vue' export class FolderLoaderSharedViaLink implements FolderLoader { public isEnabled(): boolean { @@ -10,7 +11,11 @@ export class FolderLoaderSharedViaLink implements FolderLoader { } public isActive(router: Router): boolean { - return isLocationSharesActive(router, 'files-shares-via-link') + const currentRoute = unref(router.currentRoute) + return ( + isLocationSharesActive(router, 'files-shares-via-link') || + currentRoute?.query?.contextRouteName === 'files-shares-via-link' + ) } public getTask(context: TaskContext): FolderLoaderTask { diff --git a/packages/web-pkg/src/services/folder/loaders/loaderSharedWithMe.ts b/packages/web-pkg/src/services/folder/loaders/loaderSharedWithMe.ts index f4b9b8b5e66..eb0bee7fdef 100644 --- a/packages/web-pkg/src/services/folder/loaders/loaderSharedWithMe.ts +++ b/packages/web-pkg/src/services/folder/loaders/loaderSharedWithMe.ts @@ -3,6 +3,7 @@ import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { buildIncomingShareResource, call } from '@ownclouders/web-client' import { isLocationSharesActive } from '../../../router' +import { unref } from 'vue' export class FolderLoaderSharedWithMe implements FolderLoader { public isEnabled(): boolean { @@ -10,7 +11,11 @@ export class FolderLoaderSharedWithMe implements FolderLoader { } public isActive(router: Router): boolean { - return isLocationSharesActive(router, 'files-shares-with-me') + const currentRoute = unref(router.currentRoute) + return ( + isLocationSharesActive(router, 'files-shares-with-me') || + currentRoute?.query?.contextRouteName === 'files-shares-with-me' + ) } public getTask(context: TaskContext): FolderLoaderTask { diff --git a/packages/web-pkg/src/services/folder/loaders/loaderSharedWithOthers.ts b/packages/web-pkg/src/services/folder/loaders/loaderSharedWithOthers.ts index 396c6b98928..8ee3f6dc715 100644 --- a/packages/web-pkg/src/services/folder/loaders/loaderSharedWithOthers.ts +++ b/packages/web-pkg/src/services/folder/loaders/loaderSharedWithOthers.ts @@ -1,4 +1,5 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folderService' +import { unref } from 'vue' import { Router } from 'vue-router' import { useTask } from 'vue-concurrency' import { isLocationSharesActive } from '../../../router' @@ -10,7 +11,11 @@ export class FolderLoaderSharedWithOthers implements FolderLoader { } public isActive(router: Router): boolean { - return isLocationSharesActive(router, 'files-shares-with-others') + const currentRoute = unref(router.currentRoute) + return ( + isLocationSharesActive(router, 'files-shares-with-others') || + currentRoute?.query?.contextRouteName === 'files-shares-with-others' + ) } public getTask(context: TaskContext): FolderLoaderTask {