Merge pull request #4935 from nextcloud/feature/noid/move-more-settings-to-conversation-settings

Copy actions in conversation menu into the new conversation settings dialog
This commit is contained in:
Joas Schilling 2021-02-25 09:22:09 +01:00 коммит произвёл GitHub
Родитель f64d87549c 65f273cfa3
Коммит da2588e47f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 363 добавлений и 2 удалений

Просмотреть файл

@ -24,12 +24,24 @@
role="dialog"
:aria-label="t('spreed', 'Conversation settings')"
:open.sync="showSettings"
:show-navigation="false">
:show-navigation="true">
<!-- Notifications settings -->
<AppSettingsSection
:title="t('spreed', 'Chat notifications')"
class="app-settings-section">
<NotificationsSettings :conversation="conversation" />
</AppSettingsSection>
<!-- Guest access -->
<AppSettingsSection
v-if="canFullModerate"
:title="t('spreed', 'Guests access')"
class="app-settings-section">
<LinkShareSettings ref="linkShareSettings" />
</AppSettingsSection>
<!-- TODO sepatate these 2 settings and rename the settings sections
all the settings in this component are conversation settings. Proposal:
move lock conversation in destructive actions and create a separate
section for listablesettings -->
<AppSettingsSection
v-if="canFullModerate"
:title="t('spreed', 'Conversation settings')"
@ -37,6 +49,7 @@
<ListableSettings :token="token" />
<LockingSettings :token="token" />
</AppSettingsSection>
<!-- Meeting settings -->
<AppSettingsSection
v-if="canFullModerate"
:title="t('spreed', 'Meeting settings')"
@ -50,6 +63,16 @@
class="app-settings-section">
<MatterbridgeSettings />
</AppSettingsSection>
<!-- Destructive actions -->
<AppSettingsSection
v-if="canLeaveConversation || canDeleteConversation"
:title="t('spreed', 'Danger zone')"
class="app-settings-section">
<DangerZone
:conversation="conversation"
:can-leave-conversation="canLeaveConversation"
:can-delete-conversation="canDeleteConversation" />
</AppSettingsSection>
</AppSettingsDialog>
</template>
@ -65,6 +88,8 @@ import LobbySettings from './LobbySettings'
import SipSettings from './SipSettings'
import MatterbridgeSettings from './Matterbridge/MatterbridgeSettings'
import { loadState } from '@nextcloud/initial-state'
import DangerZone from './DangerZone'
import NotificationsSettings from './NotificationsSettings'
export default {
name: 'ConversationSettingsDialog',
@ -78,6 +103,8 @@ export default {
LockingSettings,
SipSettings,
MatterbridgeSettings,
DangerZone,
NotificationsSettings,
},
data() {
@ -95,19 +122,31 @@ export default {
token() {
return this.$store.getters.getToken()
},
conversation() {
return this.$store.getters.conversation(this.token) || this.$store.getters.dummyConversation
},
participantType() {
return this.conversation.participantType
},
canFullModerate() {
return this.participantType === PARTICIPANT.TYPE.OWNER || this.participantType === PARTICIPANT.TYPE.MODERATOR
},
canDeleteConversation() {
return this.conversation.canDeleteConversation
},
canLeaveConversation() {
return this.conversation.canLeaveConversation
},
},
mounted() {
subscribe('show-conversation-settings', this.handleShowSettings)
subscribe('hide-conversation-settings', this.handleHideSettings)
},
methods: {
@ -118,8 +157,13 @@ export default {
})
},
handleHideSettings() {
this.showSettings = false
},
beforeDestroy() {
unsubscribe('show-conversation-settings', this.handleShowSettings)
unsubscribe('hide-conversation-settings', this.handleHideSettings)
},
},
}

Просмотреть файл

@ -0,0 +1,134 @@
<!--
- @copyright Copyright (c) 2021 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>
<div>
<div class="app-settings-section__hint">
{{ t('spreed', 'Be careful, these actions cannot be undone.') }}
</div>
<button v-if="canLeaveConversation"
@click.prevent.exact="leaveConversation">
{{ t('spreed', 'Leave conversation') }}
</button>
<button v-if="canDeleteConversation"
class="critical error"
@click.prevent.exact="deleteConversation">
{{ t('spreed', 'Delete conversation') }}
</button>
</div>
</template>
<script>
import { removeCurrentUserFromConversation } from '../../services/participantsService'
import { showError } from '@nextcloud/dialogs'
import { deleteConversation } from '../../services/conversationsService'
import { emit } from '@nextcloud/event-bus'
export default {
name: 'DangerZone',
props: {
conversation: {
type: Object,
required: true,
},
canLeaveConversation: {
type: Boolean,
required: true,
},
canDeleteConversation: {
type: Boolean,
required: true,
},
},
computed: {
token() {
return this.conversation.token
},
},
methods: {
hideConversationSettings() {
emit('hide-conversation-settings')
},
/**
* Deletes the current user from the conversation.
*/
async leaveConversation() {
try {
await removeCurrentUserFromConversation(this.token)
// If successful, deletes the conversation from the store
this.$store.dispatch('deleteConversation', this.conversation)
this.hideConversationSettings()
} catch (error) {
if (error.response && error.response.status === 400) {
showError(t('spreed', 'You need to promote a new moderator before you can leave the conversation.'))
} else {
console.error(`error while removing yourself from conversation ${error}`)
}
}
},
/**
* Deletes the conversation.
*/
async deleteConversation() {
OC.dialogs.confirm(
t('spreed', 'Do you really want to delete "{displayName}"?', this.conversation),
t('spreed', 'Delete conversation'),
async function(decision) {
if (!decision) {
return
}
if (this.token === this.$store.getters.getToken()) {
this.$router.push({ name: 'root' })
this.$store.dispatch('updateToken', '')
}
try {
await deleteConversation(this.token)
// If successful, deletes the conversation from the store
this.$store.dispatch('deleteConversation', this.conversation)
// Close the settings
this.hideConversationSettings()
} catch (error) {
console.debug(`error while deleting conversation ${error}`)
showError(t('spreed', 'Error while deleting conversation'))
}
}.bind(this)
)
},
},
}
</script>
<style lang="scss" scoped>
button {
height: 44px;
border: none;
}
</style>

Просмотреть файл

@ -0,0 +1,175 @@
<!--
- @copyright Copyright (c) 2020 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>
<div>
<div class="app-settings-section__hint">
{{ t('spreed', 'Set the notification level for the current conversation. This will affect only the notifications you receive.') }}
</div>
<a
href="#"
class="radio-element"
:class="{'radio-element--active': isNotifyAlways}"
@click.prevent.exact="setNotificationLevel(1)">
<VolumeHigh
decorative
title=""
:size="24"
class="radio-element__icon" />
<label
class="radio-element__label">
{{ t('spreed', 'All messages') }}
</label>
<Check
v-if="isNotifyAlways"
class="check"
decorative
title=""
:size="20" />
</a>
<a
href="#"
class="radio-element"
:class="{'radio-element--active': isNotifyMention}"
@click.prevent.exact="setNotificationLevel(2)">
<Account
decorative
title=""
:size="24"
class="radio-element__icon" />
<label
class="radio-element__label">
{{ t('spreed', '@-mentions only') }}
</label>
<Check
v-if="isNotifyMention"
class="check"
decorative
title=""
:size="20" />
</a>
<a href="#"
class="radio-element"
:class="{'radio-element--active': isNotifyNever}"
@click.prevent.exact="setNotificationLevel(3)">
<VolumeOff
decorative
title=""
:size="24"
class="radio-element__icon" />
<label class="radio-element__label">
{{ t('spreed', 'Off') }}
</label>
<Check
v-if="isNotifyNever"
class="check"
decorative
title=""
:size="20" />
</a>
</div>
</template>
<script>
import { PARTICIPANT } from '../../constants'
import { setNotificationLevel } from '../../services/conversationsService'
import VolumeHigh from 'vue-material-design-icons/VolumeHigh'
import Account from 'vue-material-design-icons/Account'
import VolumeOff from 'vue-material-design-icons/VolumeOff'
import Check from 'vue-material-design-icons/Check'
export default {
name: 'NotificationsSettings',
components: {
VolumeHigh,
Account,
VolumeOff,
Check,
},
props: {
conversation: {
type: Object,
required: true,
},
},
computed: {
token() {
return this.conversation.token
},
isNotifyAlways() {
return this.conversation.notificationLevel === PARTICIPANT.NOTIFY.ALWAYS
},
isNotifyMention() {
return this.conversation.notificationLevel === PARTICIPANT.NOTIFY.MENTION
},
isNotifyNever() {
return this.conversation.notificationLevel === PARTICIPANT.NOTIFY.NEVER
},
},
methods: {
/**
* Set the notification level for the conversation
* @param {int} notificationLevel The notification level to set.
*/
async setNotificationLevel(notificationLevel) {
const token = this.token
await setNotificationLevel(token, notificationLevel)
this.$store.dispatch('changeNotificationLevel', { token, notificationLevel })
},
},
}
</script>
<style lang="scss" scoped>
.radio-element {
display: flex;
align-items: center;
height: 44px;
padding: 0 12px;
margin: 4px 0;
border-radius: var(--border-radius-pill);
&:hover,
&:focus {
background-color: var(--color-background-hover);
}
&--active{
background-color: var(--color-primary-light) !important;
}
&__icon {
display: flex;
}
&__label {
margin-left: 12px;
}
}
.check {
display: flex;
margin: 0 8px 0 auto;
}
</style>

Просмотреть файл

@ -336,6 +336,7 @@ export default {
this.$store.dispatch('deleteConversation', this.item.token)
} catch (error) {
console.debug(`error while deleting conversation ${error}`)
showError(t('spreed', 'Error while deleting conversation'))
}
}.bind(this)
)

Просмотреть файл

@ -85,7 +85,6 @@
<ActionSeparator
v-if="showModerationOptions" />
<ActionButton
v-if="showModerationOptions"
icon="icon-settings"
:close-after-click="true"
@click="showConversationSettings">

Просмотреть файл

@ -106,6 +106,10 @@ const mutations = {
setConversationDescription(state, { token, description }) {
Vue.set(state.conversations[token], 'description', description)
},
changeNotificationLevel(state, { token, notificationLevel }) {
Vue.set(state.conversations[token], 'notificationLevel', notificationLevel)
},
}
const actions = {
@ -314,6 +318,10 @@ const actions = {
commit('addConversation', conversation)
},
changeNotificationLevel({ commit }, { token, notificationLevel }) {
commit('changeNotificationLevel', { token, notificationLevel })
},
}
export default { state, mutations, getters, actions }