diff --git a/src/components/RightSidebar/Participants/Participant.vue b/src/components/RightSidebar/Participants/Participant.vue
index aeae82f0c3f..aa1319d3608 100644
--- a/src/components/RightSidebar/Participants/Participant.vue
+++ b/src/components/RightSidebar/Participants/Participant.vue
@@ -80,7 +80,7 @@
(token, attendeeId) => {
- if (!state.speaking[token]) {
- return undefined
- }
-
- return state.speaking[token][attendeeId]
+ getParticipantSpeakingInformation: (state) => (attendeeId) => {
+ return state.speaking[attendeeId]
},
/**
@@ -410,30 +406,55 @@ const mutations = {
*
* @param {object} state - current store state.
* @param {object} data - the wrapping object.
- * @param {string} data.token - the conversation token participant is speaking in.
* @param {string} data.attendeeId - the attendee ID of the participant in conversation.
* @param {boolean} data.speaking - whether the participant is speaking or not
*/
- setSpeaking(state, { token, attendeeId, speaking }) {
+ setSpeaking(state, { attendeeId, speaking }) {
// create a dummy object for current call
- if (!state.speaking[token]) {
- Vue.set(state.speaking, token, {})
+ if (!state.speaking[attendeeId]) {
+ Vue.set(state.speaking, attendeeId, { speaking, lastTimestamp: Date.now(), totalCountedTime: 0 })
}
- if (!state.speaking[token][attendeeId]) {
- Vue.set(state.speaking[token], attendeeId, { speaking: null, lastTimestamp: 0, totalCountedTime: 0 })
+ state.speaking[attendeeId].speaking = speaking
+ },
+
+ /**
+ * Tracks the interval id to update speaking information for a current call.
+ *
+ * @param {object} state - current store state.
+ * @param {number} interval - interval id.
+ */
+ setSpeakingInterval(state, interval) {
+ Vue.set(state, 'speakingInterval', interval)
+ },
+
+ /**
+ * Update speaking information for a participant.
+ *
+ * @param {object} state - current store state.
+ * @param {object} data - the wrapping object.
+ * @param {string} data.attendeeId - the attendee ID of the participant in conversation.
+ * @param {boolean} data.speaking - whether the participant is speaking or not
+ */
+ updateTimeSpeaking(state, { attendeeId, speaking }) {
+ if (!state.speaking[attendeeId]) {
+ return
}
const currentTimestamp = Date.now()
- const currentSpeakingState = state.speaking[token][attendeeId].speaking
-
- if (!currentSpeakingState && speaking) {
- state.speaking[token][attendeeId].speaking = true
- state.speaking[token][attendeeId].lastTimestamp = currentTimestamp
- } else if (currentSpeakingState && !speaking) {
- // when speaking has stopped, update the total talking time
- state.speaking[token][attendeeId].speaking = false
- state.speaking[token][attendeeId].totalCountedTime += (currentTimestamp - state.speaking[token][attendeeId].lastTimestamp)
+ const currentSpeakingState = state.speaking[attendeeId].speaking
+
+ if (!currentSpeakingState && !speaking) {
+ // false -> false, no updates
+ return
+ }
+
+ if (currentSpeakingState) {
+ // true -> false / true -> true, participant is still speaking or finished to speak, update total time
+ state.speaking[attendeeId].totalCountedTime += (currentTimestamp - state.speaking[attendeeId].lastTimestamp)
}
+
+ // false -> true / true -> false / true -> true, update timestamp of last check / signal
+ state.speaking[attendeeId].lastTimestamp = currentTimestamp
},
/**
@@ -441,11 +462,14 @@ const mutations = {
* (including cases when the call ends for everyone).
*
* @param {object} state - current store state.
- * @param {object} data - the wrapping object.
- * @param {string} data.token - the conversation token.
*/
- purgeSpeakingStore(state, { token }) {
- Vue.delete(state.speaking, token)
+ purgeSpeakingStore(state) {
+ Vue.set(state, 'speaking', {})
+
+ if (state.speakingInterval) {
+ clearInterval(state.speakingInterval)
+ Vue.set(state, 'speakingInterval', null)
+ }
},
/**
@@ -1036,12 +1060,33 @@ const actions = {
}
},
- setSpeaking(context, { token, attendeeId, speaking }) {
- context.commit('setSpeaking', { token, attendeeId, speaking })
+ setSpeaking(context, { attendeeId, speaking }) {
+ // We should update time before speaking state, to be able to check previous state
+ context.commit('updateTimeSpeaking', { attendeeId, speaking })
+ context.commit('setSpeaking', { attendeeId, speaking })
+
+ if (!context.state.speakingInterval && speaking) {
+ const interval = setInterval(() => {
+ context.dispatch('updateIntervalTimeSpeaking')
+ }, 1000)
+ context.commit('setSpeakingInterval', interval)
+ }
+ },
+
+ updateIntervalTimeSpeaking(context) {
+ if (!context.state.speaking || !context.state.speakingInterval) {
+ return
+ }
+
+ for (const attendeeId in context.state.speaking) {
+ if (context.state.speaking[attendeeId].speaking) {
+ context.commit('updateTimeSpeaking', { attendeeId, speaking: true })
+ }
+ }
},
- purgeSpeakingStore(context, { token }) {
- context.commit('purgeSpeakingStore', { token })
+ purgeSpeakingStore(context) {
+ context.commit('purgeSpeakingStore')
},
processDialOutAnswer(context, { callid }) {
diff --git a/src/utils/webrtc/SpeakingStatusHandler.js b/src/utils/webrtc/SpeakingStatusHandler.js
index 9201f36583e..63bb40e0af2 100644
--- a/src/utils/webrtc/SpeakingStatusHandler.js
+++ b/src/utils/webrtc/SpeakingStatusHandler.js
@@ -81,7 +81,7 @@ export default class SpeakingStatusHandler {
callParticipantModel.off('change:stoppedSpeaking', this.#handleSpeakingBound)
})
- this.#store.dispatch('purgeSpeakingStore', { token: this.#store.getters.getToken() })
+ this.#store.dispatch('purgeSpeakingStore')
}
/**
@@ -114,7 +114,6 @@ export default class SpeakingStatusHandler {
*/
#handleLocalSpeaking(localMediaModel, speaking) {
this.#store.dispatch('setSpeaking', {
- token: this.#store.getters.getToken(),
attendeeId: this.#store.getters.getAttendeeId(),
speaking,
})
@@ -126,7 +125,6 @@ export default class SpeakingStatusHandler {
*/
#handleLocalPeerId() {
this.#store.dispatch('setSpeaking', {
- token: this.#store.getters.getToken(),
attendeeId: this.#store.getters.getAttendeeId(),
speaking: this.#localMediaModel.attributes.speaking,
})
@@ -149,7 +147,6 @@ export default class SpeakingStatusHandler {
}
this.#store.dispatch('setSpeaking', {
- token: this.#store.getters.getToken(),
attendeeId,
speaking,
})