<commit_before>import { Injectable } from '@angular/core'
import * as CodeMirror from 'codemirror'

import { NetworkService } from '../core/network/network.service'
import { CollaboratorsService } from '../core/collaborators/collaborators.service'
import { DocService } from '../doc/doc.service'
import * as MuteStructs  from 'mute-structs'

@Injectable()
export class CursorService {

  private networkService: NetworkService
  private collaboratorsService: CollaboratorsService
  private docService: DocService
  private cmEditor: CodeMirror.Editor

  // Cursor objects of other collaborators, not yours.
  private cursors: Map<number, Cursor>

  constructor(
    networkService: NetworkService,
    collaboratorsService: CollaboratorsService,
    docService: DocService
  ) {
    this.networkService = networkService
    this.collaboratorsService = collaboratorsService
    this.docService = docService
    this.cursors = new Map()
  }

  init (cmEditor: CodeMirror.Editor): void {
    this.cmEditor = cmEditor
    let cmDoc: CodeMirror.Doc = cmEditor.getDoc()

    this.collaboratorsService.onJoin
      .subscribe(({id, pseudo, color}: {id: number, pseudo: string, color: string}) => {
        this.cursors.set(id, new Cursor(color))
    })

    this.collaboratorsService.onLeave.subscribe((id: number) => {
      let cursor = this.cursors.get(id)
      cursor.cmBookmark.clear()
      cursor.stopClotting()
      this.cursors.delete(id)
    })

    this.networkService.onPeerCursor
      .subscribe(({id, index, identifier}:
        {id: number, index: number, identifier: MuteStructs.Identifier}) => {
        if (id !== -1) {
          let cursor = this.cursors.get(id)
          if (cursor.cmBookmark === null) {
            cursor.startClotting()
          } else {
            cursor.restartClotting()
            // cursor.cmBookmark.clear()
          }
          if (index === -2) {
            cursor.stopClotting()
          } else {
            let pos: any
            if (index === -1) {
              let lastLine = cmDoc.lastLine()
              pos = {line: lastLine, pos: cmDoc.getLine(lastLine).length}
            } else {
              pos = cmDoc.posFromIndex(this.docService.indexFromId(identifier) + index)
            }
            if (cursor.cmBookmark !== null) {
              let oldCoords = this.cmEditor.cursorCoords(cursor.cmBookmark.find(), 'local')<commit_msg>fix(cursor): when peer has left just after has joined<commit_after>import { Injectable } from '@angular/core'
import * as CodeMirror from 'codemirror'

import { NetworkService } from '../core/network/network.service'
import { CollaboratorsService } from '../core/collaborators/collaborators.service'
import { DocService } from '../doc/doc.service'
import * as MuteStructs  from 'mute-structs'

@Injectable()
export class CursorService {

  private networkService: NetworkService
  private collaboratorsService: CollaboratorsService
  private docService: DocService
  private cmEditor: CodeMirror.Editor

  // Cursor objects of other collaborators, not yours.
  private cursors: Map<number, Cursor>

  constructor(
    networkService: NetworkService,
    collaboratorsService: CollaboratorsService,
    docService: DocService
  ) {
    this.networkService = networkService
    this.collaboratorsService = collaboratorsService
    this.docService = docService
    this.cursors = new Map()
  }

  init (cmEditor: CodeMirror.Editor): void {
    this.cmEditor = cmEditor
    let cmDoc: CodeMirror.Doc = cmEditor.getDoc()

    this.collaboratorsService.onJoin
      .subscribe(({id, pseudo, color}: {id: number, pseudo: string, color: string}) => {
        this.cursors.set(id, new Cursor(color))
    })

    this.collaboratorsService.onLeave.subscribe((id: number) => {
      let cursor = this.cursors.get(id)
      if (cursor.cmBookmark !== null) {
        cursor.cmBookmark.clear()
      }
      cursor.stopClotting()
      this.cursors.delete(id)
    })

    this.networkService.onPeerCursor
      .subscribe(({id, index, identifier}:
        {id: number, index: number, identifier: MuteStructs.Identifier}) => {
        if (id !== -1) {
          let cursor = this.cursors.get(id)
          if (cursor.cmBookmark === null) {
            cursor.startClotting()
          } else {
            cursor.restartClotting()
            // cursor.cmBookmark.clear()
          }
          if (index === -2) {
            cursor.stopClotting()
          } else {
            let pos: any
            if (index === -1) {
              let lastLine = cmDoc.lastLine()
              pos = {line: lastLine, pos: cmDoc.getLine(lastLine).length}
            } else {
              pos = cmDoc.posFromIndex(this.docService.indexFromId(identifier) + index)
            }
            if (cursor.cmBookmark !== null) {
              let oldCoords = this.cmEditor.cursorCoords(cursor.cmBookmark.find(), 'local')
{'fraction_non_alphanumeric': 0.11440851412198116, 'fraction_numerical': 0.0012279983626688497, 'mean_word_length': 2.663418290854573, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5503896', 'n_tokens_mistral': 1430, 'n_tokens_neox': 1387, 'n_words': 316}