| "use client";
|
|
|
| import { useState, useEffect, useCallback, useSyncExternalStore } from "react";
|
|
|
| |
| |
| |
| |
| |
|
|
|
|
|
|
|
|
| function getIsElectronSnapshot(): boolean {
|
| return typeof window !== "undefined" && window.electronAPI?.isElectron === true;
|
| }
|
|
|
| function getServerSnapshot(): boolean {
|
| return false;
|
| }
|
|
|
| const noop = () => () => {};
|
|
|
| |
| |
|
|
| export function useIsElectron(): boolean {
|
| return useSyncExternalStore(noop, getIsElectronSnapshot, getServerSnapshot);
|
| }
|
|
|
| |
| |
| |
|
|
| interface AppInfo {
|
| name: string;
|
| version: string;
|
| platform: string;
|
| isDev: boolean;
|
| port: number;
|
| }
|
|
|
| |
| |
|
|
| export function useElectronAppInfo() {
|
| const hasApi = getIsElectronSnapshot();
|
| const [appInfo, setAppInfo] = useState<AppInfo | null>(null);
|
| const [loading, setLoading] = useState(hasApi);
|
| const [error, setError] = useState<Error | null>(null);
|
|
|
| useEffect(() => {
|
| if (typeof window === "undefined" || !window.electronAPI) return;
|
|
|
| window.electronAPI
|
| .getAppInfo()
|
| .then((info) => {
|
| setAppInfo(info);
|
| setLoading(false);
|
| })
|
| .catch((err) => {
|
| setError(err);
|
| setLoading(false);
|
| });
|
| }, []);
|
|
|
| return { appInfo, loading, error };
|
| }
|
|
|
| |
| |
| |
|
|
| export function useDataDir() {
|
| const hasApi = getIsElectronSnapshot();
|
| const [dataDir, setDataDir] = useState<string | null>(null);
|
| const [loading, setLoading] = useState(hasApi);
|
| const [error, setError] = useState<Error | null>(null);
|
|
|
| useEffect(() => {
|
| if (typeof window === "undefined" || !window.electronAPI) return;
|
|
|
| window.electronAPI
|
| .getDataDir()
|
| .then((dir) => {
|
| setDataDir(dir);
|
| setLoading(false);
|
| })
|
| .catch((err) => {
|
| setError(err instanceof Error ? err : new Error(String(err)));
|
| setLoading(false);
|
| });
|
| }, []);
|
|
|
| return { dataDir, loading, error };
|
| }
|
|
|
| |
| |
|
|
| export function useWindowControls() {
|
| const isElectron = useIsElectron();
|
|
|
| const minimize = useCallback(() => {
|
| if (isElectron && window.electronAPI) {
|
| window.electronAPI.minimizeWindow();
|
| }
|
| }, [isElectron]);
|
|
|
| const maximize = useCallback(() => {
|
| if (isElectron && window.electronAPI) {
|
| window.electronAPI.maximizeWindow();
|
| }
|
| }, [isElectron]);
|
|
|
| const close = useCallback(() => {
|
| if (isElectron && window.electronAPI) {
|
| window.electronAPI.closeWindow();
|
| }
|
| }, [isElectron]);
|
|
|
| return { isElectron, minimize, maximize, close };
|
| }
|
|
|
| |
| |
|
|
| export function useOpenExternal() {
|
| const isElectron = useIsElectron();
|
|
|
| const openExternal = useCallback(
|
| async (url: string) => {
|
| if (isElectron && window.electronAPI) {
|
| await window.electronAPI.openExternal(url);
|
| } else {
|
| window.open(url, "_blank", "noopener,noreferrer");
|
| }
|
| },
|
| [isElectron]
|
| );
|
|
|
| return { openExternal };
|
| }
|
|
|
| |
| |
|
|
| export function useServerControls() {
|
| const isElectron = useIsElectron();
|
| const [restarting, setRestarting] = useState(false);
|
|
|
| const restart = useCallback(async () => {
|
| if (!isElectron || !window.electronAPI) {
|
| return { success: false };
|
| }
|
|
|
| setRestarting(true);
|
| try {
|
| const result = await window.electronAPI.restartServer();
|
| return result;
|
| } finally {
|
| setRestarting(false);
|
| }
|
| }, [isElectron]);
|
|
|
| return { isElectron, restart, restarting };
|
| }
|
|
|
| |
| |
| |
|
|
| export function useServerStatus(onStatus: (status: { status: string; port: number }) => void) {
|
| const isElectron = useIsElectron();
|
|
|
| useEffect(() => {
|
| if (!isElectron || !window.electronAPI) return;
|
|
|
| const dispose = window.electronAPI.onServerStatus(onStatus);
|
| return dispose;
|
| }, [isElectron, onStatus]);
|
| }
|
|
|
| |
| |
| |
|
|
| export function usePortChanged(onPortChanged: (port: number) => void) {
|
| const isElectron = useIsElectron();
|
|
|
| useEffect(() => {
|
| if (!isElectron || !window.electronAPI) return;
|
|
|
| const dispose = window.electronAPI.onPortChanged(onPortChanged);
|
| return dispose;
|
| }, [isElectron, onPortChanged]);
|
| }
|
|
|