From bd78555cc31e653171ec68a1f87eafe2304d7bba Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 8 Oct 2020 15:59:55 +0200 Subject: [PATCH 1/5] Add checkbox for locking conversation Added logic for setting a conversation to read-only. Signed-off-by: Vincent Petry --- src/components/TopBar/TopBar.vue | 20 ++++++++++++++++++++ src/services/conversationsService.js | 17 +++++++++++++++++ src/store/conversationsStore.js | 13 +++++++++++++ 3 files changed, 50 insertions(+) diff --git a/src/components/TopBar/TopBar.vue b/src/components/TopBar/TopBar.vue index 7efdae757c6..14499f8a3d3 100644 --- a/src/components/TopBar/TopBar.vue +++ b/src/components/TopBar/TopBar.vue @@ -118,6 +118,12 @@ {{ t('spreed', 'Enter a password') }} + + {{ t('spreed', 'Lock conversation') }} + @@ -204,6 +210,7 @@ export default { // Switch for the password-editing operation isEditingPassword: false, lobbyTimerLoading: false, + readOnlyStateLoading: false, } }, @@ -317,6 +324,9 @@ export default { hasLobbyEnabled() { return this.conversation.lobbyState === WEBINAR.LOBBY.NON_MODERATORS }, + isReadOnly() { + return this.conversation.readOnly === CONVERSATION.STATE.READ_ONLY + }, isPasswordProtected() { return this.conversation.hasPassword }, @@ -457,6 +467,16 @@ export default { this.lobbyTimerLoading = false }, + + async toggleReadOnly() { + this.readOnlyStateLoading = true + await this.$store.dispatch('setReadOnlyState', { + token: this.token, + readOnly: this.isReadOnly ? CONVERSATION.STATE.READ_WRITE : CONVERSATION.STATE.READ_ONLY, + }) + this.readOnlyStateLoading = false + }, + async handlePasswordDisable() { // disable the password protection for the current conversation if (this.conversation.hasPassword) { diff --git a/src/services/conversationsService.js b/src/services/conversationsService.js index fcb827aabad..0aa97ed734a 100644 --- a/src/services/conversationsService.js +++ b/src/services/conversationsService.js @@ -297,6 +297,22 @@ const changeLobbyState = async function(token, newState, timestamp) { } } +/** + * Change the read-only state + * @param {string} token The token of the conversation to be modified + * @param {int} readOnly The new read-only state to set + */ +const changeReadOnlyState = async function(token, readOnly) { + try { + const response = await axios.put(generateOcsUrl('apps/spreed/api/v2', 2) + `room/${token}/read-only`, { + state: readOnly, + }) + return response + } catch (error) { + console.debug('Error while updating read-only state: ', error) + } +} + export { fetchConversations, fetchConversation, @@ -312,6 +328,7 @@ export { makePublic, makePrivate, changeLobbyState, + changeReadOnlyState, setConversationPassword, setConversationName, } diff --git a/src/store/conversationsStore.js b/src/store/conversationsStore.js index fa7f4a4bdab..886d13bcf32 100644 --- a/src/store/conversationsStore.js +++ b/src/store/conversationsStore.js @@ -24,6 +24,7 @@ import { makePublic, makePrivate, changeLobbyState, + changeReadOnlyState, addToFavorites, removeFromFavorites, setConversationName, @@ -206,6 +207,18 @@ const actions = { commit('addConversation', conversation) }, + async setReadOnlyState({ commit, getters }, { token, readOnly }) { + const conversation = Object.assign({}, getters.conversations[token]) + if (!conversation) { + return + } + + await changeReadOnlyState(token, readOnly) + conversation.readOnly = readOnly + + commit('addConversation', conversation) + }, + async setLobbyTimer({ commit, getters }, { token, timestamp }) { const conversation = Object.assign({}, getters.conversations[token]) if (!conversation) { From c176c680fd8a36d574a4daacb17bfac13a7a5ac3 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Thu, 8 Oct 2020 21:22:00 +0200 Subject: [PATCH 2/5] Hide chat controls in read-only conversation In a read-only conversation, the following actions are not available: - start call button is hidden - field for posting fields is hidden - reply button in the messages list is hidden Signed-off-by: Vincent Petry --- src/components/ChatView.vue | 4 ++-- .../MessagesList/MessagesGroup/Message/Message.vue | 9 +++++++-- src/components/TopBar/CallButton.vue | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/components/ChatView.vue b/src/components/ChatView.vue index e60dcbff520..aa3ce582746 100644 --- a/src/components/ChatView.vue +++ b/src/components/ChatView.vue @@ -44,7 +44,7 @@ - + @@ -84,7 +84,7 @@ export default { if (this.isGuest) { return t('spreed', 'You need to be logged in to upload files') } else if (this.isReadOnly) { - return t('spreed', 'This conversation is read only') + return t('spreed', 'This conversation is read-only') } else { return t('spreed', 'Drop your files to upload') } diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.vue b/src/components/MessagesList/MessagesGroup/Message/Message.vue index 8c8d168abcf..dfc4b8c6503 100644 --- a/src/components/MessagesList/MessagesGroup/Message/Message.vue +++ b/src/components/MessagesList/MessagesGroup/Message/Message.vue @@ -59,7 +59,7 @@ the main body of the message as well as a quote. {{ messageTime }} Date: Thu, 8 Oct 2020 21:22:46 +0200 Subject: [PATCH 3/5] In case of error when sending message, revert Whenever an error occurs when sending a message, the message is now put back into the field and the temporary one is removed from the messages list. Whenever a conversation was locked or lobby was enabled concurrently, posting a message before the UI update could result in a 403 or 412 error. These now display a proper message to inform about missing permissions. Signed-off-by: Vincent Petry --- .../NewMessageForm/NewMessageForm.vue | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/components/NewMessageForm/NewMessageForm.vue b/src/components/NewMessageForm/NewMessageForm.vue index fe0e728c8c8..336591ce920 100644 --- a/src/components/NewMessageForm/NewMessageForm.vue +++ b/src/components/NewMessageForm/NewMessageForm.vue @@ -238,8 +238,8 @@ export default { * Sends the new message */ async handleSubmit() { - if (this.parsedText !== '') { + const oldMessage = this.parsedText const temporaryMessage = createTemporaryMessage(this.parsedText, this.token) this.$store.dispatch('addTemporaryMessage', temporaryMessage) this.text = '' @@ -270,7 +270,28 @@ export default { }) } } catch (error) { - console.debug(`error while submitting message ${error}`) + let statusCode = null + console.debug(`error while submitting message ${error}`, error) + if (error.isAxiosError) { + statusCode = error.response.status + } + // 403 when room is read-only, 412 when switched to lobby mode + if (statusCode === 403 || statusCode === 412) { + OC.Notification.show( + t('spreed', 'No permission to post messages in this room'), + { type: 'error' } + ) + } else { + OC.Notification.show( + t('spreed', 'Could not post message: {errorMessage}', { errorMessage: error.message || error }), + { type: 'error' } + ) + } + + // restore message to allow re-sending + this.$store.dispatch('deleteMessage', temporaryMessage) + this.text = oldMessage + this.parsedText = oldMessage } } }, From cbb16c00a5430ffca81c9c3d482046bad58cbad6 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Fri, 9 Oct 2020 14:55:59 +0200 Subject: [PATCH 4/5] Read-only conversation tweaks Moved isConversationReadOnly condition on the reply action button instead of affecting all possible (future) actions. Now using `showError` instead of the global OC notification, the displayed border now has the correct color. Renamed "room" to "conversation" in the error message. Signed-off-by: Vincent Petry --- .../MessagesList/MessagesGroup/Message/Message.vue | 4 ++-- src/components/NewMessageForm/NewMessageForm.vue | 12 +++--------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/components/MessagesList/MessagesGroup/Message/Message.vue b/src/components/MessagesList/MessagesGroup/Message/Message.vue index dfc4b8c6503..6eeb9401692 100644 --- a/src/components/MessagesList/MessagesGroup/Message/Message.vue +++ b/src/components/MessagesList/MessagesGroup/Message/Message.vue @@ -59,7 +59,7 @@ the main body of the message as well as a quote. {{ messageTime }} import AdvancedInput from './AdvancedInput/AdvancedInput' -import { getFilePickerBuilder } from '@nextcloud/dialogs' +import { getFilePickerBuilder, showError } from '@nextcloud/dialogs' import { postNewMessage } from '../../services/messagesService' import Quote from '../Quote' import Actions from '@nextcloud/vue/dist/Components/Actions' @@ -277,15 +277,9 @@ export default { } // 403 when room is read-only, 412 when switched to lobby mode if (statusCode === 403 || statusCode === 412) { - OC.Notification.show( - t('spreed', 'No permission to post messages in this room'), - { type: 'error' } - ) + showError(t('spreed', 'No permission to post messages in this conversation')) } else { - OC.Notification.show( - t('spreed', 'Could not post message: {errorMessage}', { errorMessage: error.message || error }), - { type: 'error' } - ) + showError(t('spreed', 'Could not post message: {errorMessage}', { errorMessage: error.message || error })) } // restore message to allow re-sending From 51debd56d40688277304362c71f6d3cfa87e50c4 Mon Sep 17 00:00:00 2001 From: Vincent Petry Date: Tue, 13 Oct 2020 16:50:08 +0200 Subject: [PATCH 5/5] Display disabled message form in read-only rooms Signed-off-by: Vincent Petry --- src/components/ChatView.vue | 2 +- .../AdvancedInput/AdvancedInput.vue | 2 +- src/components/NewMessageForm/NewMessageForm.vue | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/components/ChatView.vue b/src/components/ChatView.vue index aa3ce582746..4a711568beb 100644 --- a/src/components/ChatView.vue +++ b/src/components/ChatView.vue @@ -44,7 +44,7 @@ - + diff --git a/src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue b/src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue index aef9ac933f8..55aaebf0ed0 100644 --- a/src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue +++ b/src/components/NewMessageForm/AdvancedInput/AdvancedInput.vue @@ -175,7 +175,7 @@ export default { */ placeholderText: { type: String, - default: t('spreed', 'Write message, @ to mention someone …'), + default: '', }, /** diff --git a/src/components/NewMessageForm/NewMessageForm.vue b/src/components/NewMessageForm/NewMessageForm.vue index 87d9a4837fb..a6ef8dda1a6 100644 --- a/src/components/NewMessageForm/NewMessageForm.vue +++ b/src/components/NewMessageForm/NewMessageForm.vue @@ -58,6 +58,7 @@