Skip to content

Commit 266b6ff

Browse files
committed
restructure
1 parent 96f9f47 commit 266b6ff

12 files changed

+159
-104
lines changed

src-tauri/Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ rust-version = "1.70"
1010
tauri-build = { version = "2.0.0-rc.6", features = [] }
1111

1212
[dependencies]
13-
tauri = { version = "2.0.0-rc.6", features = ["tray-icon", "image-png"] }
13+
tauri = { version = "2.0.0-rc.6", features = [ "macos-private-api", "tray-icon", "image-png"] }
1414
tauri-plugin-sql = {version = "2.0.0-rc.0", features = ["sqlite"] }
1515
tauri-plugin-autostart = "2.0.0-rc.0"
1616
tauri-plugin-os = "2.0.0-rc.0"
@@ -31,6 +31,7 @@ url = "2.5.2"
3131
regex = "1"
3232
sha2 = "0.10.6"
3333
lazy_static = "1.4.0"
34+
time = "0.3"
3435

3536
[features]
3637
custom-protocol = ["tauri/custom-protocol"]

src-tauri/src/clipboard.rs src-tauri/src/api/clipboard.rs

+34-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use base64::Engine;
22
use base64::engine::general_purpose::STANDARD;
3-
use tauri::{AppHandle, Manager, Runtime, Emitter, Listener};
3+
use tauri::{AppHandle, Manager, Emitter, Listener};
44
use tauri_plugin_clipboard::Clipboard;
55
use tokio::runtime::Runtime as TokioRuntime;
66
use regex::Regex;
@@ -16,14 +16,20 @@ use sha2::{Sha256, Digest};
1616
use rdev::{simulate, Key, EventType};
1717
use lazy_static::lazy_static;
1818
use image::ImageFormat;
19-
20-
lazy_static! {
21-
static ref APP_DATA_DIR: Mutex<Option<std::path::PathBuf>> = Mutex::new(None);
22-
}
23-
24-
pub fn set_app_data_dir(path: std::path::PathBuf) {
25-
let mut dir = APP_DATA_DIR.lock().unwrap();
26-
*dir = Some(path);
19+
use tauri::plugin::TauriPlugin;
20+
21+
pub fn init() -> TauriPlugin<tauri::Wry> {
22+
tauri::plugin::Builder::new("clipboard")
23+
.invoke_handler(tauri::generate_handler![
24+
read_image,
25+
simulate_paste,
26+
get_image_path
27+
])
28+
.setup(|app_handle, _api| {
29+
setup(app_handle.clone());
30+
Ok(())
31+
})
32+
.build()
2733
}
2834

2935
#[tauri::command]
@@ -58,7 +64,15 @@ pub fn get_image_path(app_handle: tauri::AppHandle, filename: String) -> String
5864
image_path.to_str().unwrap_or("").to_string()
5965
}
6066

61-
pub fn setup<R: Runtime>(app: &AppHandle<R>) {
67+
#[tauri::command]
68+
pub fn start_monitor(app_handle: tauri::AppHandle) -> Result<(), String> {
69+
let clipboard = app_handle.state::<Clipboard>();
70+
clipboard.start_monitor(app_handle.clone()).map_err(|e| e.to_string())?;
71+
app_handle.emit("plugin:clipboard://clipboard-monitor/status", true).map_err(|e| e.to_string())?;
72+
Ok(())
73+
}
74+
75+
fn setup<R: tauri::Runtime>(app: AppHandle<R>) {
6276
let app = app.clone();
6377
let runtime = TokioRuntime::new().expect("Failed to create Tokio runtime");
6478

@@ -110,14 +124,14 @@ pub fn setup<R: Runtime>(app: &AppHandle<R>) {
110124
});
111125
}
112126

113-
async fn get_pool<R: Runtime>(app_handle: &AppHandle<R>) -> Result<SqlitePool, Box<dyn std::error::Error + Send + Sync>> {
127+
async fn get_pool<R: tauri::Runtime>(app_handle: &tauri::AppHandle<R>) -> Result<SqlitePool, Box<dyn std::error::Error + Send + Sync>> {
114128
let app_data_dir = app_handle.path().app_data_dir().expect("Failed to get app data directory");
115129
let db_path = app_data_dir.join("data.db");
116130
let database_url = format!("sqlite:{}", db_path.to_str().unwrap());
117131
SqlitePool::connect(&database_url).await.map_err(|e| Box::new(e) as Box<dyn std::error::Error + Send + Sync>)
118132
}
119133

120-
async fn insert_content_if_not_exists<R: Runtime>(app_handle: AppHandle<R>, pool: SqlitePool, content_type: &str, content: String) {
134+
async fn insert_content_if_not_exists<R: tauri::Runtime>(app_handle: tauri::AppHandle<R>, pool: SqlitePool, content_type: &str, content: String) {
121135
let last_content: Option<String> = sqlx::query_scalar(
122136
"SELECT content FROM history WHERE content_type = ? ORDER BY timestamp DESC LIMIT 1",
123137
)
@@ -177,7 +191,7 @@ async fn insert_content_if_not_exists<R: Runtime>(app_handle: AppHandle<R>, pool
177191
}
178192
}
179193

180-
async fn save_image<R: Runtime>(app_handle: &AppHandle<R>, base64_image: &str) -> Result<String, Box<dyn std::error::Error>> {
194+
async fn save_image<R: tauri::Runtime>(app_handle: &tauri::AppHandle<R>, base64_image: &str) -> Result<String, Box<dyn std::error::Error>> {
181195
let image_data = STANDARD.decode(base64_image)?;
182196
let mut hasher = Sha256::new();
183197
hasher.update(&image_data);
@@ -212,10 +226,11 @@ async fn fetch_favicon_as_base64(url: url::Url) -> Result<Option<String>, Box<dy
212226
}
213227
}
214228

215-
#[tauri::command]
216-
pub fn start_monitor(app_handle: AppHandle) -> Result<(), String> {
217-
let clipboard = app_handle.state::<Clipboard>();
218-
clipboard.start_monitor(app_handle.clone()).map_err(|e| e.to_string())?;
219-
app_handle.emit("plugin:clipboard://clipboard-monitor/status", true).map_err(|e| e.to_string())?;
220-
Ok(())
229+
lazy_static! {
230+
static ref APP_DATA_DIR: Mutex<Option<std::path::PathBuf>> = Mutex::new(None);
231+
}
232+
233+
pub fn set_app_data_dir(path: std::path::PathBuf) {
234+
let mut dir = APP_DATA_DIR.lock().unwrap();
235+
*dir = Some(path);
221236
}

src-tauri/src/database.rs src-tauri/src/api/database.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1+
use tauri::plugin::TauriPlugin;
2+
use tauri::{AppHandle, Manager, Emitter};
13
use sqlx::sqlite::SqlitePoolOptions;
24
use std::fs;
35
use tokio::runtime::Runtime;
4-
use tauri::Manager;
56
use rand::{thread_rng, Rng};
67
use rand::distributions::Alphanumeric;
78

8-
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
9+
pub fn init() -> TauriPlugin<tauri::Wry> {
10+
tauri::plugin::Builder::new("database")
11+
.setup(|app_handle: &AppHandle, _api| {
12+
setup(app_handle)?;
13+
Ok(())
14+
})
15+
.build()
16+
}
17+
18+
fn setup(app: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
919
let rt = Runtime::new().expect("Failed to create Tokio runtime");
1020

1121
let app_data_dir = app.path().app_data_dir().unwrap();
@@ -66,5 +76,7 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
6676
app.manage(pool);
6777
app.manage(rt);
6878

79+
app.emit("database_initialized", ()).expect("Failed to emit database_initialized event");
80+
6981
Ok(())
7082
}

src-tauri/src/hotkeys.rs src-tauri/src/api/hotkeys.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
use rdev::{listen, EventType, Key};
1+
use tauri::plugin::TauriPlugin;
22
use tauri::Manager;
3+
use rdev::{listen, EventType, Key};
4+
use crate::utils::commands;
35

4-
use crate::center_window_on_current_monitor;
6+
pub fn init() -> TauriPlugin<tauri::Wry> {
7+
tauri::plugin::Builder::new("hotkeys")
8+
.setup(|app, _| {
9+
setup(app.app_handle().clone());
10+
Ok(())
11+
})
12+
.build()
13+
}
514

6-
pub fn setup(app_handle: tauri::AppHandle) {
15+
fn setup(app_handle: tauri::AppHandle) {
716
std::thread::spawn(move || {
817
let mut meta_pressed = false;
918
listen(move |event| {
@@ -20,7 +29,7 @@ pub fn setup(app_handle: tauri::AppHandle) {
2029
let window = app_handle.get_webview_window("main").unwrap();
2130
window.show().unwrap();
2231
window.set_focus().unwrap();
23-
center_window_on_current_monitor(&window);
32+
commands::center_window_on_current_monitor(&window);
2433
}
2534
}
2635
_ => {}

src-tauri/src/api/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pub mod updater;
2+
pub mod clipboard;
3+
pub mod database;
4+
pub mod tray;
5+
pub mod hotkeys;

src-tauri/src/tray.rs src-tauri/src/api/tray.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
1-
use tauri::{
2-
Manager,
3-
menu::{MenuBuilder, MenuItemBuilder},
4-
tray::{MouseButton, TrayIconBuilder, TrayIconEvent},
5-
};
1+
use tauri::AppHandle;
2+
use tauri::plugin::TauriPlugin;
3+
use tauri::Manager;
4+
use tauri::menu::{MenuBuilder, MenuItemBuilder};
5+
use tauri::tray::{MouseButton, TrayIconBuilder, TrayIconEvent};
66

7-
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
7+
pub fn init() -> TauriPlugin<tauri::Wry> {
8+
tauri::plugin::Builder::new("tray")
9+
.setup(|app, _api| {
10+
setup(app)?;
11+
Ok(())
12+
})
13+
.build()
14+
}
15+
16+
fn setup(app: &AppHandle) -> Result<(), Box<dyn std::error::Error>> {
817
let window = app.get_webview_window("main").unwrap();
918
let window_clone_for_tray = window.clone();
1019
let window_clone_for_click = window.clone();
1120

12-
let icon_bytes = include_bytes!("../icons/Square71x71Logo.png");
21+
let icon_bytes = include_bytes!("../../icons/Square71x71Logo.png");
1322
let icon = tauri::image::Image::from_bytes(icon_bytes).unwrap();
1423

1524
let _tray = TrayIconBuilder::new()

src-tauri/src/updater.rs src-tauri/src/api/updater.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1-
use tauri::{AppHandle, async_runtime};
1+
use tauri::plugin::TauriPlugin;
2+
use tauri::AppHandle;
23
use tauri_plugin_dialog::{DialogExt, MessageDialogKind};
34
use tauri_plugin_updater::UpdaterExt;
5+
use tokio;
46

7+
pub fn init() -> TauriPlugin<tauri::Wry> {
8+
tauri::plugin::Builder::new("updater")
9+
.invoke_handler(tauri::generate_handler![check_for_updates])
10+
.build()
11+
}
512

13+
#[tauri::command]
614
pub async fn check_for_updates(app: AppHandle) {
715
println!("Checking for updates...");
816

@@ -28,7 +36,7 @@ pub async fn check_for_updates(app: AppHandle) {
2836
if !response {
2937
return;
3038
}
31-
async_runtime::spawn(async move {
39+
tokio::spawn(async move {
3240
if let Err(e) = update.download_and_install(|_, _| {}, || {}).await {
3341
println!("Error installing new update: {:?}", e);
3442
app.dialog().message(
@@ -43,4 +51,4 @@ pub async fn check_for_updates(app: AppHandle) {
4351
println!("Failed to check for updates: {:?}", e);
4452
}
4553
}
46-
}
54+
}

src-tauri/src/main.rs

+29-65
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,13 @@
33
windows_subsystem = "windows"
44
)]
55

6-
mod clipboard;
7-
mod database;
8-
mod hotkeys;
9-
mod tray;
10-
mod updater;
6+
mod api;
7+
mod utils;
118

12-
use tauri::Manager;
13-
use tauri::PhysicalPosition;
9+
use tauri::{Manager, Listener};
1410
use tauri_plugin_autostart::MacosLauncher;
1511
use tauri_plugin_prevent_default::Flags;
1612

17-
pub fn center_window_on_current_monitor(window: &tauri::WebviewWindow) {
18-
if let Some(monitor) = window.available_monitors().unwrap().iter().find(|m| {
19-
let primary_monitor = window
20-
.primary_monitor()
21-
.unwrap()
22-
.expect("Failed to get primary monitor");
23-
let mouse_position = primary_monitor.position();
24-
let monitor_position = m.position();
25-
let monitor_size = m.size();
26-
mouse_position.x >= monitor_position.x
27-
&& mouse_position.x < monitor_position.x + monitor_size.width as i32
28-
&& mouse_position.y >= monitor_position.y
29-
&& mouse_position.y < monitor_position.y + monitor_size.height as i32
30-
}) {
31-
let monitor_size = monitor.size();
32-
let window_size = window.outer_size().unwrap();
33-
34-
let x = (monitor_size.width as i32 - window_size.width as i32) / 2;
35-
let y = (monitor_size.height as i32 - window_size.height as i32) / 2;
36-
37-
window
38-
.set_position(PhysicalPosition::new(
39-
monitor.position().x + x,
40-
monitor.position().y + y,
41-
))
42-
.unwrap();
43-
}
44-
}
45-
4613
fn main() {
4714
tauri::Builder::default()
4815
.plugin(tauri_plugin_clipboard::init())
@@ -54,58 +21,55 @@ fn main() {
5421
MacosLauncher::LaunchAgent,
5522
Some(vec![]),
5623
))
24+
.plugin(api::updater::init())
25+
.plugin(api::database::init())
26+
.plugin(api::tray::init())
27+
.plugin(api::hotkeys::init())
28+
.plugin(api::clipboard::init())
5729
.plugin(
5830
tauri_plugin_prevent_default::Builder::new()
5931
.with_flags(Flags::all().difference(Flags::CONTEXT_MENU))
6032
.build(),
6133
)
6234
.setup(|app| {
6335
let app_handle = app.handle().clone();
64-
65-
hotkeys::setup(app_handle.clone());
66-
tray::setup(app)?;
67-
database::setup(app)?;
68-
clipboard::setup(app.handle());
69-
let _ = clipboard::start_monitor(app_handle.clone());
70-
71-
if let Some(window) = app.get_webview_window("main") {
72-
center_window_on_current_monitor(&window);
73-
window.hide().unwrap();
74-
}
75-
76-
// #[cfg(dev)]
77-
// {
78-
// let window = app.get_webview_window("main").unwrap();
79-
// window.open_devtools();
80-
// window.close_devtools();
81-
// }
82-
36+
8337
let app_data_dir = app
8438
.path()
8539
.app_data_dir()
8640
.expect("Failed to get app data directory");
87-
clipboard::set_app_data_dir(app_data_dir);
41+
api::clipboard::set_app_data_dir(app_data_dir);
42+
43+
if let Some(window) = app.get_webview_window("main") {
44+
utils::commands::center_window_on_current_monitor(&window);
45+
window.hide().unwrap();
46+
}
8847

48+
let update_handle = app_handle.clone();
8949
tauri::async_runtime::spawn(async move {
90-
updater::check_for_updates(app_handle).await;
50+
api::updater::check_for_updates(update_handle).await;
51+
});
52+
53+
let monitor_handle = app_handle.clone();
54+
app_handle.listen("database_initialized", move |_| {
55+
let _ = api::clipboard::start_monitor(monitor_handle.clone());
9156
});
9257

9358
Ok(())
9459
})
95-
.on_window_event(|app, event| match event {
60+
.on_window_event(|app, event| {
9661
#[cfg(not(dev))]
97-
tauri::WindowEvent::Focused(false) => {
62+
if let WindowEvent::Focused(false) = event {
9863
if let Some(window) = app.get_webview_window("main") {
99-
window.hide().unwrap();
64+
let _ = window.hide();
10065
}
10166
}
102-
_ => {}
10367
})
10468
.invoke_handler(tauri::generate_handler![
105-
clipboard::simulate_paste,
106-
clipboard::get_image_path,
107-
clipboard::read_image
69+
api::clipboard::simulate_paste,
70+
api::clipboard::get_image_path,
71+
api::clipboard::read_image
10872
])
10973
.run(tauri::generate_context!())
11074
.expect("error while running tauri application");
111-
}
75+
}

0 commit comments

Comments
 (0)