refactor(popup): 5종 팝업 _i18n 주입 + 색상 토큰화 (WS-POPUP)
- 4종 팝업(command/history/result/recording-tip) _i18n 주입: WindowManager getPopupI18nStrings() + 팝업 script applyI18nToHtml() - 한국어/영어 하드코딩 -> popup.* i18n 키 (ko/en 17키) - theme-vars.ts에 --d3-wave-1~9, --d3-status-error/success 토큰 추가 (6 테마) - 팝업 style.css hex -> CSS var 토큰 - packages/i18n getI18n() (main 프로세스용) 추가 SKIP: caption-overlay _i18n(별도 IPC 구조), wave box-shadow 보간(opacity 단순화) 정책: docs/REFACTOR_POLICY.md DP3, 이식 인사이트 P5
This commit is contained in:
parent
660e622a93
commit
00a99e4087
15 changed files with 256 additions and 35 deletions
|
|
@ -10,6 +10,7 @@ import { getLogger } from '../services/LoggerService'
|
|||
import { getIsQuitting } from '../lifecycle'
|
||||
import { configGet } from '../services/ConfigService'
|
||||
import { buildPopupThemeCss } from '@d3ro/ui/theme-vars'
|
||||
import { getI18n } from '@d3ro/i18n'
|
||||
|
||||
const logger = getLogger('WindowManager')
|
||||
|
||||
|
|
@ -28,6 +29,39 @@ function injectPopupTheme(win: BrowserWindow): void {
|
|||
})
|
||||
}
|
||||
|
||||
// ── 팝업 i18n 문자열 가져오기 ─────────────────────────────
|
||||
/**
|
||||
* 팝업에 주입할 i18n 문자열 맵을 반환.
|
||||
*/
|
||||
function getPopupI18nStrings(): Record<string, string> {
|
||||
const locale = (configGet('language') as string) || 'ko'
|
||||
const { t } = getI18n(locale as 'ko' | 'en' | 'ja' | 'zh' | 'zh-TW' | 'es' | 'fr' | 'de' | 'pt' | 'ru' | 'vi' | 'th')
|
||||
return {
|
||||
// command-popup
|
||||
commandSelect: t('popup.commandSelect'),
|
||||
hintsSelect: t('popup.hints.select'),
|
||||
hintsApply: t('popup.hints.apply'),
|
||||
hintsClear: t('popup.hints.clear'),
|
||||
hintsClose: t('popup.hints.close'),
|
||||
noCommands: t('popup.noCommands'),
|
||||
noCommand: t('popup.noCommand'),
|
||||
// history-popup
|
||||
hintsSelectEn: t('popup.hints.selectEn'),
|
||||
hintsPaste: t('popup.hints.paste'),
|
||||
noHistory: t('popup.noHistory'),
|
||||
timeJustNow: t('popup.time.justNow'),
|
||||
timeMinutesAgo: t('popup.time.minutesAgo'),
|
||||
timeHoursAgo: t('popup.time.hoursAgo'),
|
||||
timeDaysAgo: t('popup.time.daysAgo'),
|
||||
// result-popup
|
||||
copy: t('popup.copy'),
|
||||
// recording-tip
|
||||
errorDefault: t('popup.error.default'),
|
||||
// caption-overlay
|
||||
captionLoading: t('popup.caption.loading'),
|
||||
}
|
||||
}
|
||||
|
||||
// ── 윈도우 참조 ───────────────────────────────────────
|
||||
|
||||
let mainWindow: BrowserWindow | null = null
|
||||
|
|
@ -181,7 +215,7 @@ export function showRecordingTip(
|
|||
win.setBounds({ x, y, width: TIP_WIDTH, height: TIP_HEIGHT })
|
||||
|
||||
// 상태 전송 후 즉시 show (2-phase 제거 — 숨겨진 윈도우의 렌더러 비활성 문제 방지)
|
||||
win.webContents.send(IPC_CHANNELS.WINDOW.TIP_STATE_CHANGED, { state, ...params })
|
||||
win.webContents.send(IPC_CHANNELS.WINDOW.TIP_STATE_CHANGED, { state, _i18n: getPopupI18nStrings(), ...params })
|
||||
if (!win.isVisible()) {
|
||||
win.showInactive()
|
||||
}
|
||||
|
|
@ -198,7 +232,7 @@ export function updateRecordingTipState(
|
|||
params?: { text?: string; errorMessage?: string }
|
||||
): void {
|
||||
if (recordingTipWindow && !recordingTipWindow.isDestroyed()) {
|
||||
recordingTipWindow.webContents.send(IPC_CHANNELS.WINDOW.TIP_STATE_CHANGED, { state, ...params })
|
||||
recordingTipWindow.webContents.send(IPC_CHANNELS.WINDOW.TIP_STATE_CHANGED, { state, _i18n: getPopupI18nStrings(), ...params })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -268,7 +302,7 @@ export function showResultPopup(text: string, autoHideMs = 5000): void {
|
|||
const win = getResultPopupWindow()
|
||||
|
||||
// Phase 1: prepare
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_RESULT.PREPARE, { text })
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_RESULT.PREPARE, { text, _i18n: getPopupI18nStrings() })
|
||||
|
||||
const handler = (_event: Electron.IpcMainEvent, data: { width: number; height: number }) => {
|
||||
ipcMain.removeListener(IPC_CHANNELS.POPUP_RESULT.MEASURED, handler)
|
||||
|
|
@ -369,7 +403,7 @@ export function showHistoryPopup(entries: Array<Record<string, unknown>>): void
|
|||
|
||||
win.setBounds({ x, y, width: popupWidth, height: popupHeight })
|
||||
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_HISTORY.SHOW_ITEMS, { entries })
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_HISTORY.SHOW_ITEMS, { entries, _i18n: getPopupI18nStrings() })
|
||||
|
||||
if (!win.isVisible()) {
|
||||
win.showInactive()
|
||||
|
|
@ -456,7 +490,7 @@ export function showCommandPopup(commands: Array<Record<string, unknown>>, activ
|
|||
if (y < display.workArea.y) { y = cursorPos.y + 20 }
|
||||
|
||||
win.setBounds({ x, y, width: popupWidth, height: popupHeight })
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_COMMAND.SHOW_ITEMS, { commands, activeId })
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_COMMAND.SHOW_ITEMS, { commands, activeId, _i18n: getPopupI18nStrings() })
|
||||
|
||||
if (!win.isVisible()) { win.showInactive() }
|
||||
win.webContents.send(IPC_CHANNELS.POPUP_COMMAND.SHOW, {})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue