import { useState, useEffect, useCallback } from "react"; import { invoke } from "@tauri-apps/api/tauri"; import { appWindow } from "@tauri-apps/api/window"; import "./App.css"; // Import cursor images directly import defaultCursor from "./cursors/default.png"; import iconCursor from "./cursors/icon.png"; import redCursor from "./cursors/red.png"; // Components import Header from "./components/Header"; import Content from "./components/Content"; import Footer from "./components/Footer"; function App() { const [activePage, setActivePage] = useState("cursors"); const [cursors, setCursors] = useState([]); const [currentCursorIndex, setCurrentCursorIndex] = useState(0); const [settings, setSettings] = useState({ minimizeToTrayOnClose: true, startWithWindows: false, autoApplyCursorOnSelection: true }); // Function to minimize app to tray const minimizeToTray = useCallback(async () => { try { // First hide the window to ensure it disappears immediately await appWindow.hide(); // Then call the backend to ensure the tray is visible await invoke("minimize_to_tray"); } catch (error) { console.error("Failed to minimize to tray:", error); // Fallback to window API if the invoke fails try { await appWindow.hide(); } catch (fallbackError) { console.error("Fallback hide also failed:", fallbackError); } } }, []); // Function to handle window focus/show events to re-apply cursor useEffect(() => { const setupFocusHandler = async () => { const unlistenFocus = await appWindow.onFocusChanged(async ({ payload: focused }) => { if (focused) { try { await invoke("reapply_custom_cursor"); } catch (error) { console.error('Failed to re-apply cursor on focus:', error); } } }); return unlistenFocus; }; let unlistenFocusFn; setupFocusHandler().then(unlisten => { unlistenFocusFn = unlisten; }).catch(err => console.error('Failed to set up focus handler:', err)); return () => { if (unlistenFocusFn) { unlistenFocusFn(); } }; }, []); // Load cursors on mount and set up event listeners useEffect(() => { const loadCursors = async () => { try { // Get cursors from the Tauri backend const loadedCursors = await invoke("get_cursors"); setCursors(loadedCursors || []); // Get current cursor index const currentIndex = await invoke("get_current_cursor_index"); setCurrentCursorIndex(currentIndex); } catch (error) { console.error("Failed to load cursors:", error); // Use the imported cursor images directly setCursors([ { name: "default", path: defaultCursor }, { name: "icon", path: iconCursor }, { name: "red", path: redCursor }, // We don't have blue and gold cursors imported since they don't exist yet // These will be excluded for now ]); setCurrentCursorIndex(0); } }; loadCursors(); }, []); // Set up window close event listener useEffect(() => { const setupCloseHandler = async () => { const unlisten = await appWindow.onCloseRequested(async (event) => { if (settings.minimizeToTrayOnClose) { // Prevent the window from closing event.preventDefault(); // Temporarily restore cursor before hiding to tray try { await invoke("temporarily_restore_cursor"); } catch (error) { console.error('Failed to restore cursor before hiding:', error); } // Hide the window instead try { await minimizeToTray(); } catch (error) { console.error('Failed to minimize to tray on close:', error); } } else { // Let the window close normally, but we need to call quit_app to ensure proper cleanup try { await invoke("quit_app"); } catch (error) { console.error("Failed to quit app:", error); } } }); return unlisten; }; let unlistenFn; setupCloseHandler().then(unlisten => { unlistenFn = unlisten; }).catch(err => console.error('Failed to set up close handler:', err)); // Clean up event listener on unmount return () => { if (unlistenFn) { unlistenFn(); } }; }, [settings.minimizeToTrayOnClose, minimizeToTray]); // Functions to handle cursor operations using Tauri backend const selectCursor = async (index) => { try { await invoke("select_cursor", { index }); setCurrentCursorIndex(index); } catch (error) { console.error("Failed to select cursor:", error); } }; const nextCursor = async () => { if (cursors.length === 0) return; try { const newIndex = await invoke("next_cursor"); setCurrentCursorIndex(newIndex); } catch (error) { console.error("Failed to switch to next cursor:", error); // Fallback if backend fails const newIndex = (currentCursorIndex + 1) % cursors.length; setCurrentCursorIndex(newIndex); } }; // Function to exit app const quitApp = async () => { try { await invoke("quit_app"); } catch (error) { console.error("Failed to quit app:", error); } }; return (