open-documents.ts 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Migrated from static methods of Document in Document.js
  2. import { DocumentContainer } from '@/features/ide-react/editor/document-container'
  3. import { debugConsole } from '@/utils/debugging'
  4. import { Socket } from '@/features/ide-react/connection/types/socket'
  5. import { IdeEventEmitter } from '@/features/ide-react/create-ide-event-emitter'
  6. import { EventLog } from '@/features/ide-react/editor/event-log'
  7. import EditorWatchdogManager from '@/features/ide-react/connection/editor-watchdog-manager'
  8. export class OpenDocuments {
  9. private openDocs = new Map<string, DocumentContainer>()
  10. // eslint-disable-next-line no-useless-constructor
  11. constructor(
  12. private readonly socket: Socket,
  13. private readonly globalEditorWatchdogManager: EditorWatchdogManager,
  14. private readonly events: IdeEventEmitter,
  15. private readonly eventLog: EventLog
  16. ) {}
  17. getDocument(docId: string) {
  18. // Try to clean up existing docs before reopening them. If the doc has no
  19. // buffered ops then it will be deleted by _cleanup() and a new instance
  20. // of the document created below. This prevents us trying to follow the
  21. // joinDoc:existing code path on an existing doc that doesn't have any
  22. // local changes and getting an error if its version is too old.
  23. if (this.openDocs.has(docId)) {
  24. debugConsole.log(
  25. `[getDocument] Cleaning up existing document instance for ${docId}`
  26. )
  27. this.openDocs.get(docId)?.cleanUp()
  28. }
  29. if (!this.openDocs.has(docId)) {
  30. debugConsole.log(
  31. `[getDocument] Creating new document instance for ${docId}`
  32. )
  33. this.createDoc(docId)
  34. } else {
  35. debugConsole.log(
  36. `[getDocument] Returning existing document instance for ${docId}`
  37. )
  38. }
  39. return this.openDocs.get(docId)
  40. }
  41. private createDoc(docId: string) {
  42. const doc = new DocumentContainer(
  43. docId,
  44. this.socket,
  45. this.globalEditorWatchdogManager,
  46. this.events,
  47. this.eventLog,
  48. this.detachDoc.bind(this)
  49. )
  50. this.openDocs.set(docId, doc)
  51. }
  52. detachDoc(docId: string, doc: DocumentContainer) {
  53. if (this.openDocs.get(docId) === doc) {
  54. debugConsole.log(
  55. `[detach] Removing document with ID (${docId}) from openDocs`
  56. )
  57. this.openDocs.delete(docId)
  58. } else {
  59. // It's possible that this instance has error, and the doc has been reloaded.
  60. // This creates a new instance in Document.openDoc with the same id. We shouldn't
  61. // clear it because it's not this instance.
  62. debugConsole.log(
  63. `[_cleanUp] New instance of (${docId}) created. Not removing`
  64. )
  65. }
  66. }
  67. hasUnsavedChanges() {
  68. for (const doc of this.openDocs.values()) {
  69. if (doc.hasBufferedOps()) {
  70. return true
  71. }
  72. }
  73. return false
  74. }
  75. flushAll() {
  76. for (const doc of this.openDocs.values()) {
  77. doc.flush()
  78. }
  79. }
  80. unsavedDocIds() {
  81. const ids = []
  82. for (const [docId, doc] of this.openDocs) {
  83. if (!doc.pollSavedStatus()) {
  84. ids.push(docId)
  85. }
  86. }
  87. return ids
  88. }
  89. }