import {
thisComputerReady,
type ThisComputerPlatform,
type ThisComputerStatus,
} from "@opengeni/sdk/this-computer";
import { LaptopIcon, XIcon } from "lucide-react";
import { useCallback, useEffect, useState, type ReactNode } from "react";
import { useOpenGeniText } from "../../messages/runtime";
import { defaultThisComputerLabels, type ThisComputerLabels } from "./labels";
import type { UseThisComputerResult } from "./use-this-computer";
/** What the status pieces show for a computer, in order of what matters. */
export type ThisComputerView =
| "hidden"
| "off"
| "setting_up"
| "finish_setup"
| "ready"
| "reconnecting"
| "paused"
| "resuming";
export function thisComputerView(status: ThisComputerStatus | null): ThisComputerView {
if (!status || status.state === "unavailable") return "hidden";
if (status.state === "paused") return status.busy ? "resuming" : "paused";
if (status.state === "connected") {
if (!thisComputerReady(status)) return "finish_setup";
return status.reconnecting ? "reconnecting" : "ready";
}
return status.busy ? "setting_up" : "off";
}
function percent(status: ThisComputerStatus | null): string {
return status?.setupProgress === undefined ? "" : ` ${Math.round(status.setupProgress * 100)}%`;
}
function storageKey(workspaceId: string) {
return `opengeni.desktop.thisComputer.dismissed.${workspaceId}`;
}
/** "Not now" on the offer, remembered per workspace on this device. */
export function useThisComputerOfferDismissed(workspaceId: string): [boolean, () => void] {
const read = useCallback(() => {
try {
return window.localStorage.getItem(storageKey(workspaceId)) === "1";
} catch {
return false;
}
}, [workspaceId]);
const [dismissed, setDismissed] = useState(read);
useEffect(() => setDismissed(read()), [read]);
const dismiss = useCallback(() => {
try {
window.localStorage.setItem(storageKey(workspaceId), "1");
} catch {
// Hidden for this page only.
}
setDismissed(true);
}, [workspaceId]);
return [dismissed, dismiss];
}
export interface ThisComputerOfferProps {
computer: UseThisComputerResult;
labels?: ThisComputerLabels;
/** Opens `ThisComputerSetup`. */
onSetup(): void;
/** The person chose "Not now" earlier; the offer stays away until set up. */
dismissed?: boolean;
onDismiss?(): void;
/** The mark beside the title; a laptop by default. */
icon?: ReactNode;
className?: string | undefined;
}
/**
* A small card for a sidebar or panel, only while there's something to do:
* the offer to set up, setup in progress, finishing the permissions, or
* resuming a paused computer. Shows nothing once it's ready.
*/
export function ThisComputerOffer({
computer,
labels: given,
onSetup,
dismissed = false,
onDismiss,
icon,
className,
}: ThisComputerOfferProps) {
const catalogText = useOpenGeniText();
const labels = given ?? defaultThisComputerLabels(catalogText);
const { status } = computer;
const view = thisComputerView(status);
const machineName = status?.machineName ?? "";
const mark = icon ??
{labels.finishSetup}
{labels.finishSetupDetail}
{labels.title}
{labels.offer(machineName)}
{labels.title}
{line}
{error}
) : null} {connected && computer.canDisconnect ? ( confirmingOff ? ({labels.turnOffConfirm(machineName)}
{status?.management === "service" ? catalogText("thisComputer.servicePauseHint") : view === "paused" ? labels.resumeHint(platform) : labels.pauseHint(platform)}
) ) : null} {!connected && status?.management === "service" ? ({catalogText("thisComputer.existingService")}
) : null}