зеркало из https://github.com/nextcloud/spreed.git
Merge pull request #2838 from nextcloud/bugfix/722/update-guestnames
Update guest names on chat messages and in the call
This commit is contained in:
Коммит
ce7a4c932b
|
@ -91,7 +91,7 @@ class GuestManager {
|
|||
$dispatchEvent = true;
|
||||
|
||||
try {
|
||||
$oldName = $this->getNameBySessionHash($sessionHash);
|
||||
$oldName = $this->getNameBySessionHash($sessionHash, true);
|
||||
|
||||
if ($oldName !== $displayName) {
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
|
@ -117,10 +117,11 @@ class GuestManager {
|
|||
|
||||
/**
|
||||
* @param string $sessionHash
|
||||
* @param bool $allowEmpty
|
||||
* @return string
|
||||
* @throws ParticipantNotFoundException
|
||||
*/
|
||||
public function getNameBySessionHash(string $sessionHash): string {
|
||||
public function getNameBySessionHash(string $sessionHash, bool $allowEmpty = false): string {
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('display_name')
|
||||
->from('talk_guests')
|
||||
|
@ -130,7 +131,7 @@ class GuestManager {
|
|||
$row = $result->fetch();
|
||||
$result->closeCursor();
|
||||
|
||||
if (isset($row['display_name']) && $row['display_name'] !== '') {
|
||||
if (isset($row['display_name']) && ($allowEmpty || $row['display_name'] !== '')) {
|
||||
return $row['display_name'];
|
||||
}
|
||||
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
import attachMediaStream from 'attachmediastream'
|
||||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
||||
import LocalMediaControls from './LocalMediaControls'
|
||||
import Hex from 'crypto-js/enc-hex'
|
||||
import SHA1 from 'crypto-js/sha1'
|
||||
|
||||
export default {
|
||||
|
||||
|
@ -81,12 +83,20 @@ export default {
|
|||
return this.$store.getters.getDisplayName()
|
||||
},
|
||||
|
||||
guestName() {
|
||||
return this.localCallParticipantModel.attributes.guestName || localStorage.getItem('nick') || '?'
|
||||
firstLetterOfGuestName() {
|
||||
const customName = this.guestName !== t('spreed', 'Guest') ? this.guestName : '?'
|
||||
return customName.charAt(0)
|
||||
},
|
||||
|
||||
firstLetterOfGuestName() {
|
||||
return this.guestName.substring(0, 1)
|
||||
sessionHash() {
|
||||
return Hex.stringify(SHA1(this.localCallParticipantModel.attributes.peerId))
|
||||
},
|
||||
|
||||
guestName() {
|
||||
return this.$store.getters.getGuestName(
|
||||
this.$store.getters.getToken(),
|
||||
this.sessionHash,
|
||||
) || localStorage.getItem('nick') || t('spreed', 'Guest')
|
||||
},
|
||||
|
||||
avatarSize() {
|
||||
|
|
|
@ -70,6 +70,8 @@ import attachMediaStream from 'attachmediastream'
|
|||
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
|
||||
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
|
||||
import { ConnectionState } from '../../utils/webrtc/models/CallParticipantModel'
|
||||
import SHA1 from 'crypto-js/sha1'
|
||||
import Hex from 'crypto-js/enc-hex'
|
||||
|
||||
export default {
|
||||
|
||||
|
@ -126,18 +128,23 @@ export default {
|
|||
'icon-loading': this.model.attributes.connectionState !== ConnectionState.CONNECTED && this.model.attributes.connectionState !== ConnectionState.COMPLETED && this.model.attributes.connectionState !== ConnectionState.FAILED_NO_RESTART,
|
||||
}
|
||||
},
|
||||
|
||||
firstLetterOfGuestName() {
|
||||
return (this.model.attributes.name || '?').substring(0, 1)
|
||||
const customName = this.participantName !== t('spreed', 'Guest') ? this.participantName : '?'
|
||||
return customName.charAt(0)
|
||||
},
|
||||
|
||||
sessionHash() {
|
||||
return Hex.stringify(SHA1(this.model.attributes.peerId))
|
||||
},
|
||||
|
||||
participantName() {
|
||||
let participantName = this.model.attributes.name
|
||||
|
||||
// "Guest" placeholder is not shown until the initial connection for
|
||||
// consistency with regular users.
|
||||
if (!this.model.attributes.userId && this.model.attributes.connectionState !== ConnectionState.NEW) {
|
||||
participantName = participantName || t('spreed', 'Guest')
|
||||
if (!this.model.attributes.userId) {
|
||||
participantName = this.$store.getters.getGuestName(
|
||||
this.$store.getters.getToken(),
|
||||
this.sessionHash,
|
||||
)
|
||||
}
|
||||
|
||||
return participantName
|
||||
|
|
|
@ -113,8 +113,8 @@ export default {
|
|||
actorDisplayName() {
|
||||
const displayName = this.messages[0].actorDisplayName.trim()
|
||||
|
||||
if (displayName === '' && this.actorType === 'guests') {
|
||||
return t('spreed', 'Guest')
|
||||
if (this.actorType === 'guests') {
|
||||
return this.$store.getters.getGuestName(this.token, this.actorId)
|
||||
}
|
||||
|
||||
if (displayName === '') {
|
||||
|
|
|
@ -252,7 +252,6 @@ export default {
|
|||
&& (message1.systemMessage.length === 0) === (message2.systemMessage.length === 0) // Only group system messages with each others
|
||||
&& message1.actorType === message2.actorType // To have the same author, the type
|
||||
&& message1.actorId === message2.actorId // and the id of the author must be the same
|
||||
&& message1.actorDisplayName === message2.actorDisplayName // FIXME: this is in case a guest user changes its username
|
||||
&& !this.messagesHaveDifferentDate(message1, message2) // Posted on the same day
|
||||
},
|
||||
|
||||
|
@ -371,6 +370,9 @@ export default {
|
|||
const messages = await request({ token: this.token, lastKnownMessageId, includeLastKnown })
|
||||
// Process each messages and adds it to the store
|
||||
messages.data.ocs.data.forEach(message => {
|
||||
if (message.actorType === 'guests') {
|
||||
this.$store.dispatch('setGuestNameIfEmpty', message)
|
||||
}
|
||||
this.$store.dispatch('processMessage', message)
|
||||
})
|
||||
} catch (exception) {
|
||||
|
@ -397,6 +399,9 @@ export default {
|
|||
const messages = await request({ token: this.token, lastKnownMessageId })
|
||||
// Process each messages and adds it to the store
|
||||
messages.data.ocs.data.forEach(message => {
|
||||
if (message.actorType === 'guests') {
|
||||
this.$store.dispatch('forceGuestName', message)
|
||||
}
|
||||
this.$store.dispatch('processMessage', message)
|
||||
})
|
||||
// Scroll to the last message if sticky
|
||||
|
|
|
@ -162,6 +162,12 @@ export default {
|
|||
token: this.token,
|
||||
isReplyable: false,
|
||||
})
|
||||
|
||||
if (this.$store.getters.getActorType() === 'guests') {
|
||||
// Strip off "guests/" from the sessionHash
|
||||
message.actorId = this.$store.getters.getActorId().substring(6)
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current message is a quote-reply messag, add the parent key to the
|
||||
* temporary message object.
|
||||
|
|
|
@ -81,7 +81,7 @@ import ParticipantsList from './ParticipantsList/ParticipantsList'
|
|||
import SearchBox from '../../LeftSidebar/SearchBox/SearchBox'
|
||||
import debounce from 'debounce'
|
||||
import { EventBus } from '../../../services/EventBus'
|
||||
import { CONVERSATION, WEBINAR } from '../../../constants'
|
||||
import { CONVERSATION, PARTICIPANT, WEBINAR } from '../../../constants'
|
||||
import { searchPossibleConversations } from '../../../services/conversationsService'
|
||||
import {
|
||||
addParticipant,
|
||||
|
@ -89,6 +89,8 @@ import {
|
|||
} from '../../../services/participantsService'
|
||||
import isInLobby from '../../../mixins/isInLobby'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import SHA1 from 'crypto-js/sha1'
|
||||
import Hex from 'crypto-js/enc-hex'
|
||||
|
||||
export default {
|
||||
name: 'ParticipantsTab',
|
||||
|
@ -315,6 +317,14 @@ export default {
|
|||
token: token,
|
||||
participant,
|
||||
})
|
||||
if (participant.participantType === PARTICIPANT.TYPE.GUEST
|
||||
|| participant.participantType === PARTICIPANT.TYPE.GUEST_MODERATOR) {
|
||||
this.$store.dispatch('forceGuestName', {
|
||||
token: token,
|
||||
actorId: Hex.stringify(SHA1(participant.sessionId)),
|
||||
actorDisplayName: participant.displayName,
|
||||
})
|
||||
}
|
||||
})
|
||||
this.participantsInitialised = true
|
||||
} catch (exception) {
|
||||
|
|
|
@ -394,11 +394,23 @@ export default {
|
|||
this.isEditingPassword = false
|
||||
},
|
||||
async handleChooseUserName() {
|
||||
const previousName = this.$store.getters.getDisplayName()
|
||||
try {
|
||||
await setGuestUserName(this.token, this.guestUserName)
|
||||
this.$store.dispatch('setDisplayName', this.guestUserName)
|
||||
this.$store.dispatch('forceGuestName', {
|
||||
token: this.token,
|
||||
actorId: this.$store.getters.getActorId().substring(6),
|
||||
actorDisplayName: this.guestUserName,
|
||||
})
|
||||
await setGuestUserName(this.token, this.guestUserName)
|
||||
this.isEditingUsername = false
|
||||
} catch (exception) {
|
||||
this.$store.dispatch('setDisplayName', previousName)
|
||||
this.$store.dispatch('forceGuestName', {
|
||||
token: this.token,
|
||||
actorId: this.$store.getters.getActorId().substring(6),
|
||||
actorDisplayName: previousName,
|
||||
})
|
||||
console.debug(exception)
|
||||
}
|
||||
},
|
||||
|
|
|
@ -56,8 +56,8 @@ const lookForNewMessages = async({ token, lastKnownMessageId }, options) => {
|
|||
* @param {string} message The message object;
|
||||
* @param {Number} parent The id of the message to be replied to.
|
||||
*/
|
||||
const postNewMessage = async function({ token, message, parent }) {
|
||||
const response = await axios.post(generateOcsUrl('apps/spreed/api/v1/chat', 2) + token, { message, actorDisplayName: '', replyTo: parent })
|
||||
const postNewMessage = async function({ token, message, actorDisplayName, parent }) {
|
||||
const response = await axios.post(generateOcsUrl('apps/spreed/api/v1/chat', 2) + token, { message, actorDisplayName, replyTo: parent })
|
||||
return response
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* @copyright Copyright (c) 2019 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @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/>.
|
||||
*
|
||||
*/
|
||||
import Vue from 'vue'
|
||||
|
||||
const state = {
|
||||
guestNames: {
|
||||
},
|
||||
}
|
||||
|
||||
const getters = {
|
||||
/**
|
||||
* Gets the participants array
|
||||
* @param {object} state the state object.
|
||||
* @returns {array} the participants array (if there are participants in the store)
|
||||
*/
|
||||
getGuestName: (state) => (token, actorId) => {
|
||||
if (state.guestNames[token] && state.guestNames[token][actorId]) {
|
||||
return state.guestNames[token][actorId]
|
||||
}
|
||||
return t('spreed', 'Guest')
|
||||
},
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
/**
|
||||
* Adds a guest name to the store
|
||||
* @param {object} state current store state
|
||||
* @param {boolean} noUpdate Only set the guest name if it was not set before
|
||||
* @param {string} token the token of the conversation
|
||||
* @param {string} actorId the guest
|
||||
* @param {string} actorDisplayName the display name to set
|
||||
*/
|
||||
addGuestName(state, { noUpdate, token, actorId, actorDisplayName }) {
|
||||
if (!state.guestNames[token]) {
|
||||
Vue.set(state.guestNames, token, [])
|
||||
}
|
||||
if (!state.guestNames[token][actorId]) {
|
||||
Vue.set(state.guestNames[token], actorId, t('spreed', 'Guest'))
|
||||
} else if (noUpdate) {
|
||||
return
|
||||
}
|
||||
state.guestNames[token][actorId] = actorDisplayName
|
||||
},
|
||||
}
|
||||
|
||||
const actions = {
|
||||
|
||||
/**
|
||||
* Add guest name of a chat message to the store
|
||||
*
|
||||
* @param {object} context default store context
|
||||
* @param {string} token the token of the conversation
|
||||
* @param {string} actorId the guest
|
||||
* @param {string} actorDisplayName the display name to set
|
||||
*/
|
||||
setGuestNameIfEmpty(context, { token, actorId, actorDisplayName }) {
|
||||
context.commit('addGuestName', { noUpdate: true, token, actorId, actorDisplayName })
|
||||
},
|
||||
/**
|
||||
* Add guest name of a chat message to the store
|
||||
*
|
||||
* @param {object} context default store context
|
||||
* @param {string} token the token of the conversation
|
||||
* @param {string} actorId the guest
|
||||
* @param {string} actorDisplayName the display name to set
|
||||
*/
|
||||
forceGuestName(context, { token, actorId, actorDisplayName }) {
|
||||
context.commit('addGuestName', { noUpdate: false, token, actorId, actorDisplayName })
|
||||
},
|
||||
}
|
||||
|
||||
export default { state, mutations, getters, actions }
|
|
@ -24,6 +24,7 @@ import Vue from 'vue'
|
|||
import Vuex, { Store } from 'vuex'
|
||||
import actorStore from './actorStore'
|
||||
import conversationsStore from './conversationsStore'
|
||||
import guestNameStore from './guestNameStore'
|
||||
import messagesStore from './messagesStore'
|
||||
import participantsStore from './participantsStore'
|
||||
import quoteReplyStore from './quoteReplyStore'
|
||||
|
@ -39,6 +40,7 @@ export default new Store({
|
|||
modules: {
|
||||
actorStore,
|
||||
conversationsStore,
|
||||
guestNameStore,
|
||||
messagesStore,
|
||||
participantsStore,
|
||||
quoteReplyStore,
|
||||
|
|
Загрузка…
Ссылка в новой задаче