OnlineUsersManager.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. /* eslint-disable
  2. camelcase,
  3. n/handle-callback-err,
  4. max-len,
  5. no-return-assign,
  6. */
  7. // TODO: This file was created by bulk-decaffeinate.
  8. // Fix any style issues and re-enable lint.
  9. /*
  10. * decaffeinate suggestions:
  11. * DS101: Remove unnecessary use of Array.from
  12. * DS102: Remove unnecessary code created because of implicit returns
  13. * DS206: Consider reworking classes to avoid initClass
  14. * DS207: Consider shorter variations of null checks
  15. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  16. */
  17. import ColorManager from '../colors/ColorManager'
  18. let OnlineUsersManager
  19. export default OnlineUsersManager = (function () {
  20. OnlineUsersManager = class OnlineUsersManager {
  21. static initClass() {
  22. this.prototype.cursorUpdateInterval = 500
  23. }
  24. constructor(ide, $scope) {
  25. this.ide = ide
  26. this.$scope = $scope
  27. this.$scope.onlineUsers = {}
  28. this.$scope.onlineUserCursorHighlights = {}
  29. this.$scope.onlineUsersArray = []
  30. this.$scope.onlineUsersCount = 0
  31. this.$scope.$on('cursor:editor:update', (event, position) => {
  32. return this.sendCursorPositionUpdate(position)
  33. })
  34. this.$scope.$on('project:joined', () => {
  35. return this.ide.socket.emit(
  36. 'clientTracking.getConnectedUsers',
  37. (error, connectedUsers) => {
  38. this.$scope.onlineUsers = {}
  39. for (const user of Array.from(connectedUsers || [])) {
  40. if (user.client_id === this.ide.socket.publicId) {
  41. // Don't store myself
  42. continue
  43. }
  44. // Store data in the same format returned by clientTracking.clientUpdated
  45. this.$scope.onlineUsers[user.client_id] = {
  46. id: user.client_id,
  47. user_id: user.user_id,
  48. email: user.email,
  49. name: `${user.first_name} ${user.last_name}`,
  50. doc_id:
  51. user.cursorData != null ? user.cursorData.doc_id : undefined,
  52. row: user.cursorData != null ? user.cursorData.row : undefined,
  53. column:
  54. user.cursorData != null ? user.cursorData.column : undefined,
  55. }
  56. }
  57. return this.refreshOnlineUsers()
  58. }
  59. )
  60. })
  61. this.ide.socket.on('clientTracking.clientUpdated', client => {
  62. if (client.id !== this.ide.socket.publicId) {
  63. // Check it's not me!
  64. return this.$scope.$apply(() => {
  65. this.$scope.onlineUsers[client.id] = client
  66. return this.refreshOnlineUsers()
  67. })
  68. }
  69. })
  70. this.ide.socket.on('clientTracking.clientDisconnected', client_id => {
  71. return this.$scope.$apply(() => {
  72. delete this.$scope.onlineUsers[client_id]
  73. return this.refreshOnlineUsers()
  74. })
  75. })
  76. this.$scope.getHueForUserId = user_id => {
  77. return ColorManager.getHueForUserId(user_id)
  78. }
  79. }
  80. refreshOnlineUsers() {
  81. this.$scope.onlineUsersArray = []
  82. for (const client_id in this.$scope.onlineUsers) {
  83. const user = this.$scope.onlineUsers[client_id]
  84. if (user.doc_id != null) {
  85. user.doc = this.ide.fileTreeManager.findEntityById(user.doc_id)
  86. }
  87. // If the user's name is empty use their email as display name
  88. // Otherwise they're probably an anonymous user
  89. if (user.name === null || user.name.trim().length === 0) {
  90. if (user.email) {
  91. user.name = user.email.trim()
  92. } else if (user.user_id === 'anonymous-user') {
  93. user.name = 'Anonymous'
  94. }
  95. }
  96. user.initial = user.name != null ? user.name[0] : undefined
  97. if (!user.initial || user.initial === ' ') {
  98. user.initial = '?'
  99. }
  100. this.$scope.onlineUsersArray.push(user)
  101. }
  102. // keep a count of the other online users
  103. this.$scope.onlineUsersCount = this.$scope.onlineUsersArray.length
  104. this.$scope.onlineUserCursorHighlights = {}
  105. for (const client_id in this.$scope.onlineUsers) {
  106. const client = this.$scope.onlineUsers[client_id]
  107. const { doc_id } = client
  108. if (doc_id == null || client.row == null || client.column == null) {
  109. continue
  110. }
  111. if (!this.$scope.onlineUserCursorHighlights[doc_id]) {
  112. this.$scope.onlineUserCursorHighlights[doc_id] = []
  113. }
  114. this.$scope.onlineUserCursorHighlights[doc_id].push({
  115. label: client.name,
  116. cursor: {
  117. row: client.row,
  118. column: client.column,
  119. },
  120. hue: ColorManager.getHueForUserId(client.user_id),
  121. })
  122. }
  123. if (this.$scope.onlineUsersArray.length > 0) {
  124. delete this.cursorUpdateTimeout
  125. return (this.cursorUpdateInterval = 500)
  126. } else {
  127. delete this.cursorUpdateTimeout
  128. return (this.cursorUpdateInterval = 60 * 1000 * 5)
  129. }
  130. }
  131. sendCursorPositionUpdate(position) {
  132. if (position != null) {
  133. this.$scope.currentPosition = position // keep track of the latest position
  134. }
  135. if (this.cursorUpdateTimeout == null) {
  136. return (this.cursorUpdateTimeout = setTimeout(() => {
  137. const doc_id = this.$scope.editor.open_doc_id
  138. // always send the latest position to other clients
  139. this.ide.socket.emit('clientTracking.updatePosition', {
  140. row:
  141. this.$scope.currentPosition != null
  142. ? this.$scope.currentPosition.row
  143. : undefined,
  144. column:
  145. this.$scope.currentPosition != null
  146. ? this.$scope.currentPosition.column
  147. : undefined,
  148. doc_id,
  149. })
  150. return delete this.cursorUpdateTimeout
  151. }, this.cursorUpdateInterval))
  152. }
  153. }
  154. }
  155. OnlineUsersManager.initClass()
  156. return OnlineUsersManager
  157. })()