import { useEffect, useState } from "react";
import { emitTo } from "@tauri-apps/api/event";
import {
hidePanel,
quitApp,
scrapeSubscriptions,
showMainWindow,
traySaveVideo,
} from "../api";
import { Spinner } from "./ui";
/**
* The menu bar panel.
*
* A window rather than a native menu, so it is the app's own type, spacing and
* colours instead of the system's. It hangs from the icon and closes when it
* loses focus, which is what a menu does; everything else about it is ours.
*/
interface RowProps {
label: string;
hint?: string;
onClick: () => void;
busy?: boolean;
icon: React.ReactNode;
}
function Row({ label, hint, onClick, busy, icon }: RowProps) {
return (
);
}
const ICON = "size-4";
const stroke = { fill: "none", stroke: "currentColor", strokeWidth: 1.8 } as const;
export default function TrayPanel() {
const [busy, setBusy] = useState(null);
const [note, setNote] = useState(null);
// The panel is its own window, so it carries no page background of the app's.
useEffect(() => {
document.documentElement.style.background = "transparent";
document.body.style.background = "transparent";
}, []);
const run = (id: string, fn: () => Promise, closeAfter = true) => {
setBusy(id);
setNote(null);
fn()
.then(() => {
if (closeAfter) void hidePanel();
})
.catch((e) => setNote(String(e)))
.finally(() => setBusy(null));
};
const importSubscriptions = () =>
run(
"subs",
async () => {
const result = await scrapeSubscriptions();
// The window owns the confirmation: replacing the list is not a thing
// to agree to in a panel that closes when you look away.
await emitTo("main", "subs:scraped", result);
await showMainWindow();
},
false,
);
return (