Tauri v2 + SolidJS + SQLite + ffmpeg 사이드카로 구현한 크로스플랫폼 사진·영상 관리 앱. 로컬/NAS(SFTP·WebDAV·FTP) 소스, 가상 그리드, 인앱 재생, 태그/이동/삭제/undo, 중복 탐지, 포터블 배포. - archive-db: SQLite 스키마·마이그레이션·단일 writer 스레드 + FTS5 trigram - archive-vfs: VFS 4백엔드(local/sftp/ftp/webdav) + 자격증명(키체인/볼트) - archive-indexer: 스캔·해시·썸네일·중복탐지·태그·파일작업·유지보수 - archive-media: localhost HTTP 미디어 서버(Range) + ffmpeg 스트림 잡 - 프론트: 3-pane UI, justified 가상 그리드, 라이트박스, 중복 검토 패널 Rust 테스트 49개 통과. CI: win x64/arm64 포터블 zip + macOS universal dmg. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { onCleanup, onMount, type Component } from "solid-js";
|
|
import { Sidebar, onLibraryChangedRefresh } from "./shell/Sidebar";
|
|
import { ContentArea } from "./shell/ContentArea";
|
|
import { DetailsPanel } from "./shell/DetailsPanel";
|
|
import { StatusBar } from "./shell/StatusBar";
|
|
import { Lightbox } from "./features/viewer/Lightbox";
|
|
import { ContextMenu } from "./features/fileops/ContextMenu";
|
|
import { MoveDialog } from "./features/fileops/MoveDialog";
|
|
import { DedupePanel } from "./features/dedupe/DedupePanel";
|
|
import { RemoteDialog } from "./features/sources/RemoteDialog";
|
|
import { onLibraryChanged, onThumbsReady, type UnlistenFn } from "./ipc/commands";
|
|
import { bumpThumbVersions, loadAppInfo, refreshSnapshot } from "./state/store";
|
|
|
|
const App: Component = () => {
|
|
onMount(() => {
|
|
void loadAppInfo();
|
|
void refreshSnapshot();
|
|
|
|
const unlisteners: Promise<UnlistenFn>[] = [
|
|
onThumbsReady((ids) => bumpThumbVersions(ids)),
|
|
onLibraryChanged(() => onLibraryChangedRefresh()),
|
|
];
|
|
onCleanup(() => {
|
|
for (const u of unlisteners) void u.then((f) => f());
|
|
});
|
|
});
|
|
|
|
return (
|
|
<div class="grid h-full grid-rows-[1fr_auto]">
|
|
<div class="grid min-h-0 grid-cols-[240px_1fr_280px]">
|
|
<Sidebar />
|
|
<ContentArea />
|
|
<DetailsPanel />
|
|
</div>
|
|
<StatusBar />
|
|
<Lightbox />
|
|
<ContextMenu />
|
|
<MoveDialog />
|
|
<DedupePanel />
|
|
<RemoteDialog />
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default App;
|