Merge pull request #15419 from nextcloud/fix/vue3/right-sidebar-shared-items

fix: expand ts migration and fix infinite loading bug of shared items tab in 1-1 conversation
This commit is contained in:
Dorra
2025-06-27 11:01:28 +02:00
committed by GitHub
12 changed files with 184 additions and 219 deletions

View File

@ -80,7 +80,7 @@ import { useViewer } from '../../../../../composables/useViewer.js'
import { SHARED_ITEM } from '../../../../../constants.ts'
import { getTalkConfig } from '../../../../../services/CapabilitiesManager.ts'
import { useActorStore } from '../../../../../stores/actor.ts'
import { useSharedItemsStore } from '../../../../../stores/sharedItems.js'
import { useSharedItemsStore } from '../../../../../stores/sharedItems.ts'
const PREVIEW_TYPE = {
TEMPORARY: 0,

View File

@ -301,8 +301,8 @@ export default {
|| this.conversation.participantType === PARTICIPANT.TYPE.MODERATOR
},
isModeratorOrUser() {
return this.$store.getters.isModeratorOrUser
isGuestModerator() {
return this.conversation?.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR
},
isInLobby() {
@ -339,7 +339,7 @@ export default {
},
showParticipantsTab() {
return (this.getUserId || this.isModeratorOrUser) && (!this.isOneToOne || this.isInCall) && !this.isNoteToSelf
return (this.getUserId || this.isGuestModerator) && (!this.isOneToOne || this.isInCall) && !this.isNoteToSelf
},
showSharedItemsTab() {
@ -461,7 +461,7 @@ export default {
immediate: true,
},
isModeratorOrUser(newValue) {
isGuestModerator(newValue) {
if (newValue && !this.isInCall) {
// Switch active tab to participants list if guest was promoted to moderators
this.activeTab = 'participants'

View File

@ -5,23 +5,20 @@
<template>
<div class="shared-items" :class="{ 'shared-items__list': hasListLayout }">
<template v-for="item in itemsToDisplay">
<div v-if="isLocation" :key="item.id" class="shared-items__location">
<template v-for="item in itemsToDisplay" :key="item.id">
<div v-if="isLocation" class="shared-items__location">
<Location wide v-bind="item.messageParameters.object" />
</div>
<DeckCard v-else-if="isDeckCard"
:key="item.id"
wide
v-bind="item.messageParameters.object" />
<Poll v-else-if="isPoll"
:key="item.id"
:token="token"
v-bind="item.messageParameters.object" />
<div v-else-if="isOther"
:key="item.id"
class="shared-items__other">
<a v-if="item.messageParameters.object?.link"
:href="item.messageParameters.object.link"
@ -34,7 +31,6 @@
</div>
<FilePreview v-else
:key="item.id"
:token="token"
:small-preview="!isMedia"
:row-layout="!isMedia"

View File

@ -38,8 +38,8 @@ import NcButton from '@nextcloud/vue/components/NcButton'
import NcModal from '@nextcloud/vue/components/NcModal'
import SharedItems from './SharedItems.vue'
import { useId } from '../../../composables/useId.ts'
import { useSharedItemsStore } from '../../../stores/sharedItems.js'
import { sharedItemsOrder, sharedItemTitle } from './sharedItemsConstants.js'
import { useSharedItemsStore } from '../../../stores/sharedItems.ts'
import { sharedItemsOrder, sharedItemTitle } from './sharedItemsConstants.ts'
export default {
name: 'SharedItemsBrowser',

View File

@ -3,9 +3,103 @@
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<script lang="ts" setup>
import type {
Conversation,
SharedItems as ShareItemsType,
} from '../../../types/index.ts'
import { loadState } from '@nextcloud/initial-state'
import { t } from '@nextcloud/l10n'
import { computed, ref, watch } from 'vue'
import { useStore } from 'vuex'
import NcAppNavigationCaption from '@nextcloud/vue/components/NcAppNavigationCaption'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcCollectionList from '@nextcloud/vue/components/NcCollectionList'
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import NcRelatedResourcesPanel from '@nextcloud/vue/components/NcRelatedResourcesPanel'
import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
import FolderMultipleImage from 'vue-material-design-icons/FolderMultipleImage.vue'
import IconPoll from 'vue-material-design-icons/Poll.vue'
import LoadingComponent from '../../LoadingComponent.vue'
import SharedItems from './SharedItems.vue'
import SharedItemsBrowser from './SharedItemsBrowser.vue'
import { useGetToken } from '../../../composables/useGetToken.ts'
import { CONVERSATION } from '../../../constants.ts'
import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts'
import { EventBus } from '../../../services/EventBus.ts'
import { useActorStore } from '../../../stores/actor.ts'
import { useSharedItemsStore } from '../../../stores/sharedItems.ts'
import { useSidebarStore } from '../../../stores/sidebar.ts'
import {
sharedItemButtonTitle,
sharedItemsOrder,
sharedItemsWithPreviewLimit,
sharedItemTitle,
} from './sharedItemsConstants.ts'
const props = defineProps<{
active: boolean
}>()
const token = useGetToken()
const showSharedItemsBrowser = ref(false)
const browserActiveTab = ref('')
const projectsEnabled = loadState('core', 'projects_enabled', false)
const hasRelatedResources = ref(false)
const store = useStore()
const sharedItemsStore = useSharedItemsStore()
const sidebarStore = useSidebarStore()
const actorStore = useActorStore()
const conversation = computed<Conversation>(() => store.getters.conversation(token.value))
const canCreatePollDrafts = computed(() => {
return hasTalkFeature(token.value, 'talk-polls-drafts') && store.getters.isModerator
&& [CONVERSATION.TYPE.GROUP, CONVERSATION.TYPE.PUBLIC].includes(conversation.value.type)
})
const sharedItems = computed(() => sharedItemsStore.sharedItems(token.value))
const hasSharedItems = computed(() => Object.keys(sharedItems.value).length > 0)
watch([token, () => props.active, () => sidebarStore.show], ([token, isActive, isOpen]) => {
if (token && isActive && isOpen) {
sharedItemsStore.getSharedItemsOverview(token)
}
}, { immediate: true })
/**
* Check if there are more items of a specific type than the limit allows.
*/
function hasMore(type: string, items: ShareItemsType) {
return Object.values(items).length > limit(type)
}
/**
* Open the SharedItemsBrowser dialog for a specific type of shared items.
*/
function showMore(type: string) {
browserActiveTab.value = type
showSharedItemsBrowser.value = true
}
/**
* Get the limit for the number of items displayed based on the type.
*/
function limit(type: string) {
return sharedItemsWithPreviewLimit.includes(type) ? 2 : 6
}
/**
* Open the Poll Drafts browser dialog.
*/
function openPollDraftHandler() {
EventBus.emit('poll-drafts-open', { token: token.value })
}
</script>
<template>
<div class="shared-items-tab">
<LoadingComponent v-if="loading" class="shared-items-tab__loading" />
<LoadingComponent v-if="!sharedItemsStore.overviewLoaded[token]" class="shared-items-tab__loading" />
<template v-else>
<NcButton v-if="canCreatePollDrafts"
@ -17,8 +111,8 @@
{{ t('spreed', 'Browse poll drafts') }}
</NcButton>
<!-- Shared items grouped by type -->
<template v-for="type in sharedItemsOrder">
<div v-if="sharedItems[type]" :key="type">
<template v-for="type in sharedItemsOrder" :key="type">
<div v-if="sharedItems[type]">
<NcAppNavigationCaption :name="sharedItemTitle[type] || sharedItemTitle.default" />
<SharedItems :type="type"
:token="token"
@ -42,12 +136,12 @@
<NcRelatedResourcesPanel class="related-resources"
provider-id="talk"
:item-id="conversation.token"
@has-resources="value => hasRelatedResources = value" />
@has-resources="(value: boolean) => hasRelatedResources = value" />
<!-- Shared from "Projects" app -->
<template v-if="projectsEnabled">
<NcAppNavigationCaption :name="t('spreed', 'Projects')" />
<NcCollectionList v-if="getUserId && token"
<NcCollectionList v-if="actorStore.userId && token"
:id="token"
type="room"
:name="conversation.displayName"
@ -73,149 +167,6 @@
</div>
</template>
<script>
import { loadState } from '@nextcloud/initial-state'
import { t } from '@nextcloud/l10n'
import NcAppNavigationCaption from '@nextcloud/vue/components/NcAppNavigationCaption'
import NcButton from '@nextcloud/vue/components/NcButton'
import NcCollectionList from '@nextcloud/vue/components/NcCollectionList'
import NcEmptyContent from '@nextcloud/vue/components/NcEmptyContent'
import NcRelatedResourcesPanel from '@nextcloud/vue/components/NcRelatedResourcesPanel'
import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
import FolderMultipleImage from 'vue-material-design-icons/FolderMultipleImage.vue'
import IconPoll from 'vue-material-design-icons/Poll.vue'
import LoadingComponent from '../../LoadingComponent.vue'
import SharedItems from './SharedItems.vue'
import SharedItemsBrowser from './SharedItemsBrowser.vue'
import { useGetToken } from '../../../composables/useGetToken.ts'
import { CONVERSATION } from '../../../constants.ts'
import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts'
import { EventBus } from '../../../services/EventBus.ts'
import { useActorStore } from '../../../stores/actor.ts'
import { useSharedItemsStore } from '../../../stores/sharedItems.js'
import { useSidebarStore } from '../../../stores/sidebar.ts'
import {
sharedItemButtonTitle,
sharedItemsOrder,
sharedItemsWithPreviewLimit,
sharedItemTitle,
} from './sharedItemsConstants.js'
export default {
name: 'SharedItemsTab',
components: {
DotsHorizontal,
FolderMultipleImage,
IconPoll,
LoadingComponent,
NcAppNavigationCaption,
NcButton,
NcCollectionList,
NcEmptyContent,
NcRelatedResourcesPanel,
SharedItems,
SharedItemsBrowser,
},
props: {
active: {
type: Boolean,
required: true,
},
},
setup() {
return {
actorStore: useActorStore(),
sharedItemsStore: useSharedItemsStore(),
sidebarStore: useSidebarStore(),
sharedItemButtonTitle,
sharedItemTitle,
sharedItemsOrder,
sharedItemsWithPreviewLimit,
token: useGetToken(),
}
},
data() {
return {
showSharedItemsBrowser: false,
browserActiveTab: '',
projectsEnabled: loadState('core', 'projects_enabled', false),
hasRelatedResources: false,
}
},
computed: {
getUserId() {
return this.actorStore.userId
},
conversation() {
return this.$store.getters.conversation(this.token)
},
canCreatePollDrafts() {
return hasTalkFeature(this.token, 'talk-polls-drafts') && this.$store.getters.isModerator
&& [CONVERSATION.TYPE.GROUP, CONVERSATION.TYPE.PUBLIC].includes(this.conversation.type)
},
loading() {
return !this.sharedItemsStore.overviewLoaded[this.token]
},
sharedItems() {
return this.sharedItemsStore.sharedItems(this.token)
},
hasSharedItems() {
return Object.keys(this.sharedItems).length > 0
},
isSidebarOpen() {
return this.sidebarStore.show
},
sharedItemsIdentifier() {
return this.token + ':' + this.active + ':' + this.isSidebarOpen
},
},
watch: {
sharedItemsIdentifier: {
immediate: true,
handler() {
if (this.token && this.active && this.isSidebarOpen) {
this.sharedItemsStore.getSharedItemsOverview(this.token)
}
},
},
},
methods: {
t,
hasMore(type, items) {
return Object.values(items).length > this.limit(type)
},
showMore(type) {
this.browserActiveTab = type
this.showSharedItemsBrowser = true
},
limit(type) {
return this.sharedItemsWithPreviewLimit.includes(type) ? 2 : 6
},
openPollDraftHandler() {
EventBus.emit('poll-drafts-open', { token: this.token })
},
},
}
</script>
<style lang="scss" scoped>
.more {
margin-top: 8px;

View File

@ -13,9 +13,9 @@ export const sharedItemsOrder = [SHARED_ITEM.TYPES.MEDIA,
SHARED_ITEM.TYPES.AUDIO,
SHARED_ITEM.TYPES.LOCATION,
SHARED_ITEM.TYPES.DECK_CARD,
SHARED_ITEM.TYPES.OTHER]
SHARED_ITEM.TYPES.OTHER] as const
export const sharedItemsWithPreviewLimit = [SHARED_ITEM.TYPES.DECK_CARD, SHARED_ITEM.TYPES.LOCATION, SHARED_ITEM.TYPES.POLL]
export const sharedItemsWithPreviewLimit = [SHARED_ITEM.TYPES.DECK_CARD, SHARED_ITEM.TYPES.LOCATION, SHARED_ITEM.TYPES.POLL] as const
export const sharedItemTitle = {
[SHARED_ITEM.TYPES.MEDIA]: t('spreed', 'Media'),
@ -28,7 +28,7 @@ export const sharedItemTitle = {
[SHARED_ITEM.TYPES.AUDIO]: t('spreed', 'Audio'),
[SHARED_ITEM.TYPES.OTHER]: t('spreed', 'Other'),
default: t('spreed', 'Other'),
}
} as const
export const sharedItemButtonTitle = {
[SHARED_ITEM.TYPES.MEDIA]: t('spreed', 'Show all media'),
@ -41,4 +41,4 @@ export const sharedItemButtonTitle = {
[SHARED_ITEM.TYPES.AUDIO]: t('spreed', 'Show all audio'),
[SHARED_ITEM.TYPES.OTHER]: t('spreed', 'Show all other'),
default: t('spreed', 'Show all other'),
}
} as const

View File

@ -3,12 +3,19 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type {
getSharedItemsOverviewParams,
getSharedItemsOverviewResponse,
getSharedItemsParams,
getSharedItemsResponse,
} from '../types/index.ts'
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
// Returns the last n shared items for each category and for a given conversation
// (n = limit)
const getSharedItemsOverview = async function(token, limit) {
const getSharedItemsOverview = async function({ token, limit }: { token: string } & getSharedItemsOverviewParams): getSharedItemsOverviewResponse {
return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}/share/overview', {
token,
}), {
@ -20,7 +27,7 @@ const getSharedItemsOverview = async function(token, limit) {
// Returns the last 200 (or limit) shared items, given a conversation and the type
// of shared item
const getSharedItems = async function(token, objectType, lastKnownMessageId, limit) {
const getSharedItems = async function({ token, objectType, lastKnownMessageId, limit }: { token: string } & getSharedItemsParams): getSharedItemsResponse {
return axios.get(generateOcsUrl('apps/spreed/api/v1/chat/{token}/share', {
token,
}), {

View File

@ -70,7 +70,7 @@ import { useFederationStore } from '../stores/federation.ts'
import { useGroupwareStore } from '../stores/groupware.ts'
import pinia from '../stores/pinia.ts'
import { useReactionsStore } from '../stores/reactions.js'
import { useSharedItemsStore } from '../stores/sharedItems.js'
import { useSharedItemsStore } from '../stores/sharedItems.ts'
import { useTalkHashStore } from '../stores/talkHash.js'
import { useTokenStore } from '../stores/token.ts'
import { convertToUnix } from '../utils/formattedTime.ts'

View File

@ -29,7 +29,7 @@ import { useCallViewStore } from '../stores/callView.ts'
import { useGuestNameStore } from '../stores/guestName.js'
import { usePollsStore } from '../stores/polls.ts'
import { useReactionsStore } from '../stores/reactions.js'
import { useSharedItemsStore } from '../stores/sharedItems.js'
import { useSharedItemsStore } from '../stores/sharedItems.ts'
import CancelableRequest from '../utils/cancelableRequest.js'
import { debugTimer } from '../utils/debugTimer.ts'
import { convertToUnix } from '../utils/formattedTime.ts'

View File

@ -3,11 +3,11 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { createPinia, setActivePinia } from 'pinia'
import { sharedItemsOrder } from '../../components/RightSidebar/SharedItems/sharedItemsConstants.js'
import { sharedItemsOrder } from '../../components/RightSidebar/SharedItems/sharedItemsConstants.ts'
import { SHARED_ITEM } from '../../constants.ts'
import { getSharedItems, getSharedItemsOverview } from '../../services/sharedItemsService.js'
import { getSharedItems, getSharedItemsOverview } from '../../services/sharedItemsService.ts'
import { generateOCSErrorResponse, generateOCSResponse } from '../../test-helpers.js'
import { useSharedItemsStore } from '../sharedItems.js'
import { useSharedItemsStore } from '../sharedItems.ts'
jest.mock('../../services/sharedItemsService', () => ({
getSharedItems: jest.fn(),
@ -123,7 +123,7 @@ describe('sharedItemsStore', () => {
await sharedItemsStore.getSharedItemsOverview(token)
// Assert
expect(getSharedItemsOverview).toHaveBeenCalledWith(token, limitOverview)
expect(getSharedItemsOverview).toHaveBeenCalledWith({ token, limit: limitOverview })
expect(sharedItemsStore.sharedItems(token)).toEqual(result)
})
@ -147,7 +147,12 @@ describe('sharedItemsStore', () => {
await sharedItemsStore.getSharedItems(token, SHARED_ITEM.TYPES.MEDIA)
// Assert
expect(getSharedItems).toHaveBeenCalledWith(token, SHARED_ITEM.TYPES.MEDIA, 100, limitGeneral)
expect(getSharedItems).toHaveBeenCalledWith({
token,
objectType: SHARED_ITEM.TYPES.MEDIA,
lastKnownMessageId: 100,
limit: limitGeneral,
})
expect(sharedItemsStore.sharedItems(token)).toEqual(result)
})
@ -163,7 +168,12 @@ describe('sharedItemsStore', () => {
const output = await sharedItemsStore.getSharedItems(token, SHARED_ITEM.TYPES.MEDIA)
// Assert
expect(getSharedItems).toHaveBeenCalledWith(token, SHARED_ITEM.TYPES.MEDIA, 100, limitGeneral)
expect(getSharedItems).toHaveBeenCalledWith({
token,
objectType: SHARED_ITEM.TYPES.MEDIA,
lastKnownMessageId: 100,
limit: limitGeneral,
})
expect(output).toEqual({ hasMoreItems: false, messages: [] })
expect(sharedItemsStore.sharedItems(token)).toEqual(result)
})

View File

@ -3,31 +3,24 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type {
ChatMessage,
SharedItems,
SharedItemsOverview,
} from '../types/index.ts'
import { defineStore } from 'pinia'
import { getSharedItems, getSharedItemsOverview } from '../services/sharedItemsService.js'
import { getSharedItems, getSharedItemsOverview } from '../services/sharedItemsService.ts'
import { getItemTypeFromMessage } from '../utils/getItemTypeFromMessage.ts'
/**
* @typedef {'media'|'file'|'voice'|'audio'|'location'|'deckcard'|'other'} Type
* @typedef {string} Token
*/
type SharedItemType = keyof SharedItemsOverview
/**
* @typedef {object} Message
* @property {string} token - conversation token
* @property {number} id - message id
*/
type SharedItemsPoolType = Record<string, Record<SharedItemType, Record<number, SharedItems[keyof SharedItems]>>>
/**
* @typedef {object} Messages
* @property {{[key: number]: Message}} messages - messages with shared items for this conversation
*/
/**
* @typedef {object} State
* @property {{[key: Token]: {[key: Type]: Messages}}} sharedItemsPool - The shared items pool.
* @property {{[key: Token]: boolean}} overviewLoaded - The overview loaded state.
*/
type State = {
sharedItemsPool: SharedItemsPoolType
overviewLoaded: Record<string, boolean>
}
/**
* Store for shared items shown in RightSidebar
@ -36,13 +29,13 @@ import { getItemTypeFromMessage } from '../utils/getItemTypeFromMessage.ts'
* @param {State} options.state store state structure
*/
export const useSharedItemsStore = defineStore('sharedItems', {
state: () => ({
state: (): State => ({
sharedItemsPool: {},
overviewLoaded: {},
}),
getters: {
sharedItems: (state) => (token) => {
sharedItems: (state) => (token: string) => {
if (!state.sharedItemsPool[token]) {
state.sharedItemsPool[token] = {}
}
@ -52,7 +45,7 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
actions: {
checkForExistence(token, type) {
checkForExistence(token: string, type: SharedItemType) {
if (token && !this.sharedItemsPool[token]) {
this.sharedItemsPool[token] = {}
}
@ -62,10 +55,10 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
/**
* @param {Token} token conversation token
* @param {{[key: Type]: Message[]}} data server response
* @param token conversation token
* @param data server response
*/
addSharedItemsFromOverview(token, data) {
addSharedItemsFromOverview(token: string, data: SharedItemsOverview) {
for (const type of Object.keys(data)) {
if (Object.keys(data[type]).length) {
this.checkForExistence(token, type)
@ -81,10 +74,10 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
/**
* @param {Token} token conversation token
* @param {Message} message message with shared items
* @param token conversation token
* @param message message with shared items
*/
addSharedItemFromMessage(token, message) {
addSharedItemFromMessage(token: string, message: ChatMessage) {
const type = getItemTypeFromMessage(message)
this.checkForExistence(token, type)
@ -94,10 +87,10 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
/**
* @param {Token} token conversation token
* @param {string} messageId id of message to be deleted
* @param token conversation token
* @param messageId id of message to be deleted
*/
deleteSharedItemFromMessage(token, messageId) {
deleteSharedItemFromMessage(token: string, messageId: number) {
if (!this.sharedItemsPool[token]) {
return
}
@ -117,7 +110,7 @@ export const useSharedItemsStore = defineStore('sharedItems', {
* @param {Type} type type of shared item
* @param {Message[]} messages message with shared items
*/
addSharedItemsFromMessages(token, type, messages) {
addSharedItemsFromMessages(token: string, type: string, messages: SharedItems[keyof SharedItems][]) {
this.checkForExistence(token, type)
messages.forEach((message) => {
@ -128,11 +121,11 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
/**
* @param {Token} token conversation token
* @param {string} messageId starting message id to purge shared items from older messages
* @param token conversation token
* @param messageId starting message id to purge shared items from older messages
* If messageId is not provided, all shared items in this conversation will be deleted.
*/
purgeSharedItemsStore(token, messageId = null) {
purgeSharedItemsStore(token: string, messageId: number | null = null) {
if (!this.sharedItemsPool[token]) {
return
}
@ -141,7 +134,7 @@ export const useSharedItemsStore = defineStore('sharedItems', {
for (const type of Object.keys(this.sharedItemsPool[token])) {
for (const id of Object.keys(this.sharedItemsPool[token][type])) {
if (+id < +messageId) {
delete this.sharedItemsPool[token][type][id]
delete this.sharedItemsPool[token][type][+id]
}
}
if (Object.keys(this.sharedItemsPool[token][type]).length === 0) {
@ -157,10 +150,10 @@ export const useSharedItemsStore = defineStore('sharedItems', {
},
/**
* @param {Token} token conversation token
* @param {Type} type type of shared item
* @param token conversation token
* @param type type of shared item
*/
async getSharedItems(token, type) {
async getSharedItems(token: string, type: string) {
// function is called from Message or SharedItemsBrowser, poll should not be empty at the moment
if (!this.sharedItemsPool[token] || !this.sharedItemsPool[token][type]) {
console.error(`Missing shared items poll of type '${type}' in conversation ${token}`)
@ -168,9 +161,9 @@ export const useSharedItemsStore = defineStore('sharedItems', {
}
const limit = 20
const lastKnownMessageId = Math.min.apply(Math, Object.keys(this.sharedItemsPool[token][type]))
const lastKnownMessageId = Math.min(...Object.keys(this.sharedItemsPool[token][type]).map(Number))
try {
const response = await getSharedItems(token, type, lastKnownMessageId, limit)
const response = await getSharedItems({ token, objectType: type, lastKnownMessageId, limit })
const messages = Object.values(response.data.ocs.data)
if (messages.length) {
this.addSharedItemsFromMessages(token, type, messages)
@ -185,13 +178,13 @@ export const useSharedItemsStore = defineStore('sharedItems', {
/**
* @param {Token} token conversation token
*/
async getSharedItemsOverview(token) {
async getSharedItemsOverview(token: string) {
if (this.overviewLoaded[token]) {
return
}
try {
const response = await getSharedItemsOverview(token, 7)
const response = await getSharedItemsOverview({ token, limit: 7 })
this.addSharedItemsFromOverview(token, response.data.ocs.data)
} catch (error) {
console.error(error)

View File

@ -348,6 +348,14 @@ export type deletePollDraftResponse = ApiResponse<operations['poll-close-poll'][
export type requiredPollParams = Omit<createPollParams, 'draft'>
// Shared items
export type getSharedItemsOverviewParams = operations['chat-get-objects-shared-in-room-overview']['parameters']['query']
export type getSharedItemsOverviewResponse = ApiResponse<operations['chat-get-objects-shared-in-room-overview']['responses'][200]['content']['application/json']>
export type SharedItemsOverview = operations['chat-get-objects-shared-in-room-overview']['responses'][200]['content']['application/json']['ocs']['data']
export type getSharedItemsParams = operations['chat-get-objects-shared-in-room']['parameters']['query']
export type getSharedItemsResponse = ApiResponse<operations['chat-get-objects-shared-in-room']['responses'][200]['content']['application/json']>
export type SharedItems = operations['chat-get-objects-shared-in-room']['responses'][200]['content']['application/json']['ocs']['data']
// Mentions
export type ChatMention = components['schemas']['ChatMentionSuggestion']
export type getMentionsParams = operations['chat-mentions']['parameters']['query']