import { useState } from "react"; import { open, save } from "@tauri-apps/plugin-dialog"; import type { ArchiveJobResult } from "../lib/types"; interface ArchivePanelProps { onExtract: (source: string, destination: string) => Promise; onCompress: (source: string, destination: string) => Promise; } type ArchiveAction = "extract" | "compress" | null; export function ArchivePanel({ onExtract, onCompress }: ArchivePanelProps) { const [source, setSource] = useState(""); const [destination, setDestination] = useState(""); const [lastResult, setLastResult] = useState(null); const [error, setError] = useState(null); const [pendingAction, setPendingAction] = useState(null); async function runAction(action: Exclude) { if (!source || !destination) { setError("Choose both a source and destination before running an archive job."); return; } setPendingAction(action); setError(null); try { const result = action === "extract" ? await onExtract(source, destination) : await onCompress(source, destination); setLastResult(result); } catch (cause) { setError(cause instanceof Error ? cause.message : "Archive job failed."); } finally { setPendingAction(null); } } return (
Archive utilities

Extract and package sample crates

Supports ZIP, TAR, and{" "} TAR.GZ / TGZ. Extraction expects an archive file and a target folder. Compression accepts either a file or directory and writes a new archive.

Source
setSource(event.target.value)} className="flex-1 rounded-2xl border border-line/40 bg-panel/70 px-4 py-3 text-text outline-none" placeholder="Archive file to extract, or file/folder to compress" />
Destination
setDestination(event.target.value)} className="flex-1 rounded-2xl border border-line/40 bg-panel/70 px-4 py-3 text-text outline-none" placeholder="Target folder for extract, or archive path like crate.tar.gz" />
{error ? (
{error}
) : null} {lastResult ? (
Output: {lastResult.output_path}
{lastResult.processed_entries} items processed
) : null}
); }