mirror of
https://github.com/0PandaDEV/Qopy.git
synced 2025-04-22 05:34:04 +02:00
feat: integrate event tracking for hotkey actions, history management, and settings updates
This commit is contained in:
parent
3824f24be4
commit
f44be512fe
8 changed files with 149 additions and 36 deletions
40
src-tauri/Cargo.lock
generated
40
src-tauri/Cargo.lock
generated
|
@ -1643,6 +1643,21 @@ dependencies = [
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
|
@ -1729,6 +1744,7 @@ version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"futures-macro",
|
"futures-macro",
|
||||||
|
@ -4081,6 +4097,7 @@ dependencies = [
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
|
"tauri-plugin-aptabase",
|
||||||
"tauri-plugin-autostart",
|
"tauri-plugin-autostart",
|
||||||
"tauri-plugin-clipboard",
|
"tauri-plugin-clipboard",
|
||||||
"tauri-plugin-dialog",
|
"tauri-plugin-dialog",
|
||||||
|
@ -4796,9 +4813,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.133"
|
version = "1.0.134"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377"
|
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 1.0.11",
|
"itoa 1.0.11",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -5664,6 +5681,25 @@ dependencies = [
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-plugin-aptabase"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "git+https://github.com/aptabase/tauri-plugin-aptabase?branch=v2#373abe1954bf20152082e506d36be07727259bb5"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"log",
|
||||||
|
"os_info",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"reqwest",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"sys-locale",
|
||||||
|
"tauri",
|
||||||
|
"tauri-plugin",
|
||||||
|
"time",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-autostart"
|
name = "tauri-plugin-autostart"
|
||||||
version = "2.2.0"
|
version = "2.2.0"
|
||||||
|
|
|
@ -13,7 +13,7 @@ tauri-build = { version = "2.0.3", features = [] }
|
||||||
tauri = { version = "2.1.1", features = [
|
tauri = { version = "2.1.1", features = [
|
||||||
"macos-private-api",
|
"macos-private-api",
|
||||||
"tray-icon",
|
"tray-icon",
|
||||||
"image-png",
|
"image-png"
|
||||||
] }
|
] }
|
||||||
tauri-plugin-sql = { version = "2.2.0", features = ["sqlite"] }
|
tauri-plugin-sql = { version = "2.2.0", features = ["sqlite"] }
|
||||||
tauri-plugin-autostart = "2.2.0"
|
tauri-plugin-autostart = "2.2.0"
|
||||||
|
@ -24,10 +24,11 @@ tauri-plugin-fs = "2.2.0"
|
||||||
tauri-plugin-clipboard = "2.1.11"
|
tauri-plugin-clipboard = "2.1.11"
|
||||||
tauri-plugin-prevent-default = "1.0.1"
|
tauri-plugin-prevent-default = "1.0.1"
|
||||||
tauri-plugin-global-shortcut = "2.2.0"
|
tauri-plugin-global-shortcut = "2.2.0"
|
||||||
|
tauri-plugin-aptabase = { git = "https://github.com/aptabase/tauri-plugin-aptabase", branch = "v2" }
|
||||||
sqlx = { version = "0.8.2", features = ["runtime-tokio-native-tls", "sqlite", "chrono"] }
|
sqlx = { version = "0.8.2", features = ["runtime-tokio-native-tls", "sqlite", "chrono"] }
|
||||||
serde = { version = "1.0.216", features = ["derive"] }
|
serde = { version = "1.0.216", features = ["derive"] }
|
||||||
tokio = { version = "1.42.0", features = ["full"] }
|
tokio = { version = "1.42.0", features = ["full"] }
|
||||||
serde_json = "1.0.133"
|
serde_json = "1.0.134"
|
||||||
rdev = "0.5.3"
|
rdev = "0.5.3"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
base64 = "0.22.1"
|
base64 = "0.22.1"
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use tauri_plugin_aptabase::EventTracker;
|
||||||
use base64::{engine::general_purpose::STANDARD, Engine};
|
use base64::{engine::general_purpose::STANDARD, Engine};
|
||||||
// use hyperpolyglot;
|
// use hyperpolyglot;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
|
@ -7,7 +8,7 @@ use sqlx::SqlitePool;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::{thread, time::Duration};
|
use std::{thread, time::Duration};
|
||||||
use tauri::{AppHandle, Emitter, Listener, Manager, Runtime};
|
use tauri::{AppHandle, Emitter, Listener, Manager};
|
||||||
use tauri_plugin_clipboard::Clipboard;
|
use tauri_plugin_clipboard::Clipboard;
|
||||||
use tokio::runtime::Runtime as TokioRuntime;
|
use tokio::runtime::Runtime as TokioRuntime;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -23,8 +24,8 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn write_and_paste<R: Runtime>(
|
pub async fn write_and_paste(
|
||||||
app_handle: tauri::AppHandle<R>,
|
app_handle: AppHandle,
|
||||||
content: String,
|
content: String,
|
||||||
content_type: String,
|
content_type: String,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
@ -80,39 +81,44 @@ pub async fn write_and_paste<R: Runtime>(
|
||||||
IS_PROGRAMMATIC_PASTE.store(false, Ordering::SeqCst);
|
IS_PROGRAMMATIC_PASTE.store(false, Ordering::SeqCst);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("clipboard_paste", Some(serde_json::json!({
|
||||||
|
"content_type": content_type
|
||||||
|
})));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
pub fn setup(app: &AppHandle) {
|
||||||
let app = app.clone();
|
let app_handle = app.clone();
|
||||||
let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime");
|
let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime");
|
||||||
|
|
||||||
app.clone().listen(
|
app_handle.clone().listen(
|
||||||
"plugin:clipboard://clipboard-monitor/update",
|
"plugin:clipboard://clipboard-monitor/update",
|
||||||
move |_event| {
|
move |_event| {
|
||||||
let app = app.clone();
|
let app_handle = app_handle.clone();
|
||||||
runtime.block_on(async move {
|
runtime.block_on(async move {
|
||||||
if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) {
|
if IS_PROGRAMMATIC_PASTE.load(Ordering::SeqCst) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clipboard = app.state::<Clipboard>();
|
let clipboard = app_handle.state::<Clipboard>();
|
||||||
let available_types = clipboard.available_types().unwrap();
|
let available_types = clipboard.available_types().unwrap();
|
||||||
|
|
||||||
let (app_name, app_icon) = get_app_info();
|
let (app_name, app_icon) = get_app_info();
|
||||||
|
|
||||||
match get_pool(&app).await {
|
match get_pool(&app_handle).await {
|
||||||
Ok(pool) => {
|
Ok(pool) => {
|
||||||
if available_types.image {
|
if available_types.image {
|
||||||
println!("Handling image change");
|
println!("Handling image change");
|
||||||
if let Ok(image_data) = clipboard.read_image_base64() {
|
if let Ok(image_data) = clipboard.read_image_base64() {
|
||||||
let file_path = save_image_to_file(&app, &image_data)
|
let file_path = save_image_to_file(&app_handle, &image_data)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())
|
.map_err(|e| e.to_string())
|
||||||
.unwrap_or_else(|e| e);
|
.unwrap_or_else(|e| e);
|
||||||
let _ = db::history::add_history_item(
|
let _ = db::history::add_history_item(
|
||||||
|
app_handle.clone(),
|
||||||
pool,
|
pool,
|
||||||
HistoryItem::new(app_name, ContentType::Image, file_path, None, app_icon, None),
|
HistoryItem::new(app_name, ContentType::Image, file_path, None, app_icon, None)
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
} else if available_types.files {
|
} else if available_types.files {
|
||||||
|
@ -120,6 +126,7 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
||||||
if let Ok(files) = clipboard.read_files() {
|
if let Ok(files) = clipboard.read_files() {
|
||||||
for file in files {
|
for file in files {
|
||||||
let _ = db::history::add_history_item(
|
let _ = db::history::add_history_item(
|
||||||
|
app_handle.clone(),
|
||||||
pool.clone(),
|
pool.clone(),
|
||||||
HistoryItem::new(
|
HistoryItem::new(
|
||||||
app_name.clone(),
|
app_name.clone(),
|
||||||
|
@ -135,6 +142,7 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
||||||
} else if available_types.text {
|
} else if available_types.text {
|
||||||
println!("Handling text change");
|
println!("Handling text change");
|
||||||
if let Ok(text) = clipboard.read_text() {
|
if let Ok(text) = clipboard.read_text() {
|
||||||
|
let text = text.to_string();
|
||||||
let url_regex = Regex::new(r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$").unwrap();
|
let url_regex = Regex::new(r"^https?://(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&//=]*)$").unwrap();
|
||||||
|
|
||||||
if url_regex.is_match(&text) {
|
if url_regex.is_match(&text) {
|
||||||
|
@ -145,6 +153,7 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = db::history::add_history_item(
|
let _ = db::history::add_history_item(
|
||||||
|
app_handle.clone(),
|
||||||
pool,
|
pool,
|
||||||
HistoryItem::new(app_name, ContentType::Link, text, favicon, app_icon, None)
|
HistoryItem::new(app_name, ContentType::Link, text, favicon, app_icon, None)
|
||||||
).await;
|
).await;
|
||||||
|
@ -167,13 +176,15 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
||||||
).await;
|
).await;
|
||||||
} else*/ if crate::utils::commands::detect_color(&text) {
|
} else*/ if crate::utils::commands::detect_color(&text) {
|
||||||
let _ = db::history::add_history_item(
|
let _ = db::history::add_history_item(
|
||||||
|
app_handle.clone(),
|
||||||
pool,
|
pool,
|
||||||
HistoryItem::new(app_name, ContentType::Color, text, None, app_icon, None)
|
HistoryItem::new(app_name, ContentType::Color, text, None, app_icon, None)
|
||||||
).await;
|
).await;
|
||||||
} else {
|
} else {
|
||||||
let _ = db::history::add_history_item(
|
let _ = db::history::add_history_item(
|
||||||
|
app_handle.clone(),
|
||||||
pool,
|
pool,
|
||||||
HistoryItem::new(app_name, ContentType::Text, text, None, app_icon, None)
|
HistoryItem::new(app_name, ContentType::Text, text.clone(), None, app_icon, None)
|
||||||
).await;
|
).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,14 +198,20 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = app.emit("clipboard-content-updated", ());
|
let _ = app_handle.emit("clipboard-content-updated", ());
|
||||||
|
let _ = app_handle.track_event("clipboard_copied", Some(serde_json::json!({
|
||||||
|
"content_type": if available_types.image { "image" }
|
||||||
|
else if available_types.files { "files" }
|
||||||
|
else if available_types.text { "text" }
|
||||||
|
else { "unknown" }
|
||||||
|
})));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_pool<R: Runtime>(
|
async fn get_pool(
|
||||||
app_handle: &AppHandle<R>,
|
app_handle: &AppHandle,
|
||||||
) -> Result<tauri::State<'_, SqlitePool>, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<tauri::State<'_, SqlitePool>, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
Ok(app_handle.state::<SqlitePool>())
|
Ok(app_handle.state::<SqlitePool>())
|
||||||
}
|
}
|
||||||
|
@ -211,8 +228,8 @@ pub fn start_monitor(app_handle: AppHandle) -> Result<(), String> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn save_image_to_file<R: Runtime>(
|
async fn save_image_to_file(
|
||||||
app_handle: &AppHandle<R>,
|
app_handle: &AppHandle,
|
||||||
base64_data: &str,
|
base64_data: &str,
|
||||||
) -> Result<String, Box<dyn std::error::Error>> {
|
) -> Result<String, Box<dyn std::error::Error>> {
|
||||||
let app_data_dir = app_handle.path().app_data_dir().unwrap();
|
let app_data_dir = app_handle.path().app_data_dir().unwrap();
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use tauri_plugin_aptabase::EventTracker;
|
||||||
use crate::utils::commands::center_window_on_current_monitor;
|
use crate::utils::commands::center_window_on_current_monitor;
|
||||||
use global_hotkey::{
|
use global_hotkey::{
|
||||||
hotkey::{Code, HotKey, Modifiers},
|
hotkey::{Code, HotKey, Modifiers},
|
||||||
|
@ -142,4 +143,8 @@ fn handle_hotkey_event(app_handle: &AppHandle) {
|
||||||
|
|
||||||
center_window_on_current_monitor(&window);
|
center_window_on_current_monitor(&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("hotkey_triggered", Some(serde_json::json!({
|
||||||
|
"action": if window.is_visible().unwrap() { "hide" } else { "show" }
|
||||||
|
})));
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,14 @@ use tauri::{
|
||||||
tray::TrayIconBuilder,
|
tray::TrayIconBuilder,
|
||||||
Emitter, Manager,
|
Emitter, Manager,
|
||||||
};
|
};
|
||||||
|
use tauri_plugin_aptabase::EventTracker;
|
||||||
|
|
||||||
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let window = app.get_webview_window("main").unwrap();
|
let window = app.get_webview_window("main").unwrap();
|
||||||
let window_clone_for_tray = window.clone();
|
let is_visible = window.is_visible().unwrap();
|
||||||
|
let _ = app.track_event("tray_toggle", Some(serde_json::json!({
|
||||||
|
"action": if is_visible { "hide" } else { "show" }
|
||||||
|
})));
|
||||||
|
|
||||||
let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png");
|
let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png");
|
||||||
let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap();
|
let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap();
|
||||||
|
@ -24,20 +28,25 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
)
|
)
|
||||||
.on_menu_event(move |_app, event| match event.id().as_ref() {
|
.on_menu_event(move |_app, event| match event.id().as_ref() {
|
||||||
"quit" => {
|
"quit" => {
|
||||||
|
let _ = _app.track_event("app_quit", None);
|
||||||
std::process::exit(0);
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
"show" => {
|
"show" => {
|
||||||
let is_visible = window_clone_for_tray.is_visible().unwrap();
|
let _ = _app.track_event("tray_toggle", Some(serde_json::json!({
|
||||||
|
"action": if is_visible { "hide" } else { "show" }
|
||||||
|
})));
|
||||||
|
let is_visible = window.is_visible().unwrap();
|
||||||
if is_visible {
|
if is_visible {
|
||||||
window_clone_for_tray.hide().unwrap();
|
window.hide().unwrap();
|
||||||
} else {
|
} else {
|
||||||
window_clone_for_tray.show().unwrap();
|
window.show().unwrap();
|
||||||
window_clone_for_tray.set_focus().unwrap();
|
window.set_focus().unwrap();
|
||||||
}
|
}
|
||||||
window_clone_for_tray.emit("main_route", ()).unwrap();
|
window.emit("main_route", ()).unwrap();
|
||||||
}
|
}
|
||||||
"keybind" => {
|
"keybind" => {
|
||||||
window_clone_for_tray.emit("change_keybind", ()).unwrap();
|
let _ = _app.track_event("tray_keybind_change", None);
|
||||||
|
window.emit("change_keybind", ()).unwrap();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,6 +4,7 @@ use rand::distributions::Alphanumeric;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use sqlx::{Row, SqlitePool};
|
use sqlx::{Row, SqlitePool};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use tauri_plugin_aptabase::EventTracker;
|
||||||
|
|
||||||
pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
pub async fn initialize_history(pool: &SqlitePool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let id: String = thread_rng()
|
let id: String = thread_rng()
|
||||||
|
@ -53,6 +54,7 @@ pub async fn get_history(pool: tauri::State<'_, SqlitePool>) -> Result<Vec<Histo
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn add_history_item(
|
pub async fn add_history_item(
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
pool: tauri::State<'_, SqlitePool>,
|
pool: tauri::State<'_, SqlitePool>,
|
||||||
item: HistoryItem,
|
item: HistoryItem,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
@ -95,6 +97,10 @@ pub async fn add_history_item(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("history_item_added", Some(serde_json::json!({
|
||||||
|
"content_type": item.content_type.to_string()
|
||||||
|
})));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,6 +169,7 @@ pub async fn load_history_chunk(
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn delete_history_item(
|
pub async fn delete_history_item(
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
pool: tauri::State<'_, SqlitePool>,
|
pool: tauri::State<'_, SqlitePool>,
|
||||||
id: String,
|
id: String,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
@ -172,16 +179,23 @@ pub async fn delete_history_item(
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("history_item_deleted", None);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn clear_history(pool: tauri::State<'_, SqlitePool>) -> Result<(), String> {
|
pub async fn clear_history(
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
|
pool: tauri::State<'_, SqlitePool>
|
||||||
|
) -> Result<(), String> {
|
||||||
sqlx::query("DELETE FROM history")
|
sqlx::query("DELETE FROM history")
|
||||||
.execute(&*pool)
|
.execute(&*pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("history_cleared", None);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ use serde_json;
|
||||||
use sqlx::Row;
|
use sqlx::Row;
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tauri::{Emitter, Manager};
|
use tauri::{Emitter, Manager};
|
||||||
|
use tauri_plugin_aptabase::EventTracker;
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
struct KeybindSetting {
|
struct KeybindSetting {
|
||||||
|
@ -26,9 +27,16 @@ pub async fn initialize_settings(pool: &SqlitePool) -> Result<(), Box<dyn std::e
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn save_keybind(
|
pub async fn save_keybind(
|
||||||
app_handle: tauri::AppHandle,
|
app_handle: tauri::AppHandle,
|
||||||
keybind: Vec<String>,
|
|
||||||
pool: tauri::State<'_, SqlitePool>,
|
pool: tauri::State<'_, SqlitePool>,
|
||||||
|
keybind: Vec<String>,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
|
let keybind_str = keybind.join("+");
|
||||||
|
let keybind_clone = keybind_str.clone();
|
||||||
|
|
||||||
|
app_handle
|
||||||
|
.emit("update-shortcut", &keybind_str)
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let json = serde_json::to_string(&keybind).map_err(|e| e.to_string())?;
|
let json = serde_json::to_string(&keybind).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES ('keybind', ?)")
|
sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES ('keybind', ?)")
|
||||||
|
@ -37,10 +45,9 @@ pub async fn save_keybind(
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let keybind_str = keybind.join("+");
|
let _ = app_handle.track_event("keybind_saved", Some(serde_json::json!({
|
||||||
app_handle
|
"keybind": keybind_clone
|
||||||
.emit("update-shortcut", keybind_str)
|
})));
|
||||||
.map_err(|e| e.to_string())?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -61,17 +68,22 @@ pub async fn get_setting(
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn save_setting(
|
pub async fn save_setting(
|
||||||
|
app_handle: tauri::AppHandle,
|
||||||
pool: tauri::State<'_, SqlitePool>,
|
pool: tauri::State<'_, SqlitePool>,
|
||||||
key: String,
|
key: String,
|
||||||
value: String,
|
value: String,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)")
|
sqlx::query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)")
|
||||||
.bind(key)
|
.bind(key.clone())
|
||||||
.bind(value)
|
.bind(value)
|
||||||
.execute(&*pool)
|
.execute(&*pool)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let _ = app_handle.track_event("setting_saved", Some(serde_json::json!({
|
||||||
|
"key": key
|
||||||
|
})));
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,19 @@ mod api;
|
||||||
mod db;
|
mod db;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
||||||
use sqlx::sqlite::SqlitePoolOptions;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
use tauri::WebviewUrl;
|
use tauri::WebviewUrl;
|
||||||
use tauri::WebviewWindow;
|
use tauri::WebviewWindow;
|
||||||
|
use sqlx::sqlite::SqlitePoolOptions;
|
||||||
use tauri_plugin_autostart::MacosLauncher;
|
use tauri_plugin_autostart::MacosLauncher;
|
||||||
use tauri_plugin_prevent_default::Flags;
|
use tauri_plugin_prevent_default::Flags;
|
||||||
|
use tauri_plugin_aptabase::{EventTracker, InitOptions};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
let runtime = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");
|
||||||
|
let _guard = runtime.enter();
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_clipboard::init())
|
.plugin(tauri_plugin_clipboard::init())
|
||||||
.plugin(tauri_plugin_os::init())
|
.plugin(tauri_plugin_os::init())
|
||||||
|
@ -23,6 +27,19 @@ fn main() {
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_updater::Builder::default().build())
|
.plugin(tauri_plugin_updater::Builder::default().build())
|
||||||
|
.plugin(tauri_plugin_aptabase::Builder::new("A-SH-8937252746")
|
||||||
|
.with_options(InitOptions {
|
||||||
|
host: Some("https://aptabase.pandadev.net".to_string()),
|
||||||
|
flush_interval: None,
|
||||||
|
})
|
||||||
|
.with_panic_hook(Box::new(|client, info, msg| {
|
||||||
|
let location = info.location().map(|loc| format!("{}:{}:{}", loc.file(), loc.line(), loc.column())).unwrap_or_else(|| "".to_string());
|
||||||
|
|
||||||
|
let _ = client.track_event("panic", Some(serde_json::json!({
|
||||||
|
"info": format!("{} ({})", msg, location),
|
||||||
|
})));
|
||||||
|
}))
|
||||||
|
.build())
|
||||||
.plugin(tauri_plugin_autostart::init(
|
.plugin(tauri_plugin_autostart::init(
|
||||||
MacosLauncher::LaunchAgent,
|
MacosLauncher::LaunchAgent,
|
||||||
Some(vec![]),
|
Some(vec![]),
|
||||||
|
@ -85,6 +102,8 @@ fn main() {
|
||||||
utils::commands::center_window_on_current_monitor(&main_window);
|
utils::commands::center_window_on_current_monitor(&main_window);
|
||||||
main_window.hide()?;
|
main_window.hide()?;
|
||||||
|
|
||||||
|
let _ = app.track_event("app_started", None);
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
api::updater::check_for_updates(app_handle).await;
|
api::updater::check_for_updates(app_handle).await;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue