/** * 모든 화면에서 서비스 종료 일정과 브라우저별 7일 숨김 선택을 안내한다. */ (function initServiceNotice() { const STORAGE_KEY = 'uniare.serviceNotice.hiddenUntil'; const HIDE_DURATION_MS = 7 * 24 * 60 * 60 * 1000; const SUPPORTED_LANGUAGES = new Set(['ko', 'ja', 'en']); /** * URL, 브라우저 저장값 순으로 안내 언어를 선택한다. * @returns {string} 지원 언어 코드 */ function getLanguage() { const fromQuery = new URLSearchParams(window.location.search).get('lang'); let selected = fromQuery; if (!selected) { try { selected = localStorage.getItem('lang'); } catch { selected = 'ko'; } } return SUPPORTED_LANGUAGES.has(selected) ? selected : 'ko'; } /** * 저장소가 차단되었거나 만료값이 유효하지 않으면 안내를 표시한다. * @returns {boolean} 7일 숨김 기간이 남아 있는지 여부 */ function isHidden() { try { const hiddenUntil = Number(localStorage.getItem(STORAGE_KEY)); return Number.isFinite(hiddenUntil) && hiddenUntil > Date.now(); } catch { return false; } } /** * 페이지 번역과 같은 키를 사용하고, 로딩 실패 시 한국어 안내를 유지한다. * @param {HTMLDialogElement} dialog 안내 모달 * @returns {Promise} */ async function translateNotice(dialog) { try { const response = await fetch(`/i18n/translations.${getLanguage()}.json?v=4.0.29`); if (!response.ok) return; const translations = await response.json(); dialog.querySelectorAll('[data-i18n]').forEach((element) => { const translated = translations[element.dataset.i18n]; if (typeof translated === 'string') element.textContent = translated; }); } catch { // 번역 요청 실패가 종료 안내 표시나 닫기를 막지 않도록 한다. } } /** * 네이티브 모달로 배경 접근을 막고 키보드 포커스와 Escape 닫기를 제공한다. */ function showNotice() { if (isHidden() || document.getElementById('service-notice')) return; const dialog = document.createElement('dialog'); dialog.id = 'service-notice'; dialog.setAttribute('aria-labelledby', 'service-notice-title'); dialog.setAttribute('aria-describedby', 'service-notice-description service-notice-date service-notice-backup'); dialog.className = 'm-auto max-h-[calc(100dvh-2rem)] w-[calc(100%-2rem)] max-w-lg overflow-y-auto break-keep [overflow-wrap:break-word] rounded-2xl border border-slate-100 bg-white p-0 text-slate-700 shadow-xl shadow-slate-900/10 backdrop:bg-slate-900/25 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-200'; dialog.style.fontFamily = 'Pretendard, "Noto Sans KR", sans-serif'; dialog.innerHTML = `

서비스 운영 종료 안내

그동안 UNIARE를 이용해 주셔서 진심으로 감사합니다.

서비스 운영 방향과 제반 여건을 종합적으로 검토한 결과, 서비스 운영을 종료하게 되었습니다.

서비스 운영 마지막 날

보관하고 싶은 덱은 종료 전에 덱 결과 화면에서 PNG 이미지로 다운로드해 주세요.

마지막까지 이용에 불편이 없도록 최선을 다하겠습니다. 그동안 함께해 주신 모든 분께 감사드립니다.

`; const previousOverflow = document.documentElement.style.overflow; const hideWeek = dialog.querySelector('#service-notice-hide-week'); dialog.querySelector('#service-notice-confirm').addEventListener('click', () => dialog.close()); dialog.addEventListener('close', () => { if (hideWeek.checked) { try { localStorage.setItem(STORAGE_KEY, String(Date.now() + HIDE_DURATION_MS)); } catch { // 저장소를 사용할 수 없어도 현재 화면의 안내는 정상적으로 닫는다. } } document.documentElement.style.overflow = previousOverflow; dialog.remove(); }, { once: true }); document.body.appendChild(dialog); dialog.showModal(); document.documentElement.style.overflow = 'hidden'; translateNotice(dialog); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', showNotice, { once: true }); } else { showNotice(); } })();