1 import type { LoggerInterface } from '@proton/utils/logs'
2 import type { InternalEventBusInterface } from '@proton/docs-shared'
3 import { EditorOrchestrator } from '../Orchestrator/EditorOrchestrator'
4 import type { LoadDocument } from '../../UseCase/LoadDocument'
5 import type { GetDocumentMeta } from '../../UseCase/GetDocumentMeta'
6 import type { PublicDriveCompat, PublicNodeMeta } from '@proton/drive-store'
7 import type { DocLoaderInterface } from './DocLoaderInterface'
8 import type { EditorOrchestratorInterface } from '../Orchestrator/EditorOrchestratorInterface'
9 import type { LoadCommit } from '../../UseCase/LoadCommit'
10 import type { ExportAndDownload } from '../../UseCase/ExportAndDownload'
11 import type { DocsApi } from '../../Api/DocsApi'
12 import type { PublicDocControllerInterface } from '../../Controller/Document/PublicDocControllerInterface'
13 import { PublicDocController } from '../../Controller/Document/PublicDocController'
15 export type StatusObserver = {
16 onSuccess: (orchestrator: EditorOrchestratorInterface) => void
17 onError: (error: string) => void
20 export class PublicDocLoader implements DocLoaderInterface {
21 private publicDocController?: PublicDocControllerInterface
22 private orchestrator?: EditorOrchestratorInterface
23 private readonly statusObservers: StatusObserver[] = []
26 private driveCompat: PublicDriveCompat,
27 private docsApi: DocsApi,
28 private loadDocument: LoadDocument,
29 private loadCommit: LoadCommit,
30 private getDocumentMeta: GetDocumentMeta,
31 private exportAndDownload: ExportAndDownload,
32 private eventBus: InternalEventBusInterface,
33 private logger: LoggerInterface,
37 this.publicDocController?.destroy()
40 public async initialize(nodeMeta: PublicNodeMeta): Promise<void> {
41 if (this.publicDocController) {
42 throw new Error('[PublicDocLoader] docController already initialized')
45 this.publicDocController = new PublicDocController(
50 this.exportAndDownload,
55 const result = await this.publicDocController.initialize()
57 if (result.isFailed()) {
58 this.statusObservers.forEach((observer) => {
59 observer.onError(result.getError())
64 const { entitlements, meta } = result.getValue()
66 if (entitlements.role.isPublicViewerWithAccess()) {
67 this.logger.info('Redirecting to authed document')
68 this.driveCompat.redirectToAuthedDocument(meta.nodeMeta)
72 this.orchestrator = new EditorOrchestrator(undefined, this.publicDocController, this.docsApi, this.eventBus)
74 this.statusObservers.forEach((observer) => {
75 if (this.orchestrator) {
76 observer.onSuccess(this.orchestrator)
81 public getDocController(): PublicDocControllerInterface {
82 if (!this.publicDocController) {
83 throw new Error('DocController not ready')
86 return this.publicDocController
89 public addStatusObserver(observer: StatusObserver): () => void {
90 this.statusObservers.push(observer)
92 if (this.orchestrator) {
93 observer.onSuccess(this.orchestrator)
97 this.statusObservers.splice(this.statusObservers.indexOf(observer), 1)