Skip to content

Commit

Permalink
feat: add archiving function
Browse files Browse the repository at this point in the history
[wip]

[skip ci]
  • Loading branch information
Antreesy committed Sep 20, 2024
1 parent 74ee60e commit 5538bee
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 20 deletions.
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* 🌉 **Sync with other chat solutions** With [Matterbridge](https://github.com/42wim/matterbridge/) being integrated in Talk, you can easily sync a lot of other chat solutions to Nextcloud Talk and vice-versa.
]]></description>

<version>21.0.0-dev.0</version>
<version>21.0.0-dev.1</version>
<licence>agpl</licence>

<author>Daniel Calviño Sánchez</author>
Expand Down
2 changes: 2 additions & 0 deletions src/__mocks__/capabilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export const mockedCapabilities: Capabilities = {
'chat-reference-id',
'mention-permissions',
'edit-messages-note-to-self',
'archive-conversations',
],
'features-local': [
'favorites',
Expand All @@ -95,6 +96,7 @@ export const mockedCapabilities: Capabilities = {
'avatar',
'remind-me-later',
'note-to-self',
'archive-conversations',
],
config: {
attachments: {
Expand Down
28 changes: 27 additions & 1 deletion src/components/LeftSidebar/ConversationsList/Conversation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@
{{ labelFavorite }}
</NcActionButton>

<NcActionButton v-if="supportsArchive"
key="toggle-archive"
close-after-click
@click="toggleArchiveConversation">
<template #icon>
<IconArchive v-if="!item.isArchived" :size="16" />
<IconArchiveOff v-else :size="16" />
</template>
{{ labelArchive }}
</NcActionButton>

<NcActionButton key="copy-link" @click.stop="handleCopyLink">
<template #icon>
<IconContentCopy :size="16" />
Expand Down Expand Up @@ -118,6 +129,8 @@
import { toRefs } from 'vue'
import { isNavigationFailure, NavigationFailureType } from 'vue-router'
import IconArchive from 'vue-material-design-icons/Archive.vue'
import IconArchiveOff from 'vue-material-design-icons/ArchiveOff.vue'
import IconArrowRight from 'vue-material-design-icons/ArrowRight.vue'
import IconCog from 'vue-material-design-icons/Cog.vue'
import IconContentCopy from 'vue-material-design-icons/ContentCopy.vue'
Expand All @@ -140,8 +153,11 @@ import ConversationIcon from './../../ConversationIcon.vue'
import { useConversationInfo } from '../../../composables/useConversationInfo.js'
import { PARTICIPANT } from '../../../constants.js'
import { hasTalkFeature } from '../../../services/CapabilitiesManager.ts'
import { copyConversationLinkToClipboard } from '../../../utils/handleUrl.ts'
const supportsArchive = hasTalkFeature('local', 'archive-conversations')
export default {
name: 'Conversation',
Expand All @@ -151,6 +167,8 @@ export default {
NcActionButton,
NcDialog,
NcListItem,
IconArchive,
IconArchiveOff,
IconArrowRight,
IconCog,
IconContentCopy,
Expand All @@ -159,7 +177,6 @@ export default {
IconEyeOff,
IconEye,
IconStar,
},
props: {
Expand Down Expand Up @@ -196,6 +213,7 @@ export default {
const { counterType, conversationInformation } = useConversationInfo({ item, isSearchResult })
return {
supportsArchive,
counterType,
conversationInformation,
}
Expand All @@ -220,6 +238,10 @@ export default {
return this.item.isFavorite ? t('spreed', 'Remove from favorites') : t('spreed', 'Add to favorites')
},
labelArchive() {
return this.item.isArchived ? t('spreed', 'Restore from archive') : t('spreed', 'Archive')
},
dialogMessage() {
return t('spreed', 'Do you really want to delete "{displayName}"?', this.item, undefined, {
escape: false,
Expand Down Expand Up @@ -298,6 +320,10 @@ export default {
this.$store.dispatch('toggleFavorite', this.item)
},
async toggleArchiveConversation() {
this.$store.dispatch('toggleArchive', this.item)
},
/**
* Set the notification level for the conversation
*
Expand Down
55 changes: 39 additions & 16 deletions src/components/LeftSidebar/LeftSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@
{{ t('spreed', 'Filter unread messages') }}
</NcActionButton>

<NcActionButton close-after-click
:model-value="isFiltered === 'archived'"
@click="handleFilter('archived')">
<template #icon>
<IconArchive :size="20" />
</template>
{{ t('spreed', 'Filter archived conversations') }}
</NcActionButton>

<NcActionButton v-if="isFiltered"
close-after-click
class="filter-actions__clearbutton"
Expand Down Expand Up @@ -135,6 +144,7 @@
:description="emptyContentDescription">
<template #icon>
<AtIcon v-if="isFiltered === 'mentions'" :size="64" />
<IconArchive v-else-if="isFiltered === 'archived'" :size="64" />
<MessageBadge v-else-if="isFiltered === 'unread'" :size="64" />
<MessageOutline v-else :size="64" />
</template>
Expand Down Expand Up @@ -277,6 +287,17 @@

<template #footer>
<div class="left-sidebar__settings-button-container">
<NcAppNavigationItem v-if="true"
class="invitation-button"
:name="t('spreed', 'Archived conversations')"
@click="handleFilter('archived')">
<template #icon>
<IconArchive :size="20" />
</template>
<template #counter>
<NcCounterBubble :count="3" />
</template>
</NcAppNavigationItem>
<NcButton type="tertiary" wide @click="showSettings">
<template #icon>
<Cog :size="20" />
Expand All @@ -293,6 +314,8 @@ import debounce from 'debounce'
import { ref } from 'vue'
import AccountMultiplePlus from 'vue-material-design-icons/AccountMultiplePlus.vue'
import IconArchive from 'vue-material-design-icons/Archive.vue'
import IconArchiveOff from 'vue-material-design-icons/ArchiveOff.vue'
import AtIcon from 'vue-material-design-icons/At.vue'
import ChatPlus from 'vue-material-design-icons/ChatPlus.vue'
import Cog from 'vue-material-design-icons/Cog.vue'
Expand Down Expand Up @@ -362,6 +385,7 @@ export default {
name: 'LeftSidebar',
components: {
IconArchiveOff,
AvatarWrapper,
CallPhoneDialog,
InvitationHandler,
Expand All @@ -388,6 +412,7 @@ export default {
MessageOutline,
FilterIcon,
FilterRemoveIcon,
IconArchive,
Phone,
Plus,
ChatPlus,
Expand Down Expand Up @@ -496,6 +521,8 @@ export default {
return t('spreed', 'You have no unread mentions.')
case 'unread':
return t('spreed', 'You have no unread messages.')
case 'archived':
return t('spreed', 'You have no archived conversations.')
default:
return ''
}
Expand All @@ -505,23 +532,19 @@ export default {
if (this.isFocused) {
return this.conversationsList
}
// applying filters
if (this.isFiltered) {
let validConversationsCount = 0
const filteredConversations = this.conversationsList.filter((conversation) => {
const conversationIsValid = filterFunction(this.isFiltered, conversation)
if (conversationIsValid) {
validConversationsCount++
}
return conversationIsValid
|| conversation.hasCall
|| conversation.token === this.token
})
// return empty if it only includes the current conversation without any flags
return validConversationsCount === 0 && !this.isNavigating ? [] : filteredConversations
}
return this.conversationsList
let validConversationsCount = 0
const filteredConversations = this.conversationsList.filter((conversation) => {
const conversationIsValid = filterFunction(this.isFiltered, conversation)
if (conversationIsValid) {
validConversationsCount++
}
return conversationIsValid
|| conversation.hasCall
|| conversation.token === this.token
})
// return empty if it only includes the current conversation without any flags
return validConversationsCount === 0 && !this.isNavigating ? [] : filteredConversations
},
isSearching() {
Expand Down
20 changes: 20 additions & 0 deletions src/services/conversationsService.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,24 @@ const removeFromFavorites = async function(token) {
return axios.delete(generateOcsUrl('apps/spreed/api/v4/room/{token}/favorite', { token }))
}

/**
* Add a conversation to the archive
*
* @param {string} token The token of the conversation to be favorites
*/
const archiveConversation = async function(token) {
return axios.post(generateOcsUrl('apps/spreed/api/v4/room/{token}/archive', { token }))
}

/**
* Restore a conversation from the archive
*
* @param {string} token The token of the conversation to be removed from favorites
*/
const unarchiveConversation = async function(token) {
return axios.delete(generateOcsUrl('apps/spreed/api/v4/room/{token}/archive', { token }))
}

/**
* Set notification level
*
Expand Down Expand Up @@ -380,6 +398,8 @@ export {
deleteConversation,
addToFavorites,
removeFromFavorites,
archiveConversation,
unarchiveConversation,
setNotificationLevel,
setNotificationCalls,
makeConversationPublic,
Expand Down
25 changes: 24 additions & 1 deletion src/store/conversationsStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
createOneToOneConversation,
addToFavorites,
removeFromFavorites,
archiveConversation,
unarchiveConversation,
fetchConversations,
fetchConversation,
setConversationName,
Expand Down Expand Up @@ -67,6 +69,7 @@ const DUMMY_CONVERSATION = {
token: '',
displayName: '',
isFavorite: false,
isArchived: false,
hasPassword: false,
breakoutRoomMode: CONVERSATION.BREAKOUT_ROOM_MODE.NOT_CONFIGURED,
breakoutRoomStatus: CONVERSATION.BREAKOUT_ROOM_STATUS.STOPPED,
Expand Down Expand Up @@ -525,6 +528,26 @@ const actions = {
}
},

async toggleArchive({ commit, getters }, { token, isArchived }) {
if (!getters.conversations[token]) {
return
}

try {
if (isArchived) {
await unarchiveConversation(token)
} else {
await archiveConversation(token)
}

const conversation = Object.assign({}, getters.conversations[token], { isArchived: !isArchived })

commit('addConversation', conversation)
} catch (error) {
console.error('Error while changing the conversation archived status: ', error)
}
},

async toggleLobby({ commit, getters }, { token, enableLobby }) {
if (!getters.conversations[token]) {
return
Expand Down Expand Up @@ -904,7 +927,7 @@ const actions = {
async setNotificationLevel({ commit }, { token, notificationLevel }) {
try {
await setNotificationLevel(token, notificationLevel)
commit('setNotificationLevel', { token, notificationLevel })
commit('setNotificationLevel', { token, notificationLevel: +notificationLevel })
} catch (error) {
console.error('Error while setting the notification level: ', error)
}
Expand Down
30 changes: 29 additions & 1 deletion src/utils/conversation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
* SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import { CONVERSATION } from '../constants.js'
import { t } from '@nextcloud/l10n'

import { CONVERSATION, PARTICIPANT } from '../constants.js'

/**
* check if the conversation has unread messages
Expand All @@ -27,6 +29,28 @@ export function hasUnreadMentions(conversation) {
&& (conversation.type === CONVERSATION.TYPE.ONE_TO_ONE || conversation.type === CONVERSATION.TYPE.ONE_TO_ONE_FORMER))
}

/**
* check if the conversation has unread mentions
*
* @param {object} conversation conversation object
* @return {boolean}
*/
export function isArchived(conversation) {
return conversation.isArchived
}

/**
* check if the conversation has unread mentions
*
* @param {object} conversation conversation object
* @return {boolean}
*/
export function isDefault(conversation) {
return !conversation.isArchived
|| (conversation.notificationLevel === PARTICIPANT.NOTIFY.ALWAYS && hasUnreadMessages(conversation))
|| (conversation.notificationLevel === PARTICIPANT.NOTIFY.MENTION && hasUnreadMentions(conversation))
}

/**
* apply the active filter
*
Expand All @@ -38,5 +62,9 @@ export function filterFunction(filter, conversation) {
return hasUnreadMessages(conversation)
} else if (filter === 'mentions') {
return hasUnreadMentions(conversation)
} else if (filter === 'archived') {
return isArchived(conversation)
} else {
return isDefault(conversation)
}
}

0 comments on commit 5538bee

Please sign in to comment.