feat: complete release preparation, 10+ ad mediation, CI/CD, and docker deployment
Some checks failed
CI Pipeline / Code Quality & Typecheck (push) Waiting to run
CI Pipeline / Test Suite (macos-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (ubuntu-latest) (push) Blocked by required conditions
CI Pipeline / Test Suite (windows-latest) (push) Blocked by required conditions
CI Pipeline / Build Validation (admin) (push) Blocked by required conditions
CI Pipeline / Build Validation (desktop) (push) Blocked by required conditions
Deploy Landing Page / deploy (push) Blocked by required conditions
Deploy Landing Page / build (push) Waiting to run
Release & Packaging Pipeline / Build & Publish Admin Docker Image (push) Failing after 8s
Release & Code Signing CA Pipeline / build-and-sign-windows (push) Failing after 1m51s
Build macOS / Build & Package (macOS) (push) Failing after 4s
Build macOS / Build & Package (macOS)-1 (push) Failing after 5s
Release & Code Signing CA Pipeline / build-and-sign-macos (push) Failing after 3s
Release & Packaging Pipeline / Package macOS Desktop App (push) Failing after 4s
Release & Packaging Pipeline / Package Windows Desktop App (push) Failing after 2m28s
Release & Packaging Pipeline / Publish Official GitHub Release (push) Has been skipped

This commit is contained in:
Yun Chan 2026-08-20 11:12:05 +09:00
parent 5cd1de6859
commit 708e20f747
406 changed files with 42464 additions and 6199 deletions

View file

@ -78,16 +78,23 @@ export function getMainWindow(): BrowserWindow | null {
}
export function createMainWindow(): BrowserWindow {
const primaryDisplay = screen.getPrimaryDisplay()
const { width: screenWidth, height: screenHeight } = primaryDisplay.workAreaSize
const initWidth = Math.min(WINDOW_SIZE.MAIN.width, screenWidth)
const initHeight = Math.min(WINDOW_SIZE.MAIN.height, screenHeight)
mainWindow = new BrowserWindow({
width: WINDOW_SIZE.MAIN.width,
height: WINDOW_SIZE.MAIN.height,
title: 'D3RO Voice',
width: initWidth,
height: initHeight,
x: Math.max(0, Math.round((screenWidth - initWidth) / 2)),
y: Math.max(0, Math.round((screenHeight - initHeight) / 2)),
minWidth: 800,
minHeight: 600,
show: false,
show: true,
autoHideMenuBar: true,
// v2 보더리스 UI — 렌더러 TitleBar가 드래그/컨트롤 담당
frame: false,
// 첫 페인트 전 플래시 방지 (렌더러 테마 로드 전 임시 배경 — Midnight bg.app)
frame: true,
backgroundColor: '#0a0e1c',
webPreferences: {
preload: join(__dirname, '../preload/index.js'),
@ -97,14 +104,19 @@ export function createMainWindow(): BrowserWindow {
}
})
mainWindow.setSkipTaskbar(false)
// Alt 키로 메뉴 활성화 방지: 메뉴 완전 제거
mainWindow.setMenu(null)
Menu.setApplicationMenu(null)
mainWindow.on('ready-to-show', () => {
mainWindow?.show()
if (is.dev) {
mainWindow?.webContents.openDevTools({ mode: 'detach' })
mainWindow?.restore()
mainWindow?.focus()
mainWindow?.flashFrame(true)
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow?.webContents.openDevTools({ mode: 'right' })
}
logger.info('Main window shown')
})
@ -121,6 +133,10 @@ export function createMainWindow(): BrowserWindow {
mainWindow = null
})
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
logger.info(`[Renderer] [${level}] ${message} (${sourceId}:${line})`)
})
mainWindow.webContents.setWindowOpenHandler((details) => {
shell.openExternal(details.url)
return { action: 'deny' }
@ -132,6 +148,19 @@ export function createMainWindow(): BrowserWindow {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
mainWindow.center()
mainWindow.restore()
mainWindow.show()
mainWindow.focus()
mainWindow.setAlwaysOnTop(true)
setTimeout(() => {
try {
mainWindow?.setAlwaysOnTop(false)
} catch {
// ignore
}
}, 1000)
logger.info('Main window created')
return mainWindow
}
@ -211,6 +240,9 @@ export function showRecordingTip(
if (y < display.workArea.y) {
y = cursorPos.y + 20
}
if (y + TIP_HEIGHT > display.workArea.y + display.workArea.height) {
y = Math.max(display.workArea.y, display.workArea.y + display.workArea.height - TIP_HEIGHT)
}
win.setBounds({ x, y, width: TIP_WIDTH, height: TIP_HEIGHT })
@ -304,9 +336,7 @@ export function showResultPopup(text: string, autoHideMs = 5000): void {
// Phase 1: prepare
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)
ipcMain.once(IPC_CHANNELS.POPUP_RESULT.MEASURED, (_event, data: { width: number; height: number }) => {
const cursorPos = screen.getCursorScreenPoint()
const display = screen.getDisplayNearestPoint(cursorPos)
@ -317,6 +347,9 @@ export function showResultPopup(text: string, autoHideMs = 5000): void {
if (y < display.workArea.y) {
y = cursorPos.y + 20
}
if (y + data.height > display.workArea.y + display.workArea.height) {
y = Math.max(display.workArea.y, display.workArea.y + display.workArea.height - data.height)
}
win.setBounds({ x, y, width: data.width, height: data.height })
@ -326,9 +359,7 @@ export function showResultPopup(text: string, autoHideMs = 5000): void {
// Phase 2: show
win.webContents.send(IPC_CHANNELS.POPUP_RESULT.SHOW, { autoHideMs })
}
ipcMain.on(IPC_CHANNELS.POPUP_RESULT.MEASURED, handler)
})
}
export function hideResultPopup(): void {