Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f733ed39b |
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"git.ignoreLimitWarning": true
|
||||||
|
}
|
||||||
@@ -16,43 +16,26 @@ A cross-platform application for customizing your cursor with gameified logic.
|
|||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
frontend/
|
||||||
├── app/ # Application core logic
|
├── src/ # React frontend code
|
||||||
│ ├── mod.rs # Main app module exports
|
│ ├── App.jsx # Main React component
|
||||||
│ ├── state.rs # Application state management
|
│ ├── components/ # UI components
|
||||||
│ ├── messages.rs # Message definitions
|
│ └── cursors/ # Cursor image files
|
||||||
│ └── cursor.rs # Cursor-related functionality
|
├── src-tauri/ # Rust backend code
|
||||||
├── ui/ # User interface components
|
│ ├── src/ # Rust source code
|
||||||
│ ├── mod.rs # UI module exports
|
│ │ ├── lib.rs # Main library code
|
||||||
│ ├── view.rs # View rendering logic
|
│ │ ├── main.rs # Application entry point
|
||||||
│ └── tray.rs # System tray functionality
|
│ │ ├── integrations/ # External integrations
|
||||||
├── platform/ # Platform-specific implementations
|
│ │ │ ├── mod.rs # Integrations module exports
|
||||||
│ ├── mod.rs # Platform module exports
|
│ │ │ └── steam.rs # Steam integration
|
||||||
│ ├── windows/ # Windows-specific code
|
│ │ └── platform/ # Platform-specific code
|
||||||
│ │ ├── mod.rs # Windows module exports
|
│ │ ├── mod.rs # Platform module exports
|
||||||
│ │ ├── types.rs # Windows type definitions
|
│ │ ├── types.rs # Common type definitions
|
||||||
│ │ ├── state.rs # Windows state management
|
│ │ ├── windows/ # Windows-specific code
|
||||||
│ │ └── cursor.rs # Windows cursor handling
|
│ │ ├── macos/ # macOS-specific code
|
||||||
│ ├── macos/ # macOS-specific code (in development)
|
│ │ └── linux/ # Linux-specific code
|
||||||
│ │ ├── mod.rs # macOS module exports
|
│ └── Cargo.toml # Rust dependencies
|
||||||
│ │ ├── state.rs # macOS state management
|
└── package.json # npm dependencies
|
||||||
│ │ └── cursor.rs # macOS cursor handling
|
|
||||||
│ ├── linux/ # Linux-specific code (in development)
|
|
||||||
│ │ ├── mod.rs # Linux module exports
|
|
||||||
│ │ ├── state.rs # Linux state management
|
|
||||||
│ │ └── cursor.rs # Linux cursor handling
|
|
||||||
│ └── unsupported/ # Fallback for unsupported platforms
|
|
||||||
│ ├── mod.rs # Unsupported module exports
|
|
||||||
│ ├── state.rs # Unsupported state management
|
|
||||||
│ └── cursor.rs # Unsupported cursor handling
|
|
||||||
├── integrations/ # External integrations
|
|
||||||
│ ├── mod.rs # Integrations module exports
|
|
||||||
│ └── steam.rs # Steam integration
|
|
||||||
├── utils/ # Utility functions and helpers
|
|
||||||
│ ├── mod.rs # Utils module exports
|
|
||||||
│ ├── config.rs # Configuration management
|
|
||||||
│ └── logging.rs # Logging utilities
|
|
||||||
└── main.rs # Application entry point
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
@@ -149,27 +132,6 @@ The application includes integration with the Steam API for future gameified fea
|
|||||||
- Item drop functionality is implemented but not yet active
|
- Item drop functionality is implemented but not yet active
|
||||||
- Steam must be running for this functionality to work
|
- Steam must be running for this functionality to work
|
||||||
|
|
||||||
## Project Structure (Tauri Version)
|
|
||||||
|
|
||||||
```
|
|
||||||
frontend/
|
|
||||||
├── src/ # React frontend code
|
|
||||||
│ ├── App.jsx # Main React component
|
|
||||||
│ ├── components/ # UI components
|
|
||||||
│ └── cursors/ # Cursor image files
|
|
||||||
├── src-tauri/ # Rust backend code
|
|
||||||
│ ├── src/ # Rust source code
|
|
||||||
│ │ ├── lib.rs # Main library code
|
|
||||||
│ │ ├── main.rs # Application entry point
|
|
||||||
│ │ └── platform/ # Platform-specific code
|
|
||||||
│ │ ├── mod.rs # Platform module exports
|
|
||||||
│ │ ├── windows/ # Windows-specific code
|
|
||||||
│ │ ├── macos/ # macOS-specific code
|
|
||||||
│ │ └── linux/ # Linux-specific code
|
|
||||||
│ └── Cargo.toml # Rust dependencies
|
|
||||||
└── package.json # npm dependencies
|
|
||||||
```
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributions to Cursor Rush are welcome! Here are some ways you can contribute:
|
Contributions to Cursor Rush are welcome! Here are some ways you can contribute:
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ rust-version = "1.56"
|
|||||||
tauri-build = { version = "1.5.2", features = [] }
|
tauri-build = { version = "1.5.2", features = [] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tauri = { version = "1.6.0", features = [ "window-start-dragging", "shell-open"] }
|
tauri = { version = "1.6.0", features = [ "window-start-dragging", "shell-open", "system-tray", "window-minimize", "window-hide", "window-show", "window-close"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
# Ensure "consoleapi" is in this features list
|
# Ensure "consoleapi" is in this features list
|
||||||
winapi = { version = "0.3.9", features = ["winuser", "libloaderapi", "wingdi", "errhandlingapi", "consoleapi"] }
|
winapi = { version = "0.3.9", features = ["winuser", "libloaderapi", "wingdi", "errhandlingapi", "consoleapi"] }
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
|
steamworks = "0.10.0"
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||||
# DO NOT REMOVE!!
|
# DO NOT REMOVE!!
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
// External integrations module
|
||||||
|
|
||||||
|
pub mod steam;
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// Steam integration
|
||||||
|
|
||||||
|
use steamworks::{AppId, Client, SingleClient};
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Steam {
|
||||||
|
client: Client,
|
||||||
|
single: SingleClient,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Steam {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let (client, single) = Client::init_app(AppId(1430270)).unwrap();
|
||||||
|
Self { client, single }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn drop_item(&self) {
|
||||||
|
// Placeholder for item drop functionality
|
||||||
|
// The actual implementation would use the Steam API to trigger an item drop
|
||||||
|
println!("Steam item drop triggered (placeholder)");
|
||||||
|
|
||||||
|
// In a real implementation with the correct API version, we would use:
|
||||||
|
// self.client.get_inventory().trigger_item_drop(item_def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use tauri::{Manager, AppHandle};
|
use tauri::{Manager, AppHandle, CustomMenuItem, SystemTray, SystemTrayMenu, SystemTrayMenuItem, SystemTrayEvent, WindowEvent};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
mod platform;
|
mod platform;
|
||||||
|
mod integrations;
|
||||||
|
|
||||||
// Define cursor structure
|
// Define cursor structure
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@@ -168,6 +169,24 @@ fn quit_app(app_handle: AppHandle) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Command to minimize the window to tray
|
||||||
|
#[tauri::command]
|
||||||
|
fn minimize_to_tray(app_handle: AppHandle) -> Result<(), String> {
|
||||||
|
println!("Minimizing to tray");
|
||||||
|
|
||||||
|
// Get the main window
|
||||||
|
let window = app_handle.get_window("main")
|
||||||
|
.ok_or_else(|| "Failed to get main window".to_string())?;
|
||||||
|
|
||||||
|
// Hide the window
|
||||||
|
window.hide().map_err(|e| format!("Failed to hide window: {}", e))?;
|
||||||
|
|
||||||
|
// The tray should already be visible as configured in tauri.conf.json
|
||||||
|
println!("Window hidden, application should now be accessible from the system tray");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
// Function to load cursor files from src/cursors directory
|
// Function to load cursor files from src/cursors directory
|
||||||
fn load_cursor_files() -> Vec<Cursor> {
|
fn load_cursor_files() -> Vec<Cursor> {
|
||||||
println!("=== RESOURCE DEBUG [load_cursor_files] ===");
|
println!("=== RESOURCE DEBUG [load_cursor_files] ===");
|
||||||
@@ -273,19 +292,138 @@ pub fn run() {
|
|||||||
current_index: 0,
|
current_index: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create system tray menu
|
||||||
|
let next_cursor_item = CustomMenuItem::new("next_cursor".to_string(), "Next cursor");
|
||||||
|
let show_window_item = CustomMenuItem::new("show_window".to_string(), "Show window");
|
||||||
|
let quit_item = CustomMenuItem::new("quit".to_string(), "Quit");
|
||||||
|
|
||||||
|
let tray_menu = SystemTrayMenu::new()
|
||||||
|
.add_item(next_cursor_item)
|
||||||
|
.add_item(show_window_item)
|
||||||
|
.add_native_item(SystemTrayMenuItem::Separator)
|
||||||
|
.add_item(quit_item);
|
||||||
|
|
||||||
|
let system_tray = SystemTray::new().with_menu(tray_menu);
|
||||||
|
|
||||||
// This is one of the simplest ways to initialize Tauri
|
// This is one of the simplest ways to initialize Tauri
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.manage(AppStateWrapper(Mutex::new(app_state)))
|
.manage(AppStateWrapper(Mutex::new(app_state)))
|
||||||
|
.system_tray(system_tray)
|
||||||
|
.on_system_tray_event(|app, event| match event {
|
||||||
|
SystemTrayEvent::LeftClick { .. } => {
|
||||||
|
println!("System tray received a left click");
|
||||||
|
if let Some(window) = app.get_window("main") {
|
||||||
|
match window.is_visible() {
|
||||||
|
Ok(visible) => {
|
||||||
|
if visible {
|
||||||
|
println!("Window is already visible, focusing it");
|
||||||
|
let _ = window.set_focus();
|
||||||
|
} else {
|
||||||
|
println!("Window is hidden, showing it");
|
||||||
|
if let Err(e) = window.show() {
|
||||||
|
eprintln!("Failed to show window: {}", e);
|
||||||
|
}
|
||||||
|
if let Err(e) = window.set_focus() {
|
||||||
|
eprintln!("Failed to focus window: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Failed to check window visibility: {}", e);
|
||||||
|
// Try to show it anyway
|
||||||
|
if let Err(e) = window.show() {
|
||||||
|
eprintln!("Failed to show window: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("Main window not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemTrayEvent::MenuItemClick { id, .. } => {
|
||||||
|
println!("Menu item clicked: {}", id);
|
||||||
|
match id.as_str() {
|
||||||
|
"next_cursor" => {
|
||||||
|
println!("Next cursor requested from tray");
|
||||||
|
let state = app.state::<AppStateWrapper>();
|
||||||
|
let mut app_state = state.0.lock().unwrap();
|
||||||
|
|
||||||
|
if !app_state.cursors.is_empty() {
|
||||||
|
app_state.current_index = (app_state.current_index + 1) % app_state.cursors.len();
|
||||||
|
let cursor = &app_state.cursors[app_state.current_index];
|
||||||
|
|
||||||
|
if Path::new(&cursor.path).exists() {
|
||||||
|
if let Err(e) = platform::set_system_cursor(&cursor.path) {
|
||||||
|
eprintln!("Error applying cursor from tray: {}", e);
|
||||||
|
} else {
|
||||||
|
// Emit an event to notify the frontend
|
||||||
|
let _ = app.emit_all("cursor_changed", app_state.current_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"show_window" => {
|
||||||
|
println!("Show window requested from tray");
|
||||||
|
if let Some(window) = app.get_window("main") {
|
||||||
|
if let Err(e) = window.show() {
|
||||||
|
eprintln!("Failed to show window: {}", e);
|
||||||
|
}
|
||||||
|
if let Err(e) = window.set_focus() {
|
||||||
|
eprintln!("Failed to focus window: {}", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eprintln!("Main window not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"quit" => {
|
||||||
|
println!("Quit requested from tray");
|
||||||
|
// Clean up and restore default cursor before exit
|
||||||
|
match platform::restore_system_cursor() {
|
||||||
|
Ok(_) => println!("Default cursor restored"),
|
||||||
|
Err(e) => eprintln!("Failed to restore default cursor: {}", e),
|
||||||
|
}
|
||||||
|
app.exit(0);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
})
|
||||||
|
.on_window_event(move |event| {
|
||||||
|
match event.event() {
|
||||||
|
WindowEvent::CloseRequested { api, .. } => {
|
||||||
|
// Prevent the default close action
|
||||||
|
api.prevent_close();
|
||||||
|
|
||||||
|
// Get the window and hide it
|
||||||
|
let window = event.window();
|
||||||
|
println!("Window close requested in backend handler, hiding window");
|
||||||
|
|
||||||
|
// Hide the window instead of closing it
|
||||||
|
if let Err(e) = window.hide() {
|
||||||
|
eprintln!("Failed to hide window: {}", e);
|
||||||
|
} else {
|
||||||
|
println!("Window hidden successfully, app is now in system tray");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
})
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
get_cursors,
|
get_cursors,
|
||||||
get_current_cursor_index,
|
get_current_cursor_index,
|
||||||
select_cursor,
|
select_cursor,
|
||||||
next_cursor,
|
next_cursor,
|
||||||
quit_app
|
quit_app,
|
||||||
|
minimize_to_tray
|
||||||
])
|
])
|
||||||
.setup(|_app| {
|
.setup(|_app| {
|
||||||
// Register for events or perform additional setup
|
// Register for events or perform additional setup
|
||||||
println!("Tauri application setup complete");
|
println!("Tauri application setup complete");
|
||||||
|
|
||||||
|
// We're not setting up a window close handler here anymore
|
||||||
|
// The frontend will handle this based on the minimize-to-tray setting
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
// This matches exactly how it was before our changes
|
// This matches exactly how it was before our changes
|
||||||
|
|||||||
@@ -14,7 +14,11 @@
|
|||||||
"all": false,
|
"all": false,
|
||||||
"window": {
|
"window": {
|
||||||
"all": false,
|
"all": false,
|
||||||
"startDragging": true
|
"startDragging": true,
|
||||||
|
"minimize": true,
|
||||||
|
"hide": true,
|
||||||
|
"show": true,
|
||||||
|
"close": true
|
||||||
},
|
},
|
||||||
"shell": {
|
"shell": {
|
||||||
"all": false,
|
"all": false,
|
||||||
@@ -27,6 +31,12 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"systemTray": {
|
||||||
|
"iconPath": "icons/icon.png",
|
||||||
|
"iconAsTemplate": false,
|
||||||
|
"menuOnLeftClick": false,
|
||||||
|
"title": "Cursor Rush"
|
||||||
|
},
|
||||||
"bundle": {
|
"bundle": {
|
||||||
"active": true,
|
"active": true,
|
||||||
"identifier": "com.cursor-rush.dev",
|
"identifier": "com.cursor-rush.dev",
|
||||||
@@ -47,13 +57,15 @@
|
|||||||
},
|
},
|
||||||
"windows": [
|
"windows": [
|
||||||
{
|
{
|
||||||
|
"label": "main",
|
||||||
"title": "Cursor Rush",
|
"title": "Cursor Rush",
|
||||||
"width": 310,
|
"width": 310,
|
||||||
"height": 600,
|
"height": 600,
|
||||||
"resizable": true,
|
"resizable": true,
|
||||||
"fullscreen": false,
|
"fullscreen": false,
|
||||||
"decorations": false,
|
"decorations": false,
|
||||||
"transparent": true
|
"transparent": true,
|
||||||
|
"visible": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+81
-12
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect, useCallback } from "react";
|
||||||
import { invoke } from "@tauri-apps/api/tauri";
|
import { invoke } from "@tauri-apps/api/tauri";
|
||||||
import { appWindow } from "@tauri-apps/api/window";
|
import { appWindow } from "@tauri-apps/api/window";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
@@ -17,8 +17,37 @@ function App() {
|
|||||||
const [activePage, setActivePage] = useState("cursors");
|
const [activePage, setActivePage] = useState("cursors");
|
||||||
const [cursors, setCursors] = useState([]);
|
const [cursors, setCursors] = useState([]);
|
||||||
const [currentCursorIndex, setCurrentCursorIndex] = useState(0);
|
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(() => {
|
useEffect(() => {
|
||||||
const loadCursors = async () => {
|
const loadCursors = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -47,6 +76,53 @@ function App() {
|
|||||||
loadCursors();
|
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
|
// Functions to handle cursor operations using Tauri backend
|
||||||
const selectCursor = async (index) => {
|
const selectCursor = async (index) => {
|
||||||
try {
|
try {
|
||||||
@@ -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
|
// Function to exit app
|
||||||
const quitApp = async () => {
|
const quitApp = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -101,6 +167,7 @@ function App() {
|
|||||||
setActivePage={setActivePage}
|
setActivePage={setActivePage}
|
||||||
minimizeToTray={minimizeToTray}
|
minimizeToTray={minimizeToTray}
|
||||||
quitApp={quitApp}
|
quitApp={quitApp}
|
||||||
|
settings={settings}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Content
|
<Content
|
||||||
@@ -109,6 +176,8 @@ function App() {
|
|||||||
currentCursorIndex={currentCursorIndex}
|
currentCursorIndex={currentCursorIndex}
|
||||||
selectCursor={selectCursor}
|
selectCursor={selectCursor}
|
||||||
nextCursor={nextCursor}
|
nextCursor={nextCursor}
|
||||||
|
settings={settings}
|
||||||
|
setSettings={setSettings}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Footer
|
<Footer
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import Cursors from './content_modules/Cursors';
|
|||||||
import Crates from './content_modules/Crates';
|
import Crates from './content_modules/Crates';
|
||||||
import Settings from './content_modules/Settings';
|
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
|
// Render the appropriate content based on active page
|
||||||
const renderContent = () => {
|
const renderContent = () => {
|
||||||
switch (activePage) {
|
switch (activePage) {
|
||||||
@@ -29,7 +29,7 @@ function Content({ activePage, cursors, currentCursorIndex, selectCursor, nextCu
|
|||||||
case 'crates':
|
case 'crates':
|
||||||
return <Crates />;
|
return <Crates />;
|
||||||
case 'settings':
|
case 'settings':
|
||||||
return <Settings />;
|
return <Settings settings={settings} setSettings={setSettings} />;
|
||||||
default:
|
default:
|
||||||
return <Cursors
|
return <Cursors
|
||||||
cursors={cursors}
|
cursors={cursors}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
faBagShopping
|
faBagShopping
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} 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
|
// Navigation buttons for each page with icons
|
||||||
const navItems = [
|
const navItems = [
|
||||||
{ id: 'inventory', icon: faBagShopping, tooltip: 'Inventory' },
|
{ id: 'inventory', icon: faBagShopping, tooltip: 'Inventory' },
|
||||||
@@ -25,6 +25,17 @@ function Header({ activePage, setActivePage, minimizeToTray, quitApp }) {
|
|||||||
{ id: 'settings', icon: faCog, tooltip: 'Settings' }
|
{ 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 (
|
return (
|
||||||
<header className="app-header" data-tauri-drag-region>
|
<header className="app-header" data-tauri-drag-region>
|
||||||
<div className="tabs-container">
|
<div className="tabs-container">
|
||||||
@@ -42,7 +53,11 @@ function Header({ activePage, setActivePage, minimizeToTray, quitApp }) {
|
|||||||
<button className="minimize-button" onClick={minimizeToTray} title="Minimize to Tray">
|
<button className="minimize-button" onClick={minimizeToTray} title="Minimize to Tray">
|
||||||
_
|
_
|
||||||
</button>
|
</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>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Settings.css';
|
import './Settings.css';
|
||||||
|
|
||||||
function Settings() {
|
function Settings({ settings, setSettings }) {
|
||||||
|
// Handler for checkbox changes
|
||||||
|
const handleSettingChange = (settingName) => {
|
||||||
|
setSettings({
|
||||||
|
...settings,
|
||||||
|
[settingName]: !settings[settingName]
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="settings-container">
|
<div className="settings-container">
|
||||||
<h2 className="content-title">Settings</h2>
|
<h2 className="content-title">Settings</h2>
|
||||||
@@ -10,13 +18,21 @@ function Settings() {
|
|||||||
<h3>Application Settings</h3>
|
<h3>Application Settings</h3>
|
||||||
<div className="setting-item">
|
<div className="setting-item">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={settings.startWithWindows}
|
||||||
|
onChange={() => handleSettingChange('startWithWindows')}
|
||||||
|
/>
|
||||||
Start with Windows
|
Start with Windows
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div className="setting-item">
|
<div className="setting-item">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" checked />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={settings.minimizeToTrayOnClose}
|
||||||
|
onChange={() => handleSettingChange('minimizeToTrayOnClose')}
|
||||||
|
/>
|
||||||
Minimize to tray on close
|
Minimize to tray on close
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -26,7 +42,11 @@ function Settings() {
|
|||||||
<h3>Cursor Settings</h3>
|
<h3>Cursor Settings</h3>
|
||||||
<div className="setting-item">
|
<div className="setting-item">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" checked />
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={settings.autoApplyCursorOnSelection}
|
||||||
|
onChange={() => handleSettingChange('autoApplyCursorOnSelection')}
|
||||||
|
/>
|
||||||
Auto-apply cursor on selection
|
Auto-apply cursor on selection
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user