- Remove ~101 useless debug print statements from production code - Remove verbose resource debugging and repetitive status messages - Significantly reduce console noise while maintaining error visibility
212 lines
6.1 KiB
React
212 lines
6.1 KiB
React
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 (
|
|
<div className="modal-container">
|
|
<div className="modal">
|
|
<Header
|
|
activePage={activePage}
|
|
setActivePage={setActivePage}
|
|
minimizeToTray={minimizeToTray}
|
|
quitApp={quitApp}
|
|
settings={settings}
|
|
/>
|
|
|
|
<Content
|
|
activePage={activePage}
|
|
cursors={cursors}
|
|
currentCursorIndex={currentCursorIndex}
|
|
selectCursor={selectCursor}
|
|
nextCursor={nextCursor}
|
|
settings={settings}
|
|
setSettings={setSettings}
|
|
/>
|
|
|
|
<Footer
|
|
version="0.1.0"
|
|
status={cursors.length > 0 ? `${cursors.length} cursors loaded` : "No cursors found"}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default App;
|