diff --git a/frontend/package.json b/frontend/package.json
index 4f46436b..b899efda 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -9,6 +9,7 @@
"serve": "vite preview"
},
"dependencies": {
+ "@tiptap/extension-paragraph": "^2.4.0",
"@twilio/voice-sdk": "^2.10.2",
"@vueuse/core": "^10.3.0",
"@vueuse/integrations": "^10.3.0",
diff --git a/frontend/src/components/Activities.vue b/frontend/src/components/Activities.vue
index 3bf06991..8df55c2d 100644
--- a/frontend/src/components/Activities.vue
+++ b/frontend/src/components/Activities.vue
@@ -442,7 +442,7 @@
'outgoing_call',
].includes(activity.activity_type),
'bg-white': ['added', 'removed', 'changed'].includes(
- activity.activity_type
+ activity.activity_type,
),
}"
>
@@ -528,7 +528,10 @@
{{ activity.data.bcc }}
${message}` + editor.editor .chain() .clearContent() - .insertContent(message) + .insertContent('
.
') + .updateAttributes('paragraph', {class:'reply-to-content'}) + .insertContent(repliedMessage) .focus('all') - .setBlockquote() .insertContentAt(0, { type: 'paragraph' }) .focus('start') .run() diff --git a/frontend/src/components/EmailContent.vue b/frontend/src/components/EmailContent.vue index f68ea6b6..061dd7c1 100644 --- a/frontend/src/components/EmailContent.vue +++ b/frontend/src/components/EmailContent.vue @@ -6,7 +6,7 @@ style=" mask-image: linear-gradient( to bottom, - black calc(100% - 30px), + black calc(100% - 20px), transparent 100% ); " @@ -27,6 +27,90 @@ const files = import.meta.globEager('/src/index.css', { query: '?inline' }) const css = files['/src/index.css'].default const iframeRef = ref(null) +const _content = ref(props.content) + +const parser = new DOMParser() +const doc = parser.parseFromString(_content.value, 'text/html') + +const gmailReplyToContent = doc.querySelectorAll('div.gmail_quote') +const outlookReplyToContent = doc.querySelectorAll('div#appendonsend') +const replyToContent = doc.querySelectorAll('p.reply-to-content') + +if (gmailReplyToContent.length) { + _content.value = parseReplyToContent(doc, 'div.gmail_quote', true) +} else if (outlookReplyToContent.length) { + _content.value = parseReplyToContent(doc, 'div#appendonsend') +} else if (replyToContent.length) { + _content.value = parseReplyToContent(doc, 'p.reply-to-content') +} + +function parseReplyToContent(doc, selector, forGmail = false) { + function handleAllInstances(doc) { + const replyToContentElements = doc.querySelectorAll(selector) + if (replyToContentElements.length === 0) return + const replyToContentElement = replyToContentElements[0] + replaceReplyToContent(replyToContentElement, forGmail) + handleAllInstances(doc) + } + + handleAllInstances(doc) + + return doc.body.innerHTML +} + +function replaceReplyToContent(replyToContentElement, forGmail) { + if (!replyToContentElement) return + let randomId = Math.random().toString(36).substring(2, 7) + const wrapper = doc.createElement('div') + wrapper.classList.add('replied-content') + + const collapseLabel = doc.createElement('label') + collapseLabel.classList.add('collapse') + collapseLabel.setAttribute('for', randomId) + collapseLabel.innerHTML = '...' + wrapper.appendChild(collapseLabel) + + const collapseInput = doc.createElement('input') + collapseInput.setAttribute('id', randomId) + collapseInput.setAttribute('class', 'replyCollapser') + collapseInput.setAttribute('type', 'checkbox') + wrapper.appendChild(collapseInput) + + if (forGmail) { + const prevSibling = replyToContentElement.previousElementSibling + if (prevSibling && prevSibling.tagName === 'BR') { + prevSibling.remove() + } + let cloned = replyToContentElement.cloneNode(true) + cloned.classList.remove('gmail_quote') + wrapper.appendChild(cloned) + } else { + const allSiblings = Array.from(replyToContentElement.parentElement.children) + const replyToContentIndex = allSiblings.indexOf(replyToContentElement) + const followingSiblings = allSiblings.slice(replyToContentIndex + 1) + + if (followingSiblings.length === 0) return + + let clonedFollowingSiblings = followingSiblings.map((sibling) => + sibling.cloneNode(true), + ) + + const div = doc.createElement('div') + div.append(...clonedFollowingSiblings) + + wrapper.append(div) + + // Remove all siblings after the reply-to-content element + for (let i = replyToContentIndex + 1; i < allSiblings.length; i++) { + replyToContentElement.parentElement.removeChild(allSiblings[i]) + } + } + + replyToContentElement.parentElement.replaceChild( + wrapper, + replyToContentElement, + ) +} const htmlContent = ` @@ -35,6 +119,35 @@ const htmlContent = ` -