Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

SpeakerStatsCollector.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. import * as JitsiConferenceEvents from '../../JitsiConferenceEvents';
  2. import XMPPEvents from '../../service/xmpp/XMPPEvents';
  3. import SpeakerStats from './SpeakerStats';
  4. /**
  5. * A collection for tracking speaker stats. Attaches listeners
  6. * to the conference to automatically update on tracked events.
  7. */
  8. export default class SpeakerStatsCollector {
  9. /**
  10. * Initializes a new SpeakerStatsCollector instance.
  11. *
  12. * @constructor
  13. * @param {JitsiConference} conference - The conference to track.
  14. * @returns {void}
  15. */
  16. constructor(conference) {
  17. this.stats = {
  18. users: {
  19. // userId: SpeakerStats
  20. },
  21. dominantSpeakerId: null
  22. };
  23. const userId = conference.myUserId();
  24. this.stats.users[userId] = new SpeakerStats(userId, null, true);
  25. this.conference = conference;
  26. conference.addEventListener(
  27. JitsiConferenceEvents.DOMINANT_SPEAKER_CHANGED,
  28. this._onDominantSpeaker.bind(this));
  29. conference.addEventListener(
  30. JitsiConferenceEvents.USER_JOINED,
  31. this._onUserJoin.bind(this));
  32. conference.addEventListener(
  33. JitsiConferenceEvents.USER_LEFT,
  34. this._onUserLeave.bind(this));
  35. conference.addEventListener(
  36. JitsiConferenceEvents.DISPLAY_NAME_CHANGED,
  37. this._onDisplayNameChange.bind(this));
  38. if (conference.xmpp) {
  39. conference.xmpp.addListener(
  40. XMPPEvents.SPEAKER_STATS_RECEIVED,
  41. this._updateStats.bind(this));
  42. }
  43. }
  44. /**
  45. * Reacts to dominant speaker change events by changing its speaker stats
  46. * models to reflect the current dominant speaker.
  47. *
  48. * @param {string} dominantSpeakerId - The user id of the new
  49. * dominant speaker.
  50. * @returns {void}
  51. * @private
  52. */
  53. _onDominantSpeaker(dominantSpeakerId) {
  54. const oldDominantSpeaker
  55. = this.stats.users[this.stats.dominantSpeakerId];
  56. const newDominantSpeaker = this.stats.users[dominantSpeakerId];
  57. oldDominantSpeaker && oldDominantSpeaker.setDominantSpeaker(false);
  58. newDominantSpeaker && newDominantSpeaker.setDominantSpeaker(true);
  59. this.stats.dominantSpeakerId = dominantSpeakerId;
  60. }
  61. /**
  62. * Reacts to user join events by creating a new SpeakerStats model.
  63. *
  64. * @param {string} userId - The user id of the new user.
  65. * @param {JitsiParticipant} - The JitsiParticipant model for the new user.
  66. * @returns {void}
  67. * @private
  68. */
  69. _onUserJoin(userId, participant) {
  70. if (participant.isHidden()) {
  71. return;
  72. }
  73. if (!this.stats.users[userId]) {
  74. this.stats.users[userId] = new SpeakerStats(userId, participant.getDisplayName());
  75. }
  76. }
  77. /**
  78. * Reacts to user leave events by updating the associated user's
  79. * SpeakerStats model.
  80. *
  81. * @param {string} userId - The user id of the user that left.
  82. * @returns {void}
  83. * @private
  84. */
  85. _onUserLeave(userId) {
  86. const savedUser = this.stats.users[userId];
  87. if (savedUser) {
  88. savedUser.markAsHasLeft();
  89. }
  90. }
  91. /**
  92. * Reacts to user name change events by updating the last known name
  93. * tracked in the associated SpeakerStats model.
  94. *
  95. * @param {string} userId - The user id of the user that left.
  96. * @returns {void}
  97. * @private
  98. */
  99. _onDisplayNameChange(userId, newName) {
  100. const savedUser = this.stats.users[userId];
  101. if (savedUser) {
  102. savedUser.setDisplayName(newName);
  103. }
  104. }
  105. /**
  106. * Return a copy of the tracked SpeakerStats models.
  107. *
  108. * @returns {Object} The keys are the user ids and the values are the
  109. * associated user's SpeakerStats model.
  110. * @private
  111. */
  112. getStats() {
  113. return this.stats.users;
  114. }
  115. /**
  116. * Updates of the current stats is requested, passing the new values.
  117. *
  118. * @param {Object} newStats - The new values used to update current one.
  119. * @private
  120. */
  121. _updateStats(newStats) {
  122. for (const userId in newStats) { // eslint-disable-line guard-for-in
  123. let speakerStatsToUpdate;
  124. const newParticipant = this.conference.getParticipantById(userId);
  125. // we want to ignore hidden participants
  126. if (!newParticipant || !newParticipant.isHidden()) {
  127. if (this.stats.users[userId]) {
  128. speakerStatsToUpdate = this.stats.users[userId];
  129. if (!speakerStatsToUpdate.getDisplayName()) {
  130. speakerStatsToUpdate
  131. .setDisplayName(newStats[userId].displayName);
  132. }
  133. } else {
  134. speakerStatsToUpdate = new SpeakerStats(
  135. userId, newStats[userId].displayName);
  136. this.stats.users[userId] = speakerStatsToUpdate;
  137. speakerStatsToUpdate.markAsHasLeft();
  138. }
  139. }
  140. speakerStatsToUpdate.totalDominantSpeakerTime
  141. = newStats[userId].totalDominantSpeakerTime;
  142. }
  143. }
  144. }