diff --git a/app/javascript/dashboard/components-next/message/Message.vue b/app/javascript/dashboard/components-next/message/Message.vue index 63a779a7a..ce118c620 100644 --- a/app/javascript/dashboard/components-next/message/Message.vue +++ b/app/javascript/dashboard/components-next/message/Message.vue @@ -1,5 +1,5 @@ - - diff --git a/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue b/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue index 2db89cf11..31b5e6bac 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Email/EmailMeta.vue @@ -62,18 +62,15 @@ const showMeta = computed(() => { subject.value ); }); - -defineExpose({ - showMeta, -}); diff --git a/app/javascript/dashboard/components-next/message/bubbles/Email/Index.vue b/app/javascript/dashboard/components-next/message/bubbles/Email/Index.vue index b9b039e18..7d1912039 100644 --- a/app/javascript/dashboard/components-next/message/bubbles/Email/Index.vue +++ b/app/javascript/dashboard/components-next/message/bubbles/Email/Index.vue @@ -9,10 +9,9 @@ import { } from 'vue'; import { Letter } from 'vue-letter'; import { allowedCssProperties } from 'lettersanitizer'; -import { useScrollLock, useToggle } from '@vueuse/core'; +import { useScrollLock, useWindowSize, useToggle } from '@vueuse/core'; import Icon from 'next/icon/Icon.vue'; -import MessageMenu from 'dashboard/components-next/message/MessageMenu.vue'; import { EmailQuoteExtractor } from './removeReply.js'; import BaseBubble from 'next/message/bubbles/Base.vue'; import FormattedContent from 'next/message/bubbles/Text/FormattedContent.vue'; @@ -23,10 +22,11 @@ import ForwardMessageForm from 'dashboard/components-next/message/forwardMessage import { useMessageContext } from '../../provider.js'; import { useInbox } from 'dashboard/composables/useInbox'; -import { MESSAGE_TYPES, MESSAGE_STATUS } from 'next/message/constants.js'; +import { MESSAGE_TYPES } from 'next/message/constants.js'; import { useTranslations } from 'dashboard/composables/useTranslations'; +import { calculatePosition } from 'dashboard/helper/position.js'; -const { id, status, content, contentAttributes, attachments, messageType } = +const { id, content, contentAttributes, attachments, messageType } = useMessageContext(); const { inbox } = useInbox(); @@ -36,12 +36,12 @@ const isExpanded = ref(false); const showQuotedMessage = ref(false); const renderOriginal = ref(false); const contentContainer = useTemplateRef('contentContainer'); -const emailMeta = useTemplateRef('emailMeta'); -// Forward form +// Forward form - managed locally but can be triggered by parent const [showForwardMessageModal, toggleForwardModal] = useToggle(); const forwardFormPosition = reactive({ top: 0, right: 0 }); const conversationPanelScrollLock = ref(null); +const { width: windowWidth, height: windowHeight } = useWindowSize(); onMounted(() => { isExpandable.value = contentContainer.value?.scrollHeight > 400; @@ -52,12 +52,6 @@ const isIncoming = computed(() => !isOutgoing.value); const isForwarded = computed(() => contentAttributes.value?.forwardedMessageId); -const showMessageMenu = computed( - () => ![MESSAGE_STATUS.FAILED, MESSAGE_STATUS.PROGRESS].includes(status.value) -); - -const showMeta = computed(() => emailMeta.value?.showMeta); - const { hasTranslations, translationContent } = useTranslations(contentAttributes); @@ -126,16 +120,36 @@ const closeForwardModal = () => { conversationPanelScrollLock.value.value = false; }; -const openForwardModal = event => { +const openForwardModal = (event = null) => { // Lock conversation panel scroll // To prevent the conversation from scrolling when the forward form is opened const panel = document.querySelector('.conversation-panel'); if (panel) conversationPanelScrollLock.value = useScrollLock(panel, true); - // Set position from event - if (event?.target) { - const buttonRect = event.target.getBoundingClientRect(); - forwardFormPosition.top = buttonRect.top - 9; - forwardFormPosition.right = window.innerWidth - buttonRect.right - 9; + + // Form dimensions + const [formWidth, formHeight] = [672, 500]; + const { value: winWidth } = windowWidth; + const { value: winHeight } = windowHeight; + + // Position calculation + const rect = event?.target?.getBoundingClientRect?.(); + if (rect) { + // Calculate position based on click location of context menu forward button + const { left, top } = calculatePosition( + rect.left, + rect.top, + formWidth, + formHeight, + winWidth, + winHeight + ); + + forwardFormPosition.top = top; + forwardFormPosition.right = winWidth - left - formWidth; + } else { + // Center the form when no trigger event + forwardFormPosition.top = Math.max(0, (winHeight - formHeight) / 2); + forwardFormPosition.right = Math.max(0, (winWidth - formWidth) / 2); } toggleForwardModal(true); @@ -145,6 +159,11 @@ onUnmounted(() => { if (conversationPanelScrollLock.value) conversationPanelScrollLock.value.value = false; }); + +defineExpose({ + openForwardModal, + closeForwardModal, +}); diff --git a/app/javascript/dashboard/components-next/message/forwardMessage/components/ForwardMessageForm.vue b/app/javascript/dashboard/components-next/message/forwardMessage/components/ForwardMessageForm.vue index 52577e93d..b3b591839 100644 --- a/app/javascript/dashboard/components-next/message/forwardMessage/components/ForwardMessageForm.vue +++ b/app/javascript/dashboard/components-next/message/forwardMessage/components/ForwardMessageForm.vue @@ -130,9 +130,11 @@ const handleSendMessage = async () => {