실시간 UI 갱신: 세션 완료/명령어 변경 시 렌더러 자동 리로드
- bootstrap: notifyRenderer('app:dataChanged') 이벤트 발행
- session-completed: Dashboard 통계 + History 갱신
- command:selected: CMD 페이지 활성 명령어 갱신
- preload: app.onDataChanged 이벤트 리스너 추가
- DashboardPage/CommandsPage/HistoryPage: onDataChanged 구독하여 자동 loadData()
This commit is contained in:
parent
1361b95a4d
commit
ea48168b1e
5 changed files with 39 additions and 3 deletions
|
|
@ -15,6 +15,7 @@ import { getAutoLaunchService } from './services/AutoLaunchService'
|
||||||
import { initDatabase } from './db'
|
import { initDatabase } from './db'
|
||||||
import {
|
import {
|
||||||
createMainWindow,
|
createMainWindow,
|
||||||
|
getMainWindow,
|
||||||
preloadPopupWindows,
|
preloadPopupWindows,
|
||||||
showHistoryPopup,
|
showHistoryPopup,
|
||||||
hideHistoryPopup,
|
hideHistoryPopup,
|
||||||
|
|
@ -213,6 +214,9 @@ async function initVoiceMode(): Promise<void> {
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.warn(`Failed to save history: ${error instanceof Error ? error.message : String(error)}`)
|
logger.warn(`Failed to save history: ${error instanceof Error ? error.message : String(error)}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 렌더러 UI 갱신 알림 (Dashboard 통계 + History 목록)
|
||||||
|
notifyRenderer('app:dataChanged', { type: 'session-completed' })
|
||||||
})
|
})
|
||||||
|
|
||||||
voiceMode.on('session-cancelled', ({ reason }) => {
|
voiceMode.on('session-cancelled', ({ reason }) => {
|
||||||
|
|
@ -229,6 +233,14 @@ async function initVoiceMode(): Promise<void> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 메인 윈도우 렌더러에 UI 갱신 이벤트 전송 */
|
||||||
|
function notifyRenderer(channel: string, data?: Record<string, unknown>): void {
|
||||||
|
const win = getMainWindow()
|
||||||
|
if (win && !win.isDestroyed()) {
|
||||||
|
win.webContents.send(channel, data ?? {})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function initLLMPolling(): Promise<void> {
|
async function initLLMPolling(): Promise<void> {
|
||||||
const llm = getLocalLLMService()
|
const llm = getLocalLLMService()
|
||||||
llm.startPolling()
|
llm.startPolling()
|
||||||
|
|
@ -275,6 +287,9 @@ function setupCommandPopupIPC(): void {
|
||||||
configSet('activeInstructionId' as keyof import('@shared/types').AppConfig, data.id as never)
|
configSet('activeInstructionId' as keyof import('@shared/types').AppConfig, data.id as never)
|
||||||
configSet('defaultLLMAction', 'custom')
|
configSet('defaultLLMAction', 'custom')
|
||||||
logger.info(`Active command set: ${data.name} (${data.id})`)
|
logger.info(`Active command set: ${data.name} (${data.id})`)
|
||||||
|
|
||||||
|
// CMD 페이지 UI 갱신 알림
|
||||||
|
notifyRenderer('app:dataChanged', { type: 'command-changed', activeId: data.id })
|
||||||
})
|
})
|
||||||
|
|
||||||
// 팝업 닫기
|
// 팝업 닫기
|
||||||
|
|
|
||||||
|
|
@ -243,6 +243,12 @@ const electronAPI = {
|
||||||
invoke<unknown>('instruction:update', params),
|
invoke<unknown>('instruction:update', params),
|
||||||
delete: (params: { id: string }) => invoke<void>('instruction:delete', params),
|
delete: (params: { id: string }) => invoke<void>('instruction:delete', params),
|
||||||
reorder: (params: { ids: string[] }) => invoke<void>('instruction:reorder', params),
|
reorder: (params: { ids: string[] }) => invoke<void>('instruction:reorder', params),
|
||||||
|
},
|
||||||
|
|
||||||
|
// ── App 이벤트 (실시간 UI 갱신) ────────────────────────
|
||||||
|
app: {
|
||||||
|
onDataChanged: (cb: (data: { type: string; activeId?: string }) => void): Unsubscribe =>
|
||||||
|
on('app:dataChanged', cb),
|
||||||
}
|
}
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,16 @@ export function CommandsPage(): React.ReactElement {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => { loadData() }, [loadData])
|
useEffect(() => {
|
||||||
|
loadData()
|
||||||
|
const unsub = window.electronAPI.app.onDataChanged((data) => {
|
||||||
|
if (data.type === 'command-changed' && data.activeId) {
|
||||||
|
setActiveId(data.activeId)
|
||||||
|
}
|
||||||
|
loadData()
|
||||||
|
})
|
||||||
|
return unsub
|
||||||
|
}, [loadData])
|
||||||
|
|
||||||
const handleActivate = (id: string) => {
|
const handleActivate = (id: string) => {
|
||||||
const newId = activeId === id ? null : id // 토글: 같은 거 누르면 해제
|
const newId = activeId === id ? null : id // 토글: 같은 거 누르면 해제
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,9 @@ export function DashboardPage(): React.ReactElement {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
loadData()
|
loadData()
|
||||||
const interval = setInterval(loadData, 30000)
|
const interval = setInterval(loadData, 30000)
|
||||||
return () => clearInterval(interval)
|
// 실시간 갱신: 세션 완료/명령어 변경 시 즉시 리로드
|
||||||
|
const unsub = window.electronAPI.app.onDataChanged(() => { loadData() })
|
||||||
|
return () => { clearInterval(interval); unsub() }
|
||||||
}, [loadData])
|
}, [loadData])
|
||||||
|
|
||||||
// 날짜별 그룹핑
|
// 날짜별 그룹핑
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,11 @@ export function HistoryPage(): React.ReactElement {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}, [search])
|
}, [search])
|
||||||
|
|
||||||
useEffect(() => { loadData() }, [loadData])
|
useEffect(() => {
|
||||||
|
loadData()
|
||||||
|
const unsub = window.electronAPI.app.onDataChanged(() => { loadData() })
|
||||||
|
return unsub
|
||||||
|
}, [loadData])
|
||||||
|
|
||||||
// 날짜별 그룹핑
|
// 날짜별 그룹핑
|
||||||
const groupedEntries = useMemo(() => {
|
const groupedEntries = useMemo(() => {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue