Initial commit: AI Photo Organizer (Electron + face-api)
Local-first photo organizer that auto-sorts images by face recognition and EXIF capture date. - Electron app with 3-process split: Main (Node) / UI Renderer (React) / hidden Inference Renderer (face-api + WebGL) - Core pipeline: scan -> face match + EXIF -> path build -> atomic move/copy - Move = copy -> verify -> delete; auto-rename on filename collision - 1st-registered profile = move, others = copy; unmatched -> [미정]/YYYY/MM - EXIF date with mtime fallback - Vitest unit tests (pathBuilder / fileOps / concurrency) all green - electron-builder config for Windows (nsis) + macOS (dmg) - Docs: PRD / DECISIONS / ARCHITECTURE Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import { useEffect } from 'react'
|
||||
import { useStore, wireEvents } from './store'
|
||||
import { ProfileManager } from './components/ProfileManager'
|
||||
import { FolderPicker } from './components/FolderPicker'
|
||||
import { RunControl } from './components/RunControl'
|
||||
import { ProgressView } from './components/ProgressView'
|
||||
import { FileList } from './components/FileList'
|
||||
import { ReportView } from './components/ReportView'
|
||||
|
||||
export default function App(): JSX.Element {
|
||||
const phase = useStore((s) => s.phase)
|
||||
const refreshProfiles = useStore((s) => s.refreshProfiles)
|
||||
|
||||
useEffect(() => {
|
||||
const unwire = wireEvents()
|
||||
void refreshProfiles()
|
||||
return unwire
|
||||
}, [refreshProfiles])
|
||||
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<header className="px-6 py-4 bg-white border-b border-slate-200 shadow-sm">
|
||||
<h1 className="text-xl font-bold text-brand-dark">AI Photo Organizer</h1>
|
||||
<p className="text-sm text-slate-500">
|
||||
얼굴 인식 + 촬영일 기준 자동 사진 정리 · 로컬 전용
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<main className="flex-1 grid grid-cols-12 gap-4 p-6 overflow-hidden">
|
||||
{/* 좌측: 설정 패널 */}
|
||||
<section className="col-span-5 flex flex-col gap-4 overflow-y-auto pr-2">
|
||||
<ProfileManager />
|
||||
<FolderPicker />
|
||||
<RunControl />
|
||||
</section>
|
||||
|
||||
{/* 우측: 진행/결과 */}
|
||||
<section className="col-span-7 flex flex-col gap-4 overflow-hidden">
|
||||
{phase === 'done' ? <ReportView /> : <ProgressView />}
|
||||
<FileList />
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user