mirror of
https://github.com/jung-geun/NFD2NFC.git
synced 2026-06-21 12:25:14 +09:00
src/main: 트레이/감시자/저장소/IPC/알림 배치 (Electron 메인)
tray.ts: 트레이 아이콘, 팝오버 BrowserWindow 토글, 컨텍스트 메뉴. watcher.ts: chokidar 감시, dedup TTL 2s, auto/manual 모드, 글로벌 일시정지. store.ts: userData/store.json 영속화 (watchedDirs/settings/undoLog). ipc.ts: 18개 IPC 채널 핸들러. notifier.ts: interval 기반 알림 배치 처리 (알림 폭주 방지). settings-window.ts: 설정창 BrowserWindow 라이프사이클. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
94
src/main/store.ts
Normal file
94
src/main/store.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { app } from 'electron';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import type { AppSchema, AppSettings, WatchedDir, UndoEntry } from '../core/types';
|
||||
|
||||
const STORE_PATH = path.join(app.getPath('userData'), 'store.json');
|
||||
const MAX_UNDO_LOG = 1000;
|
||||
|
||||
const DEFAULT_SETTINGS: AppSettings = {
|
||||
startAtLogin: false,
|
||||
defaultMode: 'auto',
|
||||
notificationsEnabled: true,
|
||||
};
|
||||
|
||||
const DEFAULT_SCHEMA: AppSchema = {
|
||||
watchedDirs: [],
|
||||
settings: DEFAULT_SETTINGS,
|
||||
undoLog: [],
|
||||
};
|
||||
|
||||
let cache: AppSchema | null = null;
|
||||
|
||||
async function load(): Promise<AppSchema> {
|
||||
if (cache) return cache;
|
||||
try {
|
||||
const raw = await fs.readFile(STORE_PATH, 'utf-8');
|
||||
cache = { ...DEFAULT_SCHEMA, ...JSON.parse(raw) };
|
||||
} catch {
|
||||
cache = structuredClone(DEFAULT_SCHEMA);
|
||||
}
|
||||
return cache!;
|
||||
}
|
||||
|
||||
async function save(): Promise<void> {
|
||||
if (!cache) return;
|
||||
await fs.mkdir(path.dirname(STORE_PATH), { recursive: true });
|
||||
await fs.writeFile(STORE_PATH, JSON.stringify(cache, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
export async function getDirs(): Promise<WatchedDir[]> {
|
||||
return (await load()).watchedDirs;
|
||||
}
|
||||
|
||||
export async function addDir(dir: WatchedDir): Promise<void> {
|
||||
const data = await load();
|
||||
data.watchedDirs.push(dir);
|
||||
await save();
|
||||
}
|
||||
|
||||
export async function updateDir(id: string, patch: Partial<WatchedDir>): Promise<void> {
|
||||
const data = await load();
|
||||
const idx = data.watchedDirs.findIndex((d) => d.id === id);
|
||||
if (idx === -1) return;
|
||||
data.watchedDirs[idx] = { ...data.watchedDirs[idx], ...patch };
|
||||
await save();
|
||||
}
|
||||
|
||||
export async function removeDir(id: string): Promise<void> {
|
||||
const data = await load();
|
||||
data.watchedDirs = data.watchedDirs.filter((d) => d.id !== id);
|
||||
await save();
|
||||
}
|
||||
|
||||
export async function getSettings(): Promise<AppSettings> {
|
||||
return (await load()).settings;
|
||||
}
|
||||
|
||||
export async function updateSettings(patch: Partial<AppSettings>): Promise<void> {
|
||||
const data = await load();
|
||||
data.settings = { ...data.settings, ...patch };
|
||||
await save();
|
||||
}
|
||||
|
||||
export async function appendUndoEntries(entries: UndoEntry[]): Promise<void> {
|
||||
const data = await load();
|
||||
data.undoLog.push(...entries);
|
||||
if (data.undoLog.length > MAX_UNDO_LOG) {
|
||||
data.undoLog = data.undoLog.slice(-MAX_UNDO_LOG);
|
||||
}
|
||||
await save();
|
||||
}
|
||||
|
||||
export async function getUndoLog(): Promise<UndoEntry[]> {
|
||||
return (await load()).undoLog;
|
||||
}
|
||||
|
||||
export async function markUndoReverted(ids: string[]): Promise<void> {
|
||||
const data = await load();
|
||||
const set = new Set(ids);
|
||||
data.undoLog.forEach((e) => {
|
||||
if (set.has(e.id)) e.reverted = true;
|
||||
});
|
||||
await save();
|
||||
}
|
||||
Reference in New Issue
Block a user