feat(frontend): 실시간 새 메일 · 바탕화면 알림 · 설정 › 알림

- 로그인한 동안 앱 전체에서 실시간 연결 — 브라우저마다 하나(Web Locks 잠금 + BroadcastChannel 로 다른 탭에 나눔), fetch 로 읽기,
  401 은 세션 갱신 한 번, 자리 잡은 뒤에만 다시 잇기 간격을 처음부터(열리자마자 끝나는 연결에서 갱신 폭주 막기), 탭을 닫으면 이어받기
- 메일 화면: 연결이 살아 있는 동안 1분 확인을 멈추고, 바뀌면 1초 모아 맞추기 · 숨은 탭은 탭 제목 (N) 만
- 바탕화면 알림: 웹메일을 보고 있지 않을 때만(보이고 초점이 있는 탭 없음), 한 통 · 여러 통 · 제목 숨김 문구, 누르면 그 메일로, 돌아오면 닫기
- 설정 › 메일 › 알림(허락 상태 · 제목 숨김 · 시험 알림 · 연결 상태)과 목록 위 한 번 권하기 줄, 알림 아이콘

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-28 13:32:09 +09:00
parent f725908053
commit 50165bd3b7
52 changed files with 5234 additions and 38 deletions
+9
View File
@@ -5,10 +5,19 @@ import { RouterView } from 'vue-router'
import SessionExpiredDialog from '@/components/feedback/SessionExpiredDialog.vue'
import ToastHost from '@/components/feedback/ToastHost.vue'
import { useClock } from '@/composables/useClock'
import { useLogoutSync } from '@/composables/useLogoutBroadcast'
import { useMailRealtime } from '@/composables/useMailRealtime'
import { useNewMailNotifier } from '@/composables/useNewMailNotifier'
// 다른 탭에서 로그아웃하면 이 탭도 로그인 화면으로 간다 (계약 1절 "클라이언트 처리 규칙")
useLogoutSync()
// 실시간 새 메일 — 로그인한 동안 앱 전체에서 돈다(설정 등 다른 화면에서도 바탕화면 알림 · 연결 상태가 이어지게).
// 메일 화면은 이 소식을 받아 목록 · 개수를 맞춘다 (계약 2절 "실시간 알림" — MailLayout 의 useMailStatePolling).
// 사용자가 웹메일 탭(어느 탭이든)으로 돌아오면 띄운 바탕화면 알림을 닫는다
const newMailNotifier = useNewMailNotifier()
useMailRealtime({ clock: useClock(), onNewMail: newMailNotifier.notify, onUserReturn: newMailNotifier.dismiss })
</script>
<template>