diff options
author | Joas Schilling <213943+nickvergessen@users.noreply.github.com> | 2020-08-25 13:46:07 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-25 13:46:07 +0300 |
commit | ffd47f06341c05904a6fca527e5ee31a3a3959ed (patch) | |
tree | 8b9a16028919608c02c4e3dc425342c473e89f16 | |
parent | 70d1937038722160e2a88f361707c149584f0fa5 (diff) | |
parent | 56fa3c8454f8c1fc79b69fd777651b57b5df63c9 (diff) |
Merge pull request #4058 from nextcloud/feature/noid/add-anchorIds-to-conversations
Conversations list auto scrolling
4 files changed, 74 insertions, 5 deletions
diff --git a/src/components/LeftSidebar/ConversationsList/Conversation.vue b/src/components/LeftSidebar/ConversationsList/Conversation.vue index 144d83215..e34360c71 100644 --- a/src/components/LeftSidebar/ConversationsList/Conversation.vue +++ b/src/components/LeftSidebar/ConversationsList/Conversation.vue @@ -147,33 +147,43 @@ export default { counterShouldBePrimary() { return this.item.unreadMention || (this.item.unreadMessages && this.item.type === CONVERSATION.TYPE.ONE_TO_ONE) }, + linkToConversation() { return window.location.protocol + '//' + window.location.host + generateUrl('/call/' + this.item.token) }, + canFavorite() { return this.item.participantType !== PARTICIPANT.TYPE.USER_SELF_JOINED }, + iconFavorite() { return this.item.isFavorite ? 'icon-star-dark' : 'icon-starred' }, + labelFavorite() { return this.item.isFavorite ? t('spreed', 'Remove from favorites') : t('spreed', 'Add to favorites') }, + isNotifyAlways() { return this.item.notificationLevel === PARTICIPANT.NOTIFY.ALWAYS }, + isNotifyMention() { return this.item.notificationLevel === PARTICIPANT.NOTIFY.MENTION }, + isNotifyNever() { return this.item.notificationLevel === PARTICIPANT.NOTIFY.NEVER }, + canDeleteConversation() { return this.item.canDeleteConversation }, + canLeaveConversation() { return this.item.canLeaveConversation }, + iconLeaveConversation() { if (this.canDeleteConversation) { return 'icon-close' @@ -258,6 +268,7 @@ export default { return subtitle }, + /** * @returns {string} Part of the name until the first space */ @@ -289,6 +300,7 @@ export default { showError(t('spreed', 'The link could not be copied.')) } }, + /** * Deletes the conversation. */ @@ -316,6 +328,7 @@ export default { }.bind(this) ) }, + /** * Deletes the current user from the conversation. */ @@ -335,6 +348,7 @@ export default { async toggleFavoriteConversation() { this.$store.dispatch('toggleFavorite', this.item) }, + /** * Set the notification level for the conversation * @param {int} level The notification level to set. diff --git a/src/components/LeftSidebar/ConversationsList/ConversationsList.vue b/src/components/LeftSidebar/ConversationsList/ConversationsList.vue index d7c0b6eea..bbfee0cf5 100644 --- a/src/components/LeftSidebar/ConversationsList/ConversationsList.vue +++ b/src/components/LeftSidebar/ConversationsList/ConversationsList.vue @@ -25,7 +25,7 @@ v-for="item of conversationsList" :key="item.id" :item="item" - @click.native="handleConversationClick" /> + @click.native="handleConversationClick(item)" /> <template v-if="!initialisedConversations"> <LoadingPlaceholder @@ -78,9 +78,11 @@ export default { return conversations.sort(this.sortConversations) }, }, + beforeMount() { this.fetchConversations() }, + mounted() { /** Refreshes the conversations every 30 seconds */ window.setInterval(() => { @@ -92,10 +94,12 @@ export default { EventBus.$on('routeChange', this.onRouteChange) EventBus.$on('shouldRefreshConversations', this.debounceFetchConversations) }, + beforeDestroy() { EventBus.$off('routeChange', this.onRouteChange) EventBus.$off('shouldRefreshConversations', this.debounceFetchConversations) }, + methods: { onRouteChange({ from, to }) { if (from.name === 'conversation') { @@ -106,6 +110,7 @@ export default { this.$store.dispatch('markConversationRead', to.params.token) } }, + sortConversations(conversation1, conversation2) { if (conversation1.isFavorite !== conversation2.isFavorite) { return conversation1.isFavorite ? -1 : 1 @@ -150,9 +155,10 @@ export default { this.isFetchingConversations = false } }, + // Emit the click event so the search text in the leftsidebar can be reset. - handleConversationClick() { - this.$emit('click-conversation') + handleConversationClick(item) { + this.$emit('click-search-result', item.token) }, }, } diff --git a/src/components/LeftSidebar/LeftSidebar.vue b/src/components/LeftSidebar/LeftSidebar.vue index 516218ada..1eab560c0 100644 --- a/src/components/LeftSidebar/LeftSidebar.vue +++ b/src/components/LeftSidebar/LeftSidebar.vue @@ -36,7 +36,8 @@ :title="t('spreed', 'Conversations')" /> <li> <ConversationsList - :search-text="searchText" /> + :search-text="searchText" + @click-search-result="handleClickSearchResult" /> </li> <template v-if="isSearching"> <template v-if="searchResultsUsers.length !== 0"> @@ -143,9 +144,11 @@ export default { conversationsList() { return this.$store.getters.conversationsList }, + isSearching() { return this.searchText !== '' }, + showStartConversationsOptions() { return this.isSearching && this.canStartConversations }, @@ -248,6 +251,19 @@ export default { showSettings() { EventBus.$emit('show-settings', true) }, + + handleClickSearchResult(selectedConversationToken) { + // End the search operation + this.abortSearch() + const selectedConversation = document.getElementById(`conversation_${selectedConversationToken}`) + this.$nextTick(() => { + selectedConversation.scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'nearest', + }) + }) + }, }, } </script> diff --git a/src/components/NewMessageForm/NewMessageForm.vue b/src/components/NewMessageForm/NewMessageForm.vue index 2b948888e..693f5d9e8 100644 --- a/src/components/NewMessageForm/NewMessageForm.vue +++ b/src/components/NewMessageForm/NewMessageForm.vue @@ -126,6 +126,7 @@ export default { return { text: '', parsedText: '', + conversationIsFirstInList: false, } }, computed: { @@ -137,17 +138,21 @@ export default { token() { return this.$store.getters.getToken() }, + conversation() { return this.$store.getters.conversation(this.token) || { readOnly: CONVERSATION.STATE.READ_WRITE, } }, + messageToBeReplied() { return this.$store.getters.getMessageToBeReplied(this.token) }, + currentUserIsGuest() { return this.$store.getters.getUserId() === null }, + canShareAndUploadFiles() { return !this.currentUserIsGuest && this.conversation.readOnly === CONVERSATION.STATE.READ_WRITE }, @@ -156,6 +161,17 @@ export default { return this.$store.getters.getAttachmentFolder() }, }, + + watch: { + token(newValue, oldValue) { + this.isCurrentConversationIsFirstInList() + }, + }, + + mounted() { + this.isCurrentConversationIsFirstInList() + }, + methods: { contentEditableToParsed(contentEditable) { const mentions = contentEditable.querySelectorAll('span[data-at-embedded]') @@ -206,6 +222,7 @@ export default { * Sends the new message */ async handleSubmit() { + if (this.parsedText !== '') { const temporaryMessage = createTemporaryMessage(this.parsedText, this.token) this.$store.dispatch('addTemporaryMessage', temporaryMessage) @@ -225,10 +242,20 @@ export default { // And adds the complete version of the message received // by the server this.$store.dispatch('processMessage', response.data.ocs.data) + // Scrolls the conversationlist to conversation + if (!this.conversationIsFirstInList) { + const conversation = document.getElementById(`conversation_${this.token}`) + this.$nextTick(() => { + conversation.scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'nearest', + }) + }) + } } catch (error) { console.debug(`error while submitting message ${error}`) } - } }, @@ -317,6 +344,11 @@ export default { range.setStartAfter(emojiTextNode) }, + // Check whether the current conversation is the first in the conversations + // list and stores the value in the component's data. + isCurrentConversationIsFirstInList() { + this.conversationIsFirstInList = this.$store.getters.conversationsList.map(conversation => conversation.token).indexOf(this.token) === 0 + }, }, } </script> @@ -366,4 +398,5 @@ export default { } } + </style> |