+
+
+ {{ failure?.message ?? '' }} +
+
+
+ {{ announcement }} +
+ + + diff --git a/frontend/src/components/mail/MessageReader.spec.ts b/frontend/src/components/mail/MessageReader.spec.ts index b94bd16..9ff6da6 100644 --- a/frontend/src/components/mail/MessageReader.spec.ts +++ b/frontend/src/components/mail/MessageReader.spec.ts @@ -636,8 +636,9 @@ describe('MessageReader 스팸 신고 · 원문 내려받기 (4단계 — 디자 await items[1]?.trigger('click') await flushPromises() - // 메뉴를 열 때 필터(50개인지) · 주소록(보낸 사람이 있는지 · 연락처 수)을 알림 없이 한 번 받아 본다 + // 읽기 화면은 열릴 때 같은 대화를 받는다(14단계). 메뉴를 열 때 필터(50개인지) · 주소록(보낸 사람이 있는지 · 연락처 수)을 알림 없이 한 번 받아 본다 expect(requests.map((request) => `${request.method} ${request.url}`)).toEqual([ + 'GET /messages/m1/conversation', 'GET /mail-filters', 'GET /contacts', 'GET /contacts', diff --git a/frontend/src/components/mail/MessageReader.vue b/frontend/src/components/mail/MessageReader.vue index dca0637..8148a58 100644 --- a/frontend/src/components/mail/MessageReader.vue +++ b/frontend/src/components/mail/MessageReader.vue @@ -15,6 +15,7 @@ // 대용량 첨부(11단계 — largeFiles)는 첨부 칸에 첨부처럼 보이고, 본문의 덩이는 접는다(본문 틀 안 — 스크립트 없이 열고 닫는다). // 검색 결과에서 연 메일(14단계)은 제목 · 본문 · 첨부 이름의 맞은 말이 노랑이다 — 서버의 searchHighlight(제목 · 첨부 이름 · 글 본문의 위치)와 // 서식 본문 안의 . 강조가 든 응답은 여기서 보이기만 한다 — [답장] · [전달] · 인쇄는 그 메일을 검색 쿼리 없이 따로 받는다 (계약 2절 "검색 — 14단계") +// 본문 · 첨부 아래에 "같은 대화 N통"(14단계 — MessageConversation, 한 통뿐이면 없다). 칸 안에는 검색 강조가 없다 import { computed, onBeforeUnmount, onMounted, ref } from 'vue' import AppIcon from '@/components/AppIcon.vue' @@ -25,13 +26,14 @@ import MailLoadError from '@/components/mail/MailLoadError.vue' import MailToolButton from '@/components/mail/MailToolButton.vue' import MailToolbarDivider from '@/components/mail/MailToolbarDivider.vue' import MessageAttachments from '@/components/mail/MessageAttachments.vue' +import MessageConversation from '@/components/mail/MessageConversation.vue' import MessageDeleteButton from '@/components/mail/MessageDeleteButton.vue' import MessageMoreMenu from '@/components/mail/MessageMoreMenu.vue' import MessageReaderNotices from '@/components/mail/MessageReaderNotices.vue' import MessageSpamButton from '@/components/mail/MessageSpamButton.vue' import { useMailNavigation } from '@/composables/useMailNavigation' import { useMailPrint } from '@/composables/useMailPrint' -import { MAIL_SEARCH_TEXT } from '@/shared/constants/mail' +import { MAIL_NO_SENDER, MAIL_SEARCH_TEXT } from '@/shared/constants/mail' import { formatMailDateTime, initialOf } from '@/shared/utils/format' import { displayName, formatAddressList } from '@/shared/utils/mail-address' import { listedAttachments } from '@/shared/utils/mail-attachment' @@ -67,7 +69,7 @@ const searchMailboxName = computed(() => { if (!mailStore.search || !message.value) return null return mailboxOfMessage(message.value, mailStore.mailboxes, mailStore.currentMailboxId)?.name ?? null }) -const fromName = computed(() => displayName(message.value?.from) || '(보낸 사람 없음)') +const fromName = computed(() => displayName(message.value?.from) || MAIL_NO_SENDER) const fromEmail = computed(() => message.value?.from?.email ?? '') const initial = computed(() => initialOf(message.value?.from?.name, fromEmail.value)) const subject = computed(() => message.value?.subject || '(제목 없음)') @@ -98,7 +100,7 @@ function onPrintKey(event: KeyboardEvent) { print.openPrint(current) } -/** 안내 줄의 단추가 줄과 함께 사라졌다 — 초점을 잃었으면 본문으로 */ +/** 안내 줄의 단추가 줄과 함께 사라졌다 · 초점이 있던 같은 대화 칸이 없어졌다(14단계) — 초점을 잃었으면 본문으로 */ function onNoticeSettled() { const active = document.activeElement if (active !== null && active !== document.body) return @@ -286,6 +288,13 @@ onBeforeUnmount(() => { :large-files="largeFiles" :name-highlights="message.searchHighlight?.attachments ?? null" /> + + +