1 import { Comment } from '../Models'
2 import { GenerateUUID } from '../Util/GenerateUuid'
3 import type { DocumentEntitlements, PublicDocumentEntitlements } from '../Types/DocumentEntitlements'
4 import { isPrivateDocumentKeys } from '../Types/DocumentEntitlements'
5 import { Result } from '@proton/docs-shared'
6 import { ServerTime } from '@proton/docs-shared'
7 import metrics from '@proton/metrics'
8 import type { CommentInterface, CommentType } from '@proton/docs-shared'
9 import type { DocsApi } from '../Api/DocsApi'
10 import type { EncryptComment } from './EncryptComment'
11 import type { LocalCommentsState } from '../Services/Comments/LocalCommentsState'
12 import type { UseCaseInterface } from '../Domain/UseCase/UseCaseInterface'
15 * Creates and encrypts a new comment in a thread with the API.
17 export class CreateComment implements UseCaseInterface<CommentInterface> {
20 private encryptComment: EncryptComment,
26 entitlements: PublicDocumentEntitlements | DocumentEntitlements
27 commentsState: LocalCommentsState
29 decryptedDocumentName: string | null
30 }): Promise<Result<CommentInterface>> {
31 const thread = dto.commentsState.findThreadById(dto.threadID)
33 return Result.fail('Thread not found')
36 const localComment = new Comment(
42 isPrivateDocumentKeys(dto.entitlements.keys) ? dto.entitlements.keys.userOwnAddress : undefined,
48 dto.commentsState.addComment(localComment, dto.threadID)
50 const encryptionResult = await this.encryptComment.execute(dto.text, thread.markID, dto.entitlements.keys)
52 if (encryptionResult.isFailed()) {
53 dto.commentsState.deleteComment({ commentID: localComment.id, threadID: dto.threadID })
54 return Result.fail(encryptionResult.getError())
57 const encryptedValue = encryptionResult.getValue()
59 const result = await this.api.addCommentToThread(
61 threadId: dto.threadID,
62 encryptedContent: encryptedValue,
63 parentCommentId: null,
65 decryptedDocumentName: dto.decryptedDocumentName,
70 if (result.isFailed()) {
71 metrics.docs_comments_error_total.increment({
72 reason: 'server_error',
75 dto.commentsState.deleteComment({ commentID: localComment.id, threadID: dto.threadID })
76 return Result.fail(result.getError().message)
79 const { Comment: commentFromResponse } = result.getValue()
81 const emailToUse = commentFromResponse.AuthorEmail || commentFromResponse.Author
83 const comment = new Comment(
84 commentFromResponse.CommentID,
85 new ServerTime(commentFromResponse.CreateTime),
86 new ServerTime(commentFromResponse.ModifyTime),
88 commentFromResponse.ParentCommentID,
92 commentFromResponse.Type,
94 dto.commentsState.replacePlaceholderComment(localComment.id, comment)
96 return Result.ok(comment)