Integrate Tauri frontend with categorization system and Steam integration
This commit is contained in:
+89
-20
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { invoke } from "@tauri-apps/api/tauri";
|
||||
import { appWindow } from "@tauri-apps/api/window";
|
||||
import "./App.css";
|
||||
@@ -17,8 +17,37 @@ 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
|
||||
});
|
||||
|
||||
// Load cursors on mount
|
||||
// Function to minimize app to tray
|
||||
const minimizeToTray = useCallback(async () => {
|
||||
try {
|
||||
console.log('Minimizing app to tray');
|
||||
// First hide the window to ensure it disappears immediately
|
||||
await appWindow.hide();
|
||||
console.log('Window hidden, now ensuring tray is visible');
|
||||
|
||||
// Then call the backend to ensure the tray is visible
|
||||
await invoke("minimize_to_tray");
|
||||
console.log('minimize_to_tray command completed successfully');
|
||||
} catch (error) {
|
||||
console.error("Failed to minimize to tray:", error);
|
||||
// Fallback to window API if the invoke fails
|
||||
try {
|
||||
console.log('Trying fallback hide');
|
||||
await appWindow.hide();
|
||||
console.log('Fallback hide succeeded');
|
||||
} catch (fallbackError) {
|
||||
console.error("Fallback hide also failed:", fallbackError);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
// Load cursors on mount and set up event listeners
|
||||
useEffect(() => {
|
||||
const loadCursors = async () => {
|
||||
try {
|
||||
@@ -26,7 +55,7 @@ function App() {
|
||||
const loadedCursors = await invoke("get_cursors");
|
||||
console.log("Loaded cursors:", loadedCursors);
|
||||
setCursors(loadedCursors || []);
|
||||
|
||||
|
||||
// Get current cursor index
|
||||
const currentIndex = await invoke("get_current_cursor_index");
|
||||
setCurrentCursorIndex(currentIndex);
|
||||
@@ -47,6 +76,53 @@ function App() {
|
||||
loadCursors();
|
||||
}, []);
|
||||
|
||||
// Set up window close event listener
|
||||
useEffect(() => {
|
||||
const setupCloseHandler = async () => {
|
||||
const unlisten = await appWindow.onCloseRequested(async (event) => {
|
||||
console.log('Window close requested');
|
||||
|
||||
if (settings.minimizeToTrayOnClose) {
|
||||
console.log('Minimize to tray setting is enabled, preventing close and hiding instead');
|
||||
// Prevent the window from closing
|
||||
event.preventDefault();
|
||||
|
||||
// Hide the window instead
|
||||
try {
|
||||
console.log('Calling minimizeToTray function');
|
||||
await minimizeToTray();
|
||||
console.log('Window should now be hidden and app should be in system tray');
|
||||
} catch (error) {
|
||||
console.error('Failed to minimize to tray on close:', error);
|
||||
}
|
||||
} else {
|
||||
console.log('Minimize to tray setting is disabled, allowing window to close');
|
||||
// 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;
|
||||
console.log('Close handler set up successfully');
|
||||
}).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 {
|
||||
@@ -60,7 +136,7 @@ function App() {
|
||||
|
||||
const nextCursor = async () => {
|
||||
if (cursors.length === 0) return;
|
||||
|
||||
|
||||
try {
|
||||
console.log('Switching to next cursor');
|
||||
const newIndex = await invoke("next_cursor");
|
||||
@@ -73,16 +149,6 @@ function App() {
|
||||
}
|
||||
};
|
||||
|
||||
// Function to minimize app to tray
|
||||
const minimizeToTray = async () => {
|
||||
try {
|
||||
console.log('Minimizing app to tray');
|
||||
await appWindow.hide();
|
||||
} catch (error) {
|
||||
console.error("Failed to minimize to tray:", error);
|
||||
}
|
||||
};
|
||||
|
||||
// Function to exit app
|
||||
const quitApp = async () => {
|
||||
try {
|
||||
@@ -96,22 +162,25 @@ function App() {
|
||||
return (
|
||||
<div className="modal-container">
|
||||
<div className="modal">
|
||||
<Header
|
||||
activePage={activePage}
|
||||
<Header
|
||||
activePage={activePage}
|
||||
setActivePage={setActivePage}
|
||||
minimizeToTray={minimizeToTray}
|
||||
quitApp={quitApp}
|
||||
settings={settings}
|
||||
/>
|
||||
|
||||
<Content
|
||||
|
||||
<Content
|
||||
activePage={activePage}
|
||||
cursors={cursors}
|
||||
currentCursorIndex={currentCursorIndex}
|
||||
selectCursor={selectCursor}
|
||||
nextCursor={nextCursor}
|
||||
settings={settings}
|
||||
setSettings={setSettings}
|
||||
/>
|
||||
|
||||
<Footer
|
||||
|
||||
<Footer
|
||||
version="0.1.0"
|
||||
status={cursors.length > 0 ? `${cursors.length} cursors loaded` : "No cursors found"}
|
||||
/>
|
||||
|
||||
@@ -7,19 +7,19 @@ import Cursors from './content_modules/Cursors';
|
||||
import Crates from './content_modules/Crates';
|
||||
import Settings from './content_modules/Settings';
|
||||
|
||||
function Content({ activePage, cursors, currentCursorIndex, selectCursor, nextCursor }) {
|
||||
function Content({ activePage, cursors, currentCursorIndex, selectCursor, nextCursor, settings, setSettings }) {
|
||||
// Render the appropriate content based on active page
|
||||
const renderContent = () => {
|
||||
switch (activePage) {
|
||||
case 'inventory':
|
||||
return <Inventory
|
||||
return <Inventory
|
||||
cursors={cursors}
|
||||
currentCursorIndex={currentCursorIndex}
|
||||
selectCursor={selectCursor}
|
||||
/>;
|
||||
case 'cursors':
|
||||
return (
|
||||
<Cursors
|
||||
<Cursors
|
||||
cursors={cursors}
|
||||
currentCursorIndex={currentCursorIndex}
|
||||
selectCursor={selectCursor}
|
||||
@@ -29,9 +29,9 @@ function Content({ activePage, cursors, currentCursorIndex, selectCursor, nextCu
|
||||
case 'crates':
|
||||
return <Crates />;
|
||||
case 'settings':
|
||||
return <Settings />;
|
||||
return <Settings settings={settings} setSettings={setSettings} />;
|
||||
default:
|
||||
return <Cursors
|
||||
return <Cursors
|
||||
cursors={cursors}
|
||||
currentCursorIndex={currentCursorIndex}
|
||||
selectCursor={selectCursor}
|
||||
@@ -39,7 +39,7 @@ function Content({ activePage, cursors, currentCursorIndex, selectCursor, nextCu
|
||||
/>;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="app-content">
|
||||
{renderContent()}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import React from 'react';
|
||||
import './Header.css';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import {
|
||||
faGripVertical,
|
||||
faBoxOpen,
|
||||
faMousePointer,
|
||||
faBoxes,
|
||||
faCog,
|
||||
import {
|
||||
faGripVertical,
|
||||
faBoxOpen,
|
||||
faMousePointer,
|
||||
faBoxes,
|
||||
faCog,
|
||||
faBoxArchive,
|
||||
faBox,
|
||||
faWarehouse,
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
faBagShopping
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
function Header({ activePage, setActivePage, minimizeToTray, quitApp }) {
|
||||
function Header({ activePage, setActivePage, minimizeToTray, quitApp, settings }) {
|
||||
// Navigation buttons for each page with icons
|
||||
const navItems = [
|
||||
{ id: 'inventory', icon: faBagShopping, tooltip: 'Inventory' },
|
||||
@@ -24,12 +24,23 @@ function Header({ activePage, setActivePage, minimizeToTray, quitApp }) {
|
||||
{ id: 'crates', icon: faBoxOpen, tooltip: 'Crates' },
|
||||
{ id: 'settings', icon: faCog, tooltip: 'Settings' }
|
||||
];
|
||||
|
||||
|
||||
// Handle close button click based on settings
|
||||
const handleCloseClick = () => {
|
||||
if (settings && settings.minimizeToTrayOnClose) {
|
||||
console.log('Close button clicked, minimizing to tray based on settings');
|
||||
minimizeToTray();
|
||||
} else {
|
||||
console.log('Close button clicked, quitting application based on settings');
|
||||
quitApp();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<header className="app-header" data-tauri-drag-region>
|
||||
<div className="tabs-container">
|
||||
{navItems.map((item) => (
|
||||
<div
|
||||
<div
|
||||
key={item.id}
|
||||
className={`tab ${activePage === item.id ? 'active' : ''}`}
|
||||
onClick={() => setActivePage(item.id)}
|
||||
@@ -42,7 +53,11 @@ function Header({ activePage, setActivePage, minimizeToTray, quitApp }) {
|
||||
<button className="minimize-button" onClick={minimizeToTray} title="Minimize to Tray">
|
||||
_
|
||||
</button>
|
||||
<button className="close-button" onClick={quitApp} title="Quit Application">
|
||||
<button
|
||||
className="close-button"
|
||||
onClick={handleCloseClick}
|
||||
title={settings && settings.minimizeToTrayOnClose ? "Minimize to Tray" : "Quit Application"}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import React from 'react';
|
||||
import './Settings.css';
|
||||
|
||||
function Settings() {
|
||||
function Settings({ settings, setSettings }) {
|
||||
// Handler for checkbox changes
|
||||
const handleSettingChange = (settingName) => {
|
||||
setSettings({
|
||||
...settings,
|
||||
[settingName]: !settings[settingName]
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="settings-container">
|
||||
<h2 className="content-title">Settings</h2>
|
||||
@@ -10,23 +18,35 @@ function Settings() {
|
||||
<h3>Application Settings</h3>
|
||||
<div className="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.startWithWindows}
|
||||
onChange={() => handleSettingChange('startWithWindows')}
|
||||
/>
|
||||
Start with Windows
|
||||
</label>
|
||||
</div>
|
||||
<div className="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" checked />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.minimizeToTrayOnClose}
|
||||
onChange={() => handleSettingChange('minimizeToTrayOnClose')}
|
||||
/>
|
||||
Minimize to tray on close
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="settings-group">
|
||||
<h3>Cursor Settings</h3>
|
||||
<div className="setting-item">
|
||||
<label>
|
||||
<input type="checkbox" checked />
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={settings.autoApplyCursorOnSelection}
|
||||
onChange={() => handleSettingChange('autoApplyCursorOnSelection')}
|
||||
/>
|
||||
Auto-apply cursor on selection
|
||||
</label>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user