UNPKG

soocrate-core

Version:

this is the core of soocrate application

312 lines (275 loc) 8.68 kB
import animals from 'animals' import hash from 'string-hash' var debug = require('debug')('CRATE:Communication:MarkerManager:Marker') /** * Marker is class for managing the marker of one user,it includes the caret, avatar, and pseudo Names. */ export default class Marker { /** * Marker Module manages the Carets, avatars, pseudo names for the different users of the document * @param {[string]} origin the id of the the user * @param {Number} lifeTime After this time, if no ping or Caret position is received => * remove caret and avatar. if lifetime is -1 we didn't add the avatar * @param {[{index: index,length: 0}]} range range stars from index with the specified length * @param {[cursor module]} cursorsp the used cursor module for quilljs * @param {[Boolean]} cursor create the caret or not. If it is from ping, it will be false else true * @param {Boolean} isItME is it my caret ? true or false to disable the time if it is true */ constructor(origin, options, editor) { //lifeTime = -1, range, cursorsp, cursor, isItME = false, editor) { if (origin === undefined) { console.error('origin not defined', origin) } if (editor === undefined) { console.error('editor not defined', editor) } if (Object.keys(editor).length === 0 && editor.constructor === Object) { console.error('editor is empty', editor) } if (options == null) { var options = { lifeTime: -1, range: {}, cursor: false, isItME: false } } /** * origin the id of the the user * @type {[type]} */ this.options = options this.origin = origin /** * lifeTime After this time, if no ping or Caret position is received => * remove caret and avatar. if lifetime is -1 we don't add the avatar * @type {[type]} */ this.lifeTime = options.lifeTime /** * used to store last update time to detected outdated users * @type {Date} */ this.time = new Date().getTime() /** * color rgb(r,g,b) * @type {String} */ this.colorRGB = this.constructor.getColor(this.origin, 'rgb') /** * color rgba(r,g,b,0.5) * @type {String} */ this.colorRGBLight = this.constructor.getColor(this.origin, 'rgba') /** * auto generated pseudo name (from animals list) * @type {[type]} */ this.animal = this.constructor.getPseudoname(this.origin, null) /** * Anonymous + auto generated pseudo name * @type {String} */ this.pseudoName = this.constructor.getPseudoname(this.origin) /** * add or not the avatar * @type {Boolean} */ this.avatarAdd = false /** * true for an editor, false if it is from a ping * @type {[type]} */ this.cursor = options.cursor this._editor = editor if (editor) { this._editorContainerID = editor._editorContainerID } if (this.lifeTime != -1) { // -1 => created without timer avatar cursor if (options.isItMe) { this.addAvatar() } else if (this.cursor) { this.addCursor(options.range) } } } /** * capitalize uppercase the first letter * @param {[string]} s [string] * @return {[string]} [String the first letter is in uppercase] */ static capitalize(s) { return s.charAt(0).toUpperCase() + s.slice(1) } /** * getColor for a specific id, get a unique color * @param {[string]} str [the id of the user] * @return {[(r,g,b))]} [the corresponding rgb color] */ static getColor(str, format = 'rgb') { var h1 = hash(str) % 206 var h2 = (h1 * 7) % 206 var h3 = (h1 * 11) % 206 let color = Math.floor(h1 + 50) + ', ' + Math.floor(h2 + 50) + ', ' + Math.floor(h3 + 50) if (format === 'rgb') { return 'rgb(' + color + ')' } if (format === 'rgba') { return 'rgba(' + color + ')' } return color } static getPseudoname(id, format = 'Anonymous') { if (format === 'Anonymous') { return ( 'Anonymous ' + this.capitalize(animals.words[hash(id) % animals.words.length]) ) } return animals.words[hash(id) % animals.words.length] } /** * update the time to keep the avatar and cursor if it exist * @param {[{index: index,length: 0}]} range [description] * @param {[boolean]} cursor [if it is true add update the caret position] */ update(range, cursor) { this.time = new Date().getTime() let editor = $(`#${this._editorContainerID}`) let avatar = $(`#${this._editorContainerID} #${this.origin}`) if (!avatar.length && editor.length) { this.addAvatar() } if (this.avatarAdd) { avatar.attr('data-toggle', 'tooltip') avatar.attr('title', this.pseudoName) } if (this.cursor == true && cursor == true) { // in the case of update, make sure that ping updates don't change the range this._editor.viewEditor .getModule('cursors') .moveCursor(this.origin, range) } else if (cursor == true) { this.cursor = cursor this.addCursor(range) } return this } /** * checkIfOutdated check if the user is outdated and if it is the case remove its caret and avatar */ checkIfOutdated() { var timeNow = new Date().getTime() var diff = timeNow - this.time // if cursor is outdated if (diff >= this.lifeTime) { // Remve cursor and avatar if (this.cursor) { this._editor.viewEditor.getModule('cursors').removeCursor(this.origin) this.cursor = false } this.removeAvatar() return true } else { // jQuery(`#${this._editorContainerID} #${this.origin}`).css('opacity', (1 - ((timeNow - this.time) / this.lifeTime))); return false } } /* * addAvatar addAvatar of the user to the editor with corresponding divID * @param {String} divID [the id of the div where the avatars are placed] */ addAvatar(divID = '#users') { jQuery(`#${this._editorContainerID} ${divID}`).append(this.getAvatar()) let avatar = $(`#${this._editorContainerID} #${this.origin}`) avatar.attr('data-toggle', 'tooltip') avatar.attr('title', this.pseudoName) this.avatarAdd = true if (!this.options.isItMe) { /** * a timer that is used to check if the user is Outdated * @return {[type]} [description] */ this.timer = setInterval(() => this.checkIfOutdated(), 1000) } return this } /** * getAvatar return a div that contains this user id * @return {[type]} [description] */ getAvatar(subDomain = '') { return ( '<div id="' + this.origin + '"style="background-color:' + this.colorRGB + ';"><img class="imageuser" src="' + subDomain + '/icons/' + this.animal + '.png" alt="' + this.pseudoName + '"></div>' ) } /** * getAvatar return the div that contains this user id * @return {[type]} [description] */ static getAvatar(id, subDomain = '') { return ( '<div id="' + id + '"style="background-color:' + this.getColor(id, 'rgb') + ';"><img class="imageuser" src="' + subDomain + '/icons/' + this.getPseudoname(id, null) + '.png" alt="' + this.getPseudoname(id) + '"></div>' ) } /** * removeAvatar remove the avatar of the user from the interface * @return {[type]} [description] */ removeAvatar() { let avatar = $(`#${this._editorContainerID} #${this.origin}`) avatar.remove() this.avatarAdd = false clearInterval(this.timer) return this } /** * setPseudo set pseudo for the user * @param {[type]} Pseudo [description] */ setPseudo(Pseudo) { this.pseudoName = Pseudo let avatar = $(`#${this._editorContainerID} #${this.origin}`) if (avatar.length) { avatar.attr('title', this.pseudoName) } return this } /** * addCursor add the cursor to the editor * @param {[{index: index,length: 0}]} range [description] */ addCursor(range) { this.cursor = true this._editor.viewEditor .getModule('cursors') .setCursor(this.origin, range, this.pseudoName, this.colorRGB) return this } }