Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/spreed.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoas Schilling <213943+nickvergessen@users.noreply.github.com>2022-04-29 17:48:02 +0300
committerGitHub <noreply@github.com>2022-04-29 17:48:02 +0300
commita2457acf98f8ec1b142504f8ae51fd7c42e52186 (patch)
treed4bd36dc7f3ebcaf58ef3ef1f43813ad9559cbf9
parentbec039c41769affbe30b1a2b68780a34394d41f1 (diff)
parent7cc1b74b24981c6b974d43b1510793886fc55645 (diff)
Merge pull request #7252 from nextcloud/backport/7154/stable24v14.0.0-rc.4
[stable24] Shared Items browser
-rw-r--r--src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue4
-rw-r--r--src/components/RightSidebar/SharedItems/SharedItems.vue107
-rw-r--r--src/components/RightSidebar/SharedItems/SharedItemsBrowser/SharedItemsBrowser.vue173
-rw-r--r--src/components/RightSidebar/SharedItems/SharedItemsTab.vue85
-rw-r--r--src/mixins/sharedItems.js57
-rw-r--r--src/services/sharedItemsService.js (renamed from src/services/conversationSharedItemsService.js)0
-rw-r--r--src/store/sharedItemsStore.js (renamed from src/store/conversationSharedItemsStore.js)8
-rw-r--r--src/store/storeConfig.js4
8 files changed, 330 insertions, 108 deletions
diff --git a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue
index 09cda5d64..553b675bd 100644
--- a/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue
+++ b/src/components/MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue
@@ -295,7 +295,7 @@ export default {
classes += 'preview '
}
- if (this.failed || this.previewType === PREVIEW_TYPE.MIME_ICON) {
+ if (this.failed || this.previewType === PREVIEW_TYPE.MIME_ICON || this.rowLayout) {
classes += 'mimeicon'
}
return classes
@@ -323,7 +323,7 @@ export default {
if (this.previewType === PREVIEW_TYPE.TEMPORARY) {
return this.localUrl
}
- if (this.previewType === PREVIEW_TYPE.MIME_ICON) {
+ if (this.previewType === PREVIEW_TYPE.MIME_ICON || this.rowLayout) {
return OC.MimeType.getIconUrl(this.mimetype)
}
// whether to embed/render the file directly
diff --git a/src/components/RightSidebar/SharedItems/SharedItems.vue b/src/components/RightSidebar/SharedItems/SharedItems.vue
index 072e268e4..d2c848804 100644
--- a/src/components/RightSidebar/SharedItems/SharedItems.vue
+++ b/src/components/RightSidebar/SharedItems/SharedItems.vue
@@ -20,48 +20,26 @@
-->
<template>
- <div class="shared-items">
- <AppNavigationCaption :title="title" />
- <div class="files" :class="{'files__list' : isList}">
- <template v-for="file in itemsToDisplay">
- <FilePreview :key="file.id"
- :small-preview="isList"
- :row-layout="isList"
- :is-shared-items-tab="true"
- v-bind="file.messageParameters.file" />
- </template>
- </div>
- <Button v-if="hasMore"
- type="tertiary"
- class="shared-items__more"
- :wide="true"
- @click="handleCaptionClick">
- <template #icon>
- <DotsHorizontal :size="20"
- decorative
- title="" />
- </template>
- {{ buttonTitle }}
- </Button>
+ <div class="shared-items" :class="{'shared-items__list' : isList}">
+ <template v-for="file in itemsToDisplay">
+ <FilePreview :key="file.id"
+ :small-preview="isList"
+ :row-layout="isList"
+ :is-shared-items-tab="true"
+ v-bind="file.messageParameters.file" />
+ </template>
</div>
</template>
<script>
-import Button from '@nextcloud/vue/dist/Components/Button'
import FilePreview from '../../MessagesList/MessagesGroup/Message/MessagePart/FilePreview.vue'
-import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
-import AppNavigationCaption from '@nextcloud/vue/dist/Components/AppNavigationCaption'
-import { showMessage } from '@nextcloud/dialogs'
import { SHARED_ITEM } from '../../../constants'
export default {
name: 'SharedItems',
components: {
- Button,
FilePreview,
- DotsHorizontal,
- AppNavigationCaption,
},
props: {
@@ -74,51 +52,17 @@ export default {
type: Object,
required: true,
},
+
+ // Limits the amount of items displayed
+ limit: {
+ type: Boolean,
+ default: false,
+ },
},
computed: {
itemsToDisplay() {
- return Object.values(this.items).reverse().slice(0, 6)
- },
-
- title() {
- switch (this.type) {
- case SHARED_ITEM.TYPES.MEDIA:
- return t('spreed', 'Media')
- case SHARED_ITEM.TYPES.FILE:
- return t('spreed', 'Files')
- case SHARED_ITEM.TYPES.DECK_CARD:
- return t('spreed', 'Deck cards')
- case SHARED_ITEM.TYPES.VOICE:
- return t('spreed', 'Voice messages')
- case SHARED_ITEM.TYPES.LOCATION:
- return t('spreed', 'Locations')
- case SHARED_ITEM.TYPES.AUDIO:
- return t('spreed', 'Audio')
- case SHARED_ITEM.TYPES.OTHER:
- default:
- return t('spreed', 'Other')
- }
- },
-
- buttonTitle() {
- switch (this.type) {
- case SHARED_ITEM.TYPES.MEDIA:
- return t('spreed', 'Show all media')
- case SHARED_ITEM.TYPES.FILE:
- return t('spreed', 'Show all files')
- case SHARED_ITEM.TYPES.DECK_CARD:
- return t('spreed', 'Show all deck cards')
- case SHARED_ITEM.TYPES.VOICE:
- return t('spreed', 'Show all voice messages')
- case SHARED_ITEM.TYPES.LOCATION:
- return t('spreed', 'Show all locations')
- case SHARED_ITEM.TYPES.AUDIO:
- return t('spreed', 'Show all audio')
- case SHARED_ITEM.TYPES.OTHER:
- default:
- return t('spreed', 'Show all other')
- }
+ return this.limit ? Object.values(this.items).reverse().slice(0, 6) : Object.values(this.items).reverse()
},
isList() {
@@ -131,26 +75,16 @@ export default {
return true
}
},
-
- hasMore() {
- return Object.values(this.items).length > 6
- },
- },
-
- methods: {
- handleCaptionClick() {
- showMessage('Screenshot feature only. Implementation of the real feature will come soon! 😎')
- console.debug('Show more')
- },
},
}
</script>
<style lang="scss" scoped>
-.files {
+.shared-items {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
+ margin-bottom: 16px;
grid-gap: 4px;
&__list {
display: flex;
@@ -158,11 +92,4 @@ export default {
}
}
-
-.shared-items {
- margin-bottom: 16px;
- &__more {
- margin-top: 8px;
- }
-}
</style>
diff --git a/src/components/RightSidebar/SharedItems/SharedItemsBrowser/SharedItemsBrowser.vue b/src/components/RightSidebar/SharedItems/SharedItemsBrowser/SharedItemsBrowser.vue
new file mode 100644
index 000000000..f32e4914b
--- /dev/null
+++ b/src/components/RightSidebar/SharedItems/SharedItemsBrowser/SharedItemsBrowser.vue
@@ -0,0 +1,173 @@
+<!--
+ - @copyright Copyright (c) 2022 Marco Ambrosini <marcoambrosini@pm.me>
+ -
+ - @author Marco Ambrosini <marcoambrosini@pm.me>
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<template>
+ <Modal size="large" :container="container" v-on="$listeners">
+ <div class="shared-items-browser">
+ <div class="shared-items-browser__navigation">
+ <template v-for="type in sharedItemsOrder">
+ <Button v-if="sharedItems[type]"
+ :key="type"
+ :class="{'active' : activeTab === type}"
+ type="tertiary"
+ @click="handleTabClick(type)">
+ {{ getTitle(type) }}
+ </Button>
+ </template>
+ </div>
+ <div ref="scroller" class="shared-items-browser__content" @scroll="debounceHandleScroll">
+ <SharedItems :type="activeTab"
+ :items="sharedItems[activeTab]" />
+ </div>
+ </div>
+ </Modal>
+</template>
+
+<script>
+import Modal from '@nextcloud/vue/dist/Components/Modal'
+import Button from '@nextcloud/vue/dist/Components/Button'
+import SharedItems from '../SharedItems.vue'
+import sharedItems from '../../../../mixins/sharedItems'
+import debounce from 'debounce'
+
+export default {
+ name: 'SharedItemsBrowser',
+
+ components: {
+ Modal,
+ Button,
+ SharedItems,
+ },
+
+ mixins: [sharedItems],
+
+ props: {
+ sharedItems: {
+ type: Object,
+ required: true,
+ },
+
+ activeTab: {
+ type: String,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ firstItemsLoaded: {},
+ isRequestingMoreItems: {},
+ hasFetchedAllItems: {},
+ }
+ },
+
+ computed: {
+ scroller() {
+ return this.$refs.scroller
+ },
+
+ token() {
+ return this.$store.getters.getToken()
+ },
+
+ container() {
+ return this.$store.getters.getMainContainerSelector()
+ },
+ },
+
+ watch: {
+ activeTab(newType) {
+ this.firstFetchItems(newType)
+ },
+ },
+
+ mounted() {
+ this.firstFetchItems(this.activeTab)
+ },
+
+ methods: {
+ handleTabClick(type) {
+ this.$emit('update:active-tab', type)
+ },
+
+ firstFetchItems(type) {
+ if (!this.firstItemsLoaded?.[type]) {
+ this.fetchItems(type)
+ this.firstItemsLoaded[type] = true
+ }
+ },
+
+ fetchItems(type) {
+ this.isRequestingMoreItems[this.activeTab] = true
+ const hasMoreItems = this.$store.dispatch('getSharedItems', {
+ token: this.token,
+ type,
+ })
+ if (hasMoreItems === false) {
+ this.hasFetchedAllItems[this.activeTab] = true
+ }
+ this.isRequestingMoreItems[this.activeTab] = false
+ },
+
+ debounceHandleScroll: debounce(function() {
+ this.handleScroll()
+ }, 50),
+
+ async handleScroll() {
+ const scrollHeight = this.scroller.scrollHeight
+ const scrollTop = this.scroller.scrollTop
+ const containerHeight = this.scroller.clientHeight
+ if ((scrollHeight - scrollTop - containerHeight < 300) && !this.isRequestingMoreItems?.[this.activeTab] && !this.hasFetchedAllItems?.[this.activeTab]) {
+ this.fetchItems(this.activeTab)
+ }
+ },
+ },
+}
+</script>
+
+<style lang="scss" scoped>
+.shared-items-browser {
+ width: 100%;
+ height: 100%;
+ position:relative;
+ display: flex;
+ flex-direction: column;
+ &__navigation {
+ display: flex;
+ gap: 8px;
+ padding: 16px;
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+ &__content {
+ overflow-y: auto;
+ overflow-x: hidden;
+ margin: 0 12px;
+ }
+}
+
+::v-deep .button-vue {
+ border-radius: var(--border-radius-large);
+ &.active {
+ background-color: var(--color-primary-element-hover);
+ }
+}
+</style>
diff --git a/src/components/RightSidebar/SharedItems/SharedItemsTab.vue b/src/components/RightSidebar/SharedItems/SharedItemsTab.vue
index d3ee8db57..6403ecc0f 100644
--- a/src/components/RightSidebar/SharedItems/SharedItemsTab.vue
+++ b/src/components/RightSidebar/SharedItems/SharedItemsTab.vue
@@ -22,16 +22,34 @@
<template>
<div v-if="!loading && active">
<template v-for="type in sharedItemsOrder">
- <SharedItems v-if="sharedItems[type]"
- :key="type"
- :type="type"
- :items="sharedItems[type]" />
+ <div v-if="sharedItems[type]" :key="type">
+ <AppNavigationCaption :title="getTitle(type)" />
+ <SharedItems :type="type"
+ :limit="true"
+ :items="sharedItems[type]" />
+ <Button v-if="hasMore(sharedItems[type])"
+ type="tertiary-no-background"
+ class="more"
+ :wide="true"
+ @click="showMore(type)">
+ <template #icon>
+ <DotsHorizontal :size="20"
+ decorative
+ title="" />
+ </template>
+ {{ getButtonTitle(type) }}
+ </Button>
+ </div>
</template>
<AppNavigationCaption :title="t('spreed', 'Projects')" />
<CollectionList v-if="getUserId && token"
:id="token"
type="room"
:name="conversation.displayName" />
+ <SharedItemsBrowser v-if="showSharedItemsBrowser"
+ :shared-items="sharedItems"
+ :active-tab.sync="browserActiveTab"
+ @close="showSharedItemsBrowser = false" />
</div>
</template>
@@ -40,6 +58,10 @@ import { CollectionList } from 'nextcloud-vue-collections'
import SharedItems from './SharedItems'
import { SHARED_ITEM } from '../../../constants'
import AppNavigationCaption from '@nextcloud/vue/dist/Components/AppNavigationCaption'
+import SharedItemsBrowser from './SharedItemsBrowser/SharedItemsBrowser.vue'
+import DotsHorizontal from 'vue-material-design-icons/DotsHorizontal.vue'
+import Button from '@nextcloud/vue/dist/Components/Button'
+import sharedItems from '../../../mixins/sharedItems'
export default {
@@ -49,8 +71,13 @@ export default {
SharedItems,
CollectionList,
AppNavigationCaption,
+ SharedItemsBrowser,
+ DotsHorizontal,
+ Button,
},
+ mixins: [sharedItems],
+
props: {
active: {
@@ -59,6 +86,13 @@ export default {
},
},
+ data() {
+ return {
+ showSharedItemsBrowser: false,
+ browserActiveTab: '',
+ }
+ },
+
computed: {
getUserId() {
return this.$store.getters.getUserId()
@@ -79,12 +113,6 @@ export default {
sharedItems() {
return this.$store.getters.sharedItems(this.token)
},
-
- // Defines the order of the sections
- sharedItemsOrder() {
- // FIXME restore when non files work return [SHARED_ITEM.TYPES.MEDIA, SHARED_ITEM.TYPES.FILE, SHARED_ITEM.TYPES.VOICE, SHARED_ITEM.TYPES.AUDIO, SHARED_ITEM.TYPES.LOCATION, SHARED_ITEM.TYPES.DECK_CARD, SHARED_ITEM.TYPES.OTHER]
- return [SHARED_ITEM.TYPES.MEDIA, SHARED_ITEM.TYPES.FILE, SHARED_ITEM.TYPES.VOICE, SHARED_ITEM.TYPES.AUDIO]
- },
},
watch: {
@@ -99,6 +127,43 @@ export default {
getSharedItemsOverview() {
this.$store.dispatch('getSharedItemsOverview', { token: this.token })
},
+
+ hasMore(items) {
+ return Object.values(items).length > 6
+ },
+
+ showMore(type) {
+ this.browserActiveTab = type
+ this.showSharedItemsBrowser = true
+ },
+
+ getButtonTitle(type) {
+ switch (type) {
+ case SHARED_ITEM.TYPES.MEDIA:
+ return t('spreed', 'Show all media')
+ case SHARED_ITEM.TYPES.FILE:
+ return t('spreed', 'Show all files')
+ case SHARED_ITEM.TYPES.DECK_CARD:
+ return t('spreed', 'Show all deck cards')
+ case SHARED_ITEM.TYPES.VOICE:
+ return t('spreed', 'Show all voice messages')
+ case SHARED_ITEM.TYPES.LOCATION:
+ return t('spreed', 'Show all locations')
+ case SHARED_ITEM.TYPES.AUDIO:
+ return t('spreed', 'Show all audio')
+ case SHARED_ITEM.TYPES.OTHER:
+ default:
+ return t('spreed', 'Show all other')
+ }
+ },
},
}
</script>
+
+<style lang="scss" scoped>
+
+.more {
+ margin-top: 8px;
+}
+
+</style>
diff --git a/src/mixins/sharedItems.js b/src/mixins/sharedItems.js
new file mode 100644
index 000000000..5569733ae
--- /dev/null
+++ b/src/mixins/sharedItems.js
@@ -0,0 +1,57 @@
+/**
+ * @copyright Copyright (c) 2022 Marco Ambrosini <marcoambrosini@pm.me>
+ *
+ * @author Marco Ambrosini <marcoambrosini@pm.me>
+ *
+ * @license AGPL-3.0-or-later
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import { SHARED_ITEM } from '../constants'
+
+const sharedItems = {
+ computed: {
+ // Defines the order of the sections
+ sharedItemsOrder() {
+ // FIXME restore when non files work return [SHARED_ITEM.TYPES.MEDIA, SHARED_ITEM.TYPES.FILE, SHARED_ITEM.TYPES.VOICE, SHARED_ITEM.TYPES.AUDIO, SHARED_ITEM.TYPES.LOCATION, SHARED_ITEM.TYPES.DECK_CARD, SHARED_ITEM.TYPES.OTHER]
+ return [SHARED_ITEM.TYPES.MEDIA, SHARED_ITEM.TYPES.FILE, SHARED_ITEM.TYPES.VOICE, SHARED_ITEM.TYPES.AUDIO]
+ },
+ },
+
+ methods: {
+ getTitle(type) {
+ switch (type) {
+ case SHARED_ITEM.TYPES.MEDIA:
+ return t('spreed', 'Media')
+ case SHARED_ITEM.TYPES.FILE:
+ return t('spreed', 'Files')
+ case SHARED_ITEM.TYPES.DECK_CARD:
+ return t('spreed', 'Deck cards')
+ case SHARED_ITEM.TYPES.VOICE:
+ return t('spreed', 'Voice messages')
+ case SHARED_ITEM.TYPES.LOCATION:
+ return t('spreed', 'Locations')
+ case SHARED_ITEM.TYPES.AUDIO:
+ return t('spreed', 'Audio')
+ case SHARED_ITEM.TYPES.OTHER:
+ default:
+ return t('spreed', 'Other')
+ }
+ },
+ },
+}
+
+export default sharedItems
diff --git a/src/services/conversationSharedItemsService.js b/src/services/sharedItemsService.js
index a0537ecf9..a0537ecf9 100644
--- a/src/services/conversationSharedItemsService.js
+++ b/src/services/sharedItemsService.js
diff --git a/src/store/conversationSharedItemsStore.js b/src/store/sharedItemsStore.js
index 9242dd0c8..b5ce88754 100644
--- a/src/store/conversationSharedItemsStore.js
+++ b/src/store/sharedItemsStore.js
@@ -21,7 +21,7 @@
*/
import Vue from 'vue'
-import { getSharedItemsOverview, getSharedItems } from '../services/conversationSharedItemsService'
+import { getSharedItemsOverview, getSharedItems } from '../services/sharedItemsService'
import { SHARED_ITEM } from '../constants'
const getItemTypeFromMessage = function(message) {
@@ -120,19 +120,19 @@ const actions = {
return false
}
- const limit = 100
+ const limit = 20
const lastKnownMessageId = Math.min.apply(Math, Object.keys(state.sharedItemsByConversationAndType[token][type]))
try {
const response = await getSharedItems(token, type, lastKnownMessageId, limit)
const messages = response.data.ocs.data
const hasMore = messages.length >= limit
-
// loop over the response elements and add them to the store
for (const message in messages) {
+
commit('addSharedItemMessage', {
token,
type,
- message,
+ message: messages[message],
})
}
return hasMore
diff --git a/src/store/storeConfig.js b/src/store/storeConfig.js
index 9f5fbe9c1..121f3cdcf 100644
--- a/src/store/storeConfig.js
+++ b/src/store/storeConfig.js
@@ -39,7 +39,7 @@ import uiModeStore from './uiModeStore'
import windowVisibilityStore from './windowVisibilityStore'
import messageActionsStore from './messageActionsStore'
import reactionsStore from './reactionsStore'
-import conversationSharedItemStore from './conversationSharedItemsStore'
+import sharedItemStore from './sharedItemsStore'
export default {
modules: {
@@ -62,7 +62,7 @@ export default {
windowVisibilityStore,
messageActionsStore,
reactionsStore,
- conversationSharedItemStore,
+ sharedItemStore,
},
mutations: {},