diff --git a/changelog/unreleased/bugfix-loading-shares-in-deep-nested-folders b/changelog/unreleased/bugfix-loading-shares-in-deep-nested-folders
new file mode 100644
index 00000000000..75004bd5daf
--- /dev/null
+++ b/changelog/unreleased/bugfix-loading-shares-in-deep-nested-folders
@@ -0,0 +1,6 @@
+Bugfix: Loading shares in deep nested folders
+
+Loading shares and share indicators on page reloads in deep nested folders was not possible and has been fixed.
+
+https://github.com/owncloud/web/issues/7655
+https://github.com/owncloud/web/pull/8349
diff --git a/changelog/unreleased/enhancement-share-and-folder-loading-performance b/changelog/unreleased/enhancement-share-and-folder-loading-performance
new file mode 100644
index 00000000000..a3d158d0841
--- /dev/null
+++ b/changelog/unreleased/enhancement-share-and-folder-loading-performance
@@ -0,0 +1,6 @@
+Enhancement: Improve performance when loading folders and share indicators
+
+The performance when loading folders and share indicators has been improved by optimizing the way how shares are being loaded.
+
+https://github.com/owncloud/web/issues/7721
+https://github.com/owncloud/web/pull/8349
diff --git a/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue b/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue
index 259cb3ac35f..79dc9cec8dc 100644
--- a/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue
+++ b/packages/design-system/src/components/OcStatusIndicators/OcStatusIndicators.vue
@@ -13,7 +13,7 @@
variation="inverse"
:data-testid="indicator.id"
:data-test-indicator-type="indicator.type"
- @click="indicator.handler(resource, indicator.target)"
+ @click="indicator.handler(resource, indicator.target, $router)"
>
diff --git a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
index 34c41af4e75..058bb09083c 100644
--- a/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
+++ b/packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
@@ -178,6 +178,7 @@ import { urlJoin } from 'web-client/src/utils'
import { stringify } from 'qs'
import { useService } from 'web-pkg/src/composables/service'
import { UppyService } from 'web-runtime/src/services/uppyService'
+import { getIndicators } from 'web-app-files/src/helpers/statusIndicators'
export default defineComponent({
components: {
@@ -252,7 +253,13 @@ export default defineComponent({
}),
computed: {
...mapGetters(['capabilities', 'configuration', 'newFileHandlers', 'user']),
- ...mapGetters('Files', ['files', 'currentFolder', 'selectedFiles', 'clipboardResources']),
+ ...mapGetters('Files', [
+ 'ancestorMetaData',
+ 'files',
+ 'currentFolder',
+ 'selectedFiles',
+ 'clipboardResources'
+ ]),
...mapState('Files', ['areFileExtensionsShown']),
...mapGetters('runtime/spaces', ['spaces']),
@@ -317,15 +324,14 @@ export default defineComponent({
return false
}
return this.currentFolder.canUpload({ user: this.user })
+ },
+
+ loadIndicatorsForNewFile() {
+ return this.isSpacesGenericLocation && this.space.driveType !== 'share'
}
},
methods: {
- ...mapActions('Files', [
- 'loadPreview',
- 'loadIndicators',
- 'clearClipboardFiles',
- 'pasteSelectedFiles'
- ]),
+ ...mapActions('Files', ['clearClipboardFiles', 'pasteSelectedFiles']),
...mapActions(['showMessage', 'createModal', 'setModalInputErrorMessage', 'hideModal']),
...mapMutations('Files', ['UPSERT_RESOURCE']),
...mapMutations('runtime/spaces', ['UPDATE_SPACE_FIELD']),
@@ -453,16 +459,14 @@ export default defineComponent({
const resource = await (this.$clientService.webdav as WebDAV).createFolder(this.space, {
path
})
- this.UPSERT_RESOURCE(resource)
- this.hideModal()
- if (this.isSpacesGenericLocation && this.space.driveType !== 'share') {
- this.loadIndicators({
- client: this.$client,
- currentFolder: this.currentFolder.path
- })
+ if (this.loadIndicatorsForNewFile) {
+ resource.indicators = getIndicators({ resource, ancestorMetaData: this.ancestorMetaData })
}
+ this.UPSERT_RESOURCE(resource)
+ this.hideModal()
+
this.showMessage({
title: this.$gettextInterpolate(
this.$gettext('"%{folderName}" was created successfully'),
@@ -522,6 +526,10 @@ export default defineComponent({
path
})
+ if (this.loadIndicatorsForNewFile) {
+ resource.indicators = getIndicators({ resource, ancestorMetaData: this.ancestorMetaData })
+ }
+
this.UPSERT_RESOURCE(resource)
if (this.newFileAction) {
@@ -538,14 +546,6 @@ export default defineComponent({
}
this.hideModal()
-
- if (this.isSpacesGenericLocation && this.space.driveType !== 'share') {
- this.loadIndicators({
- client: this.$client,
- currentFolder: this.currentFolder.path
- })
- }
-
this.showMessage({
title: this.$gettextInterpolate(this.$gettext('"%{fileName}" was created successfully'), {
fileName
@@ -584,16 +584,14 @@ export default defineComponent({
const resource = await (this.$clientService.webdav as WebDAV).getFileInfo(this.space, {
path
})
+
+ if (this.loadIndicatorsForNewFile) {
+ resource.indicators = getIndicators({ resource, ancestorMetaData: this.ancestorMetaData })
+ }
+
this.$_fileActions_triggerDefaultAction({ space: this.space, resources: [resource] })
this.UPSERT_RESOURCE(resource)
this.hideModal()
-
- if (this.isSpacesGenericLocation && this.space.driveType !== 'share') {
- this.loadIndicators({
- client: this.$client,
- currentFolder: this.currentFolder.path
- })
- }
this.showMessage({
title: this.$gettextInterpolate(this.$gettext('"%{fileName}" was created successfully'), {
fileName
diff --git a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
index 5d29dc7addb..f7195a0bc4e 100644
--- a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
+++ b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
@@ -93,7 +93,7 @@ import { computed, defineComponent, unref } from 'vue'
import { debounce } from 'lodash-es'
import { ImageDimension, ImageType } from 'web-pkg/src/constants'
import { VisibilityObserver } from 'web-pkg/src/observer'
-import { mapActions, mapGetters, mapMutations } from 'vuex'
+import { mapActions, mapGetters } from 'vuex'
import FileActions from '../../mixins/fileActions'
import MixinAcceptShare from '../../mixins/actions/acceptShare'
import MixinDeclineShare from '../../mixins/actions/declineShare'
@@ -258,8 +258,7 @@ export default defineComponent({
visibilityObserver.disconnect()
},
methods: {
- ...mapActions('Files', ['loadIndicators', 'loadPreview', 'loadAvatars']),
- ...mapMutations('Files', ['LOAD_FILES', 'CLEAR_CURRENT_FILES_LIST']),
+ ...mapActions('Files', ['loadPreview', 'loadAvatars']),
rowMounted(resource, component) {
const debounced = debounce(({ unobserve }) => {
diff --git a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
index 2f51957ce89..713ea41ef44 100644
--- a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
+++ b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
@@ -284,7 +284,7 @@ export default defineComponent({
},
computed: {
...mapGetters('runtime/spaces', ['spaces']),
- ...mapGetters('Files', ['versions', 'sharesTree', 'sharesTreeLoading']),
+ ...mapGetters('Files', ['ancestorMetaData', 'versions', 'sharesTree', 'sharesTreeLoading']),
...mapGetters(['user', 'configuration']),
matchingSpace() {
@@ -453,7 +453,7 @@ export default defineComponent({
)
},
shareIndicators() {
- return getIndicators(this.resource, this.sharesTree)
+ return getIndicators({ resource: this.resource, ancestorMetaData: this.ancestorMetaData })
},
shares() {
if (this.sharedParentDir === null) {
diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
index 72951f6881c..46b5bedc63b 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
@@ -538,13 +538,7 @@ export default defineComponent({
this.currentFileOutgoingLinks.length === 1 ? this.currentFileOutgoingLinks[0].id : undefined
try {
- await this.removeLink({
- client,
- share,
- path,
- storageId: resource.fileId,
- loadIndicators: !!lastLinkId
- })
+ await this.removeLink({ client, share, path, loadIndicators: !!lastLinkId })
this.showMessage({
title: this.$gettext('Link was deleted successfully')
})
diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
index e93843c91a7..27c8a2e418f 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
@@ -303,7 +303,6 @@ export default defineComponent({
client: this.$client,
share: share,
path,
- storageId: this.resource.fileId,
loadIndicators: !!lastShareId
})
diff --git a/packages/web-app-files/src/components/SideBar/SideBar.vue b/packages/web-app-files/src/components/SideBar/SideBar.vue
index 795380b3433..783e5fa1429 100644
--- a/packages/web-app-files/src/components/SideBar/SideBar.vue
+++ b/packages/web-app-files/src/components/SideBar/SideBar.vue
@@ -168,6 +168,9 @@ export default defineComponent({
const highlightedFileIsSpace = computed(() => {
return isProjectSpaceResource(unref(highlightedFile) || {})
})
+ const highlightedSpace = computed(() => {
+ return store.getters['runtime/spaces/spaces'].find((s) => s.id === unref(highlightedFile).id)
+ })
const sharesLoadingDisabledOnCurrentRoute = computed(() => {
return unref(isPublicFilesLocation) || unref(isTrashLocation)
})
@@ -204,9 +207,7 @@ export default defineComponent({
const getSelectedResource = () => {
if (unref(highlightedFileIsSpace) && unref(selectedFiles).length) {
- return store.getters['runtime/spaces/spaces'].find(
- (s) => s.id === unref(highlightedFile).id
- )
+ return unref(highlightedSpace)
}
if (unref(selectedFiles).length === 1) {
return unref(selectedFiles)[0]
@@ -254,8 +255,11 @@ export default defineComponent({
}
watch(
- selectedFiles,
- (newResource, oldResource) => {
+ () => [...unref(selectedFiles), props.open],
+ () => {
+ if (!props.open) {
+ return
+ }
if (
unref(selectedFiles).length === 1 &&
unref(loadedResource)?.id === unref(selectedFiles)[0].id
@@ -267,16 +271,14 @@ export default defineComponent({
loading.value = true
let selectedResource = getSelectedResource()
if (selectedResource) {
- const shouldLoadShares =
- !unref(sharesLoadingDisabledOnCurrentRoute) && (!!oldResource || !unref(currentFolder))
- if (shouldLoadShares) {
+ if (!unref(sharesLoadingDisabledOnCurrentRoute)) {
loadShares()
}
if (unref(highlightedFileIsSpace)) {
store.dispatch('runtime/spaces/loadSpaceMembers', {
graphClient: unref(graphClient),
- space: selectedResource
+ space: unref(highlightedSpace)
})
}
diff --git a/packages/web-app-files/src/helpers/statusIndicators.ts b/packages/web-app-files/src/helpers/statusIndicators.ts
index 1d41d27b26f..aa9147d58f3 100644
--- a/packages/web-app-files/src/helpers/statusIndicators.ts
+++ b/packages/web-app-files/src/helpers/statusIndicators.ts
@@ -1,123 +1,80 @@
-import { getParentPaths } from './path'
import { ShareTypes } from 'web-client/src/helpers/share'
-import { eventBus } from 'web-pkg/src/services/eventBus'
+import { eventBus } from 'web-pkg'
import { SideBarEventTopics } from 'web-pkg/src/composables/sideBar'
+import { createLocationShares } from 'web-app-files/src/router'
// dummy to trick gettext string extraction into recognizing strings
const $gettext = (str) => {
return str
}
-const $shareTypes = (resource) => {
- if (typeof resource.shareTypes !== 'undefined') {
- return resource.shareTypes
- }
-
- if (resource.shares) {
- return Array.from(new Set(resource.shares.map((share) => parseInt(share.type))))
- }
-
- return []
-}
-
-const isDirectUserShare = (resource) => {
- return ShareTypes.containsAnyValue(ShareTypes.authenticated, $shareTypes(resource))
-}
-
-const isIndirectUserShare = (resource, sharesTree, hasShareJail) => {
- return (
- (resource.isReceivedShare() && !hasShareJail) ||
- ShareTypes.containsAnyValue(
- ShareTypes.authenticated,
- shareTypesIndirect(resource.path, sharesTree)
- )
- )
-}
-
-const isDirectLinkShare = (resource) => {
- return ShareTypes.containsAnyValue(ShareTypes.unauthenticated, $shareTypes(resource))
-}
-
-const isIndirectLinkShare = (resource, sharesTree) => {
- return ShareTypes.containsAnyValue(
- ShareTypes.unauthenticated,
- shareTypesIndirect(resource.path, sharesTree)
- )
-}
-
-const isUserShare = (resource, sharesTree, hasShareJail) => {
- return isDirectUserShare(resource) || isIndirectUserShare(resource, sharesTree, hasShareJail)
+const isUserShare = (shareTypes) => {
+ return ShareTypes.containsAnyValue(ShareTypes.authenticated, shareTypes ?? [])
}
-const isLinkShare = (resource, sharesTree) => {
- return isDirectLinkShare(resource) || isIndirectLinkShare(resource, sharesTree)
+const isLinkShare = (shareTypes) => {
+ return ShareTypes.containsAnyValue(ShareTypes.unauthenticated, shareTypes ?? [])
}
-const shareUserIconDescribedBy = (resource) => {
- return isDirectUserShare(resource)
+const shareUserIconDescribedBy = ({ isDirect }) => {
+ return isDirect
? $gettext('This item is directly shared with others.')
: $gettext('This item is shared with others through one of the parent folders.')
}
-const shareLinkDescribedBy = (resource) => {
- return isDirectLinkShare(resource)
+const shareLinkDescribedBy = ({ isDirect }) => {
+ return isDirect
? $gettext('This item is directly shared via links.')
: $gettext('This item is shared via links through one of the parent folders.')
}
-const shareTypesIndirect = (path, sharesTree) => {
- const parentPaths = getParentPaths(path, true)
-
- if (parentPaths.length === 0) {
- return []
- }
-
- const shareTypes = {}
-
- parentPaths.forEach((parentPath) => {
- // TODO: optimize for performance by skipping once we got all known types
- const shares = sharesTree[parentPath]
-
- if (shares) {
- shares.forEach((share) => {
- // note: no distinction between incoming and outgoing shares as we display the same
- // indirect indicator for them
- shareTypes[share.shareType] = true
- })
+const getUserIndicator = ({ resource, isDirect, isIncoming = false }) => {
+ return {
+ id: `files-sharing-${resource.getDomSelector()}`,
+ accessibleDescription: shareUserIconDescribedBy({ isDirect }),
+ label: isIncoming ? $gettext('Shared with you') : $gettext('Show invited people'),
+ icon: 'group',
+ target: 'sharing',
+ type: isDirect ? 'user-direct' : 'user-indirect',
+ handler: (resource, panel, $router) => {
+ if (isIncoming) {
+ $router.push(createLocationShares('files-shares-with-me'))
+ return
+ }
+ eventBus.publish(SideBarEventTopics.openWithPanel, `${panel}#peopleShares`)
}
- })
-
- return Object.keys(shareTypes).map((shareType) => parseInt(shareType, 10))
+ }
}
-// TODO: Think of a different way how to access sharesTree
-export const getIndicators = (resource, sharesTree, hasShareJail = false) => {
- const indicators = [
- {
- id: `files-sharing-${resource.getDomSelector()}`,
- accessibleDescription: shareUserIconDescribedBy(resource),
- label: $gettext('Show invited people'),
- visible: isUserShare(resource, sharesTree, hasShareJail),
- icon: 'group',
- target: 'sharing',
- type: isDirectUserShare(resource) ? 'user-direct' : 'user-indirect',
- handler: (resource, panel) => {
- eventBus.publish(SideBarEventTopics.openWithPanel, `${panel}#peopleShares`)
- }
- },
- {
- id: `file-link-${resource.getDomSelector()}`,
- accessibleDescription: shareLinkDescribedBy(resource),
- label: $gettext('Show links'),
- visible: isLinkShare(resource, sharesTree),
- icon: 'link',
- target: 'sharing',
- type: isDirectLinkShare(resource) ? 'link-direct' : 'link-indirect',
- handler: (resource, panel) => {
- eventBus.publish(SideBarEventTopics.openWithPanel, `${panel}#linkShares`)
- }
+const getLinkIndicator = ({ resource, isDirect }) => {
+ return {
+ id: `file-link-${resource.getDomSelector()}`,
+ accessibleDescription: shareLinkDescribedBy({ isDirect }),
+ label: $gettext('Show links'),
+ icon: 'link',
+ target: 'sharing',
+ type: isDirect ? 'link-direct' : 'link-indirect',
+ handler: (resource, panel) => {
+ eventBus.publish(SideBarEventTopics.openWithPanel, `${panel}#linkShares`)
}
- ]
+ }
+}
- return indicators.filter((indicator) => indicator.visible)
+export const getIndicators = ({ resource, ancestorMetaData }) => {
+ const indicators = []
+ const parentShareTypes = Object.values(ancestorMetaData).reduce((acc: any, data: any) => {
+ acc.push(...(data.shareTypes || []))
+ return acc
+ }, [])
+ const isDirectUserShare = isUserShare(resource.shareTypes)
+ if (isDirectUserShare || isUserShare(parentShareTypes)) {
+ indicators.push(getUserIndicator({ resource, isDirect: isDirectUserShare }))
+ } else if (resource.isReceivedShare()) {
+ indicators.push(getUserIndicator({ resource, isDirect: false, isIncoming: true }))
+ }
+ const isDirectLinkShare = isLinkShare(resource.shareTypes)
+ if (isDirectLinkShare || isLinkShare(parentShareTypes)) {
+ indicators.push(getLinkIndicator({ resource, isDirect: isDirectLinkShare }))
+ }
+ return indicators
}
diff --git a/packages/web-app-files/src/mixins/deleteResources.ts b/packages/web-app-files/src/mixins/deleteResources.ts
index a5ea0c2d1ae..66b0f328bfd 100644
--- a/packages/web-app-files/src/mixins/deleteResources.ts
+++ b/packages/web-app-files/src/mixins/deleteResources.ts
@@ -95,7 +95,7 @@ export default {
},
methods: {
- ...mapActions('Files', ['pushResourcesToDeleteList', 'removeFilesFromTrashbin', 'deleteFiles']),
+ ...mapActions('Files', ['removeFilesFromTrashbin', 'deleteFiles']),
...mapActions(['showMessage', 'toggleModalConfirmButton', 'hideModal', 'createModal']),
...mapMutations('runtime/spaces', ['UPDATE_SPACE_FIELD']),
...mapMutations(['SET_QUOTA']),
diff --git a/packages/web-app-files/src/services/folder/loaderSpace.ts b/packages/web-app-files/src/services/folder/loaderSpace.ts
index 420c4beed16..42d88a664a3 100644
--- a/packages/web-app-files/src/services/folder/loaderSpace.ts
+++ b/packages/web-app-files/src/services/folder/loaderSpace.ts
@@ -2,18 +2,14 @@ import { FolderLoader, FolderLoaderTask, TaskContext } from '../folder'
import { Router } from 'vue-router'
import { useTask } from 'vue-concurrency'
import { isLocationPublicActive, isLocationSpacesActive } from '../../router'
-import {
- useCapabilityFilesSharingResharing,
- useCapabilityShareJailEnabled,
- useCapabilitySpacesEnabled
-} from 'web-pkg/src/composables'
-import { getIndicators } from '../../helpers/statusIndicators'
+import { useCapabilityFilesSharingResharing } from 'web-pkg/src/composables'
import { SpaceResource } from 'web-client/src/helpers'
import { unref } from 'vue'
import { FolderLoaderOptions } from './types'
import { authService } from 'web-runtime/src/services/auth'
import { useFileRouteReplace } from 'web-pkg/src/composables/router/useFileRouteReplace'
import { aggregateResourceShares } from '../../helpers/resources'
+import { getIndicators } from 'web-app-files/src/helpers/statusIndicators'
export class FolderLoaderSpace implements FolderLoader {
public isEnabled(): boolean {
@@ -32,15 +28,10 @@ export class FolderLoaderSpace implements FolderLoader {
}
public getTask(context: TaskContext): FolderLoaderTask {
- const {
- store,
- router,
- clientService: { owncloudSdk: client, webdav }
- } = context
+ const { store, router, clientService } = context
+ const { owncloudSdk: client, webdav } = clientService
const { replaceInvalidFileRoute } = useFileRouteReplace({ router })
- const hasShareJail = useCapabilityShareJailEnabled(store)
const hasResharing = useCapabilityFilesSharingResharing(store)
- const hasSpaces = useCapabilitySpacesEnabled(store)
return useTask(function* (
signal1,
@@ -75,25 +66,19 @@ export class FolderLoaderSpace implements FolderLoader {
}
}
- if (options.loadShares) {
- yield store.dispatch('Files/loadSharesTree', {
- client,
- path: currentFolder.path,
- ...(unref(hasSpaces) && { storageId: currentFolder.fileId }),
- includeRoot: currentFolder.path === '/' && space.driveType !== 'personal'
- })
-
- for (const file of resources) {
- file.indicators = getIndicators(file, store.state.Files.sharesTree, unref(hasShareJail))
- }
- }
-
yield store.dispatch('Files/loadAncestorMetaData', {
folder: currentFolder,
space,
client: webdav
})
+ if (options.loadShares) {
+ const ancestorMetaData = store.getters['Files/ancestorMetaData']
+ for (const file of resources) {
+ file.indicators = getIndicators({ resource: file, ancestorMetaData })
+ }
+ }
+
store.commit('Files/LOAD_FILES', {
currentFolder,
files: resources
diff --git a/packages/web-app-files/src/store/actions.ts b/packages/web-app-files/src/store/actions.ts
index d627f6f8cad..814a82e3251 100644
--- a/packages/web-app-files/src/store/actions.ts
+++ b/packages/web-app-files/src/store/actions.ts
@@ -1,5 +1,4 @@
import PQueue from 'p-queue'
-import { dirname } from 'path'
import { getParentPaths } from '../helpers/path'
import { buildShare, buildCollaboratorShare } from '../helpers/resources'
@@ -269,16 +268,18 @@ export default {
const shareMethod = isGroupShare ? 'shareFileWithGroup' : 'shareFileWithUser'
return client.shares[shareMethod](path, shareWith, options)
.then((share) => {
- context.commit(
- 'CURRENT_FILE_OUTGOING_SHARES_UPSERT',
- buildCollaboratorShare(
- share.shareInfo,
- context.getters.highlightedFile,
- allowSharePermissions(context.rootGetters)
- )
+ const builtShare = buildCollaboratorShare(
+ share.shareInfo,
+ context.getters.highlightedFile,
+ allowSharePermissions(context.rootGetters)
)
+ context.commit('CURRENT_FILE_OUTGOING_SHARES_UPSERT', builtShare)
+ context.commit('SHARESTREE_UPSERT', {
+ path,
+ share: { ...builtShare, indirect: false, outgoing: true }
+ })
context.dispatch('updateCurrentFileShareTypes')
- context.dispatch('loadIndicators', { client, currentFolder: path, storageId })
+ context.commit('LOAD_INDICATORS', path)
})
.catch((e) => {
context.dispatch(
@@ -292,13 +293,13 @@ export default {
)
})
},
- deleteShare(context, { client, share, path, storageId, loadIndicators = false }) {
+ deleteShare(context, { client, share, path, loadIndicators = false }) {
return client.shares.deleteShare(share.id, {} as any).then(() => {
context.commit('CURRENT_FILE_OUTGOING_SHARES_REMOVE', share)
context.dispatch('updateCurrentFileShareTypes')
-
+ context.commit('SHARESTREE_REMOVE', { path, id: share.id })
if (loadIndicators) {
- context.dispatch('loadIndicators', { client, currentFolder: path, storageId })
+ context.commit('LOAD_INDICATORS', path)
}
})
},
@@ -369,9 +370,9 @@ export default {
}
parentPaths.forEach((queryPath) => {
+ const ancestorMetaData = context.state.ancestorMetaData[queryPath] ?? null
const indirect = path !== queryPath
- // FIXME: We need the storageId of each parent resource here
- const spaceRef = indirect ? null : storageId
+ const spaceRef = indirect ? ancestorMetaData?.id : storageId
// no need to fetch cached paths again, only adjust the "indirect" state
if (context.getters.sharesTree[queryPath] && useCached) {
sharesTree[queryPath] = context.getters.sharesTree[queryPath].map((s) => {
@@ -424,7 +425,11 @@ export default {
const link = buildShare(data.shareInfo, null, allowSharePermissions(context.rootGetters))
context.commit('CURRENT_FILE_OUTGOING_SHARES_UPSERT', link)
context.dispatch('updateCurrentFileShareTypes')
- context.dispatch('loadIndicators', { client, currentFolder: path, storageId })
+ context.commit('LOAD_INDICATORS', path)
+ context.commit('SHARESTREE_UPSERT', {
+ path,
+ share: { ...link, indirect: false, outgoing: true }
+ })
resolve(link)
})
.catch((e) => {
@@ -446,34 +451,17 @@ export default {
})
})
},
- removeLink(context, { share, client, path, storageId, loadIndicators = false }) {
+ removeLink(context, { share, client, path, loadIndicators = false }) {
return client.shares.deleteShare(share.id).then(() => {
context.commit('CURRENT_FILE_OUTGOING_SHARES_REMOVE', share)
context.dispatch('updateCurrentFileShareTypes')
-
+ context.commit('SHARESTREE_REMOVE', { path, id: share.id })
if (loadIndicators) {
- context.dispatch('loadIndicators', { client, currentFolder: path, storageId })
+ context.commit('LOAD_INDICATORS', path)
}
})
},
- pushResourcesToDeleteList({ commit }, resources) {
- commit('PUSH_RESOURCES_TO_DELETE_LIST', resources)
- },
-
- async loadIndicators({ dispatch, commit }, { client, currentFolder, storageId }) {
- // kind of bruteforce for now: remove the shares for the current folder and children, reload shares tree for the current folder.
- // TODO: when we refactor the shares tree we want to modify shares tree nodes incrementally during adding and removing shares, not loading everything new from the backend.
- commit('SHARESTREE_PRUNE_OUTSIDE_PATH', dirname(currentFolder))
- await dispatch('loadSharesTree', {
- client,
- path: currentFolder,
- storageId,
- includeRoot: currentFolder === '/'
- })
- commit('LOAD_INDICATORS', currentFolder)
- },
-
loadAvatars({ commit, rootGetters }, { resource }) {
if (!rootGetters.capabilities.files_sharing.user.profile_picture) {
return
diff --git a/packages/web-app-files/src/store/mutations.ts b/packages/web-app-files/src/store/mutations.ts
index 53288fd4dca..becefaf2e26 100644
--- a/packages/web-app-files/src/store/mutations.ts
+++ b/packages/web-app-files/src/store/mutations.ts
@@ -132,6 +132,18 @@ export default {
SHARESTREE_ADD(state, sharesTree) {
state.sharesTree = Object.assign({}, state.sharesTree, sharesTree)
},
+ SHARESTREE_UPSERT(state, { path, share }) {
+ if (!state.sharesTree[path]) {
+ state.sharesTree[path] = []
+ }
+ state.sharesTree[path].push(share)
+ },
+ SHARESTREE_REMOVE(state, { path, id }) {
+ if (!state.sharesTree[path]) {
+ return
+ }
+ state.sharesTree[path] = state.sharesTree[path].filter((s) => s.id !== id)
+ },
SHARESTREE_ERROR(state, error) {
state.sharesTreeError = error
},
@@ -158,8 +170,7 @@ export default {
LOAD_INDICATORS(state, path) {
const files = state.files.filter((f) => f.path.startsWith(path))
for (const resource of files) {
- const indicators = getIndicators(resource, state.sharesTree)
-
+ const indicators = getIndicators({ resource, ancestorMetaData: state.ancestorMetaData })
if (!indicators.length && !resource.indicators.length) {
continue
}
diff --git a/packages/web-app-files/src/views/shares/SharedViaLink.vue b/packages/web-app-files/src/views/shares/SharedViaLink.vue
index 724f2322f8d..47722271124 100644
--- a/packages/web-app-files/src/views/shares/SharedViaLink.vue
+++ b/packages/web-app-files/src/views/shares/SharedViaLink.vue
@@ -61,7 +61,7 @@