refactor: convert to bun-workspaces monorepo (desktop/ + www/)
- Move the Tauri app (React frontend + Rust backend) into desktop/ via git mv — configs unchanged (relative paths: tauri.conf.json, vite.config.ts) - Root package.json becomes a private bun workspace container with orchestration scripts; desktop package renamed gridline-desktop - Scaffold www/ with Astro 7 + Tailwind v4 (hand-wired vite plugin, static output, ready for Dokploy) - Update release.yml for the new layout: projectPath: desktop, desktop/src-tauri resource paths, rust-cache workspace path - Update README + AGENTS.md structure trees and dev commands - Verified: vitest (1074), cargo test (354), desktop build, tauri dev (window launches), tauri build (dmg + app bundles), Astro build
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { create } from "zustand";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import type { BackupJob } from "../lib/types";
|
||||
|
||||
interface BackupJobEvent {
|
||||
job_id: string;
|
||||
status: "running" | "completed" | "failed";
|
||||
error?: string | null;
|
||||
}
|
||||
|
||||
interface BackupStore {
|
||||
jobs: BackupJob[];
|
||||
activeJobId: string | null;
|
||||
progress: number;
|
||||
startJob: (jobId: string, type: string) => void;
|
||||
completeJob: (jobId: string) => void;
|
||||
failJob: (jobId: string, error: string) => void;
|
||||
initListener: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const useBackupStore = create<BackupStore>((set, get) => ({
|
||||
jobs: [],
|
||||
activeJobId: null,
|
||||
progress: 0,
|
||||
|
||||
startJob: (jobId: string, type: string) =>
|
||||
set((s) => ({
|
||||
activeJobId: jobId,
|
||||
progress: 0,
|
||||
jobs: [
|
||||
...s.jobs,
|
||||
{
|
||||
id: jobId,
|
||||
connection_id: "",
|
||||
type: type as BackupJob["type"],
|
||||
format: null,
|
||||
file_path: null,
|
||||
source_connection_id: null,
|
||||
status: "running",
|
||||
error_message: null,
|
||||
size_bytes: null,
|
||||
started_at: new Date().toISOString(),
|
||||
completed_at: null,
|
||||
} satisfies BackupJob,
|
||||
],
|
||||
})),
|
||||
|
||||
completeJob: (jobId: string) =>
|
||||
set((s) => ({
|
||||
progress: 100,
|
||||
jobs: s.jobs.map((j) =>
|
||||
j.id === jobId
|
||||
? { ...j, status: "completed" as const, completed_at: new Date().toISOString() }
|
||||
: j,
|
||||
),
|
||||
})),
|
||||
|
||||
failJob: (jobId: string, error: string) =>
|
||||
set((s) => ({
|
||||
jobs: s.jobs.map((j) =>
|
||||
j.id === jobId
|
||||
? {
|
||||
...j,
|
||||
status: "failed" as const,
|
||||
error_message: error,
|
||||
completed_at: new Date().toISOString(),
|
||||
}
|
||||
: j,
|
||||
),
|
||||
})),
|
||||
|
||||
initListener: async () => {
|
||||
await listen<BackupJobEvent>("backup-progress", (event) => {
|
||||
const { job_id, status, error } = event.payload;
|
||||
if (status === "completed") {
|
||||
get().completeJob(job_id);
|
||||
} else if (status === "failed") {
|
||||
get().failJob(job_id, error || "Unknown error");
|
||||
}
|
||||
});
|
||||
},
|
||||
}));
|
||||
Reference in New Issue
Block a user