2025-03-18 16:00:57 +13:00

125 lines
3.8 KiB
Rust

use config::Config;
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
use enigo::{
Direction::{Press, Release},
Enigo, Key, Keyboard,
};
use rdev::{listen, Event, EventType};
use std::sync::Mutex;
use std::thread;
use tauri::{ipc::Channel, Manager, State};
mod config;
struct AppState {
config: Config,
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
.plugin(tauri_plugin_fs::init())
.plugin(tauri_plugin_opener::init())
.invoke_handler(tauri::generate_handler![
get_config_path,
update_config,
get_default,
get_theme,
get_bind,
start_listener,
paste_text
])
.setup(|app| {
let config = config::Config::load_or_create(get_config_path()).unwrap();
let theme = &config.theme;
// Validate and set the theme
let themes = vec!["grey", "night", "day", "catppuccin_mocha"];
if themes.contains(&theme.as_str()) {
println!("Setting theme to: {}", theme);
app.manage(Mutex::new(AppState { config: config }));
} else {
println!(
"{}",
format!("Theme {} is invalid! Valid themes are: {:?}", theme, themes)
);
}
Ok(())
})
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
// Commands
// Config commands
// gross but i tried returning a struct and everything froze up
#[tauri::command]
fn get_config_path() -> std::path::PathBuf {
let config_dir = dirs::config_dir().expect("Config directory not found");
config_dir.join("copybot")
}
// update the app state with new config
#[tauri::command]
fn update_config(state: State<'_, Mutex<AppState>>) {
let mut state = state.lock().unwrap();
state.config = config::Config::load_or_create(get_config_path()).unwrap();
}
#[tauri::command]
fn get_default(state: State<'_, Mutex<AppState>>) -> Result<bool, bool> {
let default = state.lock().unwrap().config.default;
Ok(default)
}
#[tauri::command]
fn get_theme(state: State<'_, Mutex<AppState>>) -> Result<String, String> {
let theme = state.lock().unwrap().config.theme.clone();
Ok(theme)
}
#[tauri::command]
fn get_bind(state: State<'_, Mutex<AppState>>) -> Result<String, String> {
let bind = state.lock().unwrap().config.bind.clone();
Ok(bind)
}
// Input events
#[tauri::command]
fn start_listener(bind: String, channel: Channel<Event>) {
thread::spawn(move || {
println!("Started listening for bind: {:?}", bind);
listen(move |event| match event.event_type {
EventType::KeyPress(key) | EventType::KeyRelease(key) => {
if bind == serde_json::to_string(&key).unwrap().replace("\"", "") {
channel.send(event).unwrap()
};
}
_ => (),
})
});
}
#[tauri::command]
fn paste_text(state: State<'_, Mutex<AppState>>, text: String) {
println!("{}", text);
let mut enigo = Enigo::new(&enigo::Settings::default()).unwrap();
if state.lock().unwrap().config.shift_enter_newline {
for c in text.chars() {
if c == '\n' {
// Press Shift+Enter combination
enigo.key(Key::Shift, Press).unwrap();
enigo.key(Key::Return, Press).unwrap();
enigo.key(Key::Return, Release).unwrap();
enigo.key(Key::Shift, Release).unwrap();
} else {
// Type regular characters normally
enigo.text(&c.to_string()).unwrap();
}
}
} else {
enigo.text(text.as_str()).unwrap();
}
}