Skip to content

Commit fc369a2

Browse files
committed
feat: support tray menu screenshot action
1 parent 8ea099c commit fc369a2

File tree

15 files changed

+194
-206
lines changed

15 files changed

+194
-206
lines changed

src-tauri/src/cmd/screenshot.rs

Lines changed: 10 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,19 @@
1-
use std::{
2-
path::PathBuf,
3-
process::Command,
4-
thread,
5-
time::{Duration, Instant},
6-
};
7-
8-
use chrono::Local;
9-
use tauri::{Manager, Runtime};
10-
use tauri_plugin_store::StoreExt;
1+
use crate::platform;
112

123
#[tauri::command]
13-
pub async fn capture_screen<R: Runtime>(
14-
app_handle: tauri::AppHandle<R>,
15-
path: String,
16-
) -> Result<String, String> {
17-
let start = Instant::now();
18-
19-
let images_dir = get_images_dir(app_handle, path)?;
20-
21-
println!("images_dir: {:?}", images_dir);
22-
std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
23-
24-
let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
25-
let output_path = images_dir.join(&filename);
26-
27-
Command::new("screencapture")
28-
.arg("-x")
29-
.arg(output_path.to_str().unwrap())
30-
.output()
31-
.map_err(|e| e.to_string())?;
32-
33-
println!("capture_screen 运行耗时: {:?}", start.elapsed());
34-
Ok(filename)
4+
pub async fn capture_screen(app_handle: tauri::AppHandle, path: String) -> Result<String, String> {
5+
let filename = platform::capture_screen(&app_handle, path).await?;
6+
Ok(filename)
357
}
368

379
#[tauri::command]
38-
pub async fn capture_select<R: Runtime>(
39-
app_handle: tauri::AppHandle<R>,
40-
path: String,
41-
) -> Result<String, String> {
42-
let start = Instant::now();
43-
44-
let images_dir = get_images_dir(app_handle, path)?;
45-
46-
let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
47-
let output_path = images_dir.join(&filename);
48-
49-
Command::new("screencapture")
50-
.arg("-i")
51-
.arg("-x")
52-
.arg(output_path.to_str().unwrap())
53-
.output()
54-
.map_err(|e| e.to_string())?;
55-
56-
println!("capture_select 运行耗时: {:?}", start.elapsed());
57-
Ok(filename)
10+
pub async fn capture_select(app_handle: tauri::AppHandle, path: String) -> Result<String, String> {
11+
let filename = platform::capture_select(&app_handle, path).await?;
12+
Ok(filename)
5813
}
5914

6015
#[tauri::command]
61-
pub async fn capture_window<R: Runtime>(
62-
app_handle: tauri::AppHandle<R>,
63-
path: String,
64-
) -> Result<String, String> {
65-
let start = Instant::now();
66-
67-
let images_dir = get_images_dir(app_handle, path)?;
68-
69-
let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
70-
let output_path = images_dir.join(&filename);
71-
72-
Command::new("osascript")
73-
.args([
74-
"-e",
75-
"tell application \"System Events\" to key code 48 using {command down}",
76-
]) // Cmd+Tab
77-
.output()
78-
.map_err(|e| e.to_string())?;
79-
80-
thread::sleep(Duration::from_secs(1));
81-
82-
let output = Command::new("screencapture")
83-
.args([
84-
"-iw", // 交互式窗口选择
85-
"-t",
86-
"png", // 明确指定 PNG 格式
87-
"-C", // 捕获鼠标光标
88-
"-o", // 不包含窗口阴影
89-
"-T",
90-
"0", // 没有延迟
91-
output_path.to_str().unwrap(),
92-
])
93-
.output()
94-
.map_err(|e| e.to_string())?;
95-
96-
if !output.status.success() {
97-
println!("screencapture -wx 失败: {:?}", output.status);
98-
}
99-
100-
println!("capture_window 运行耗时: {:?}", start.elapsed());
101-
102-
Ok(filename)
103-
}
104-
105-
pub fn get_images_dir<R: Runtime>(
106-
app_handle: tauri::AppHandle<R>,
107-
path: String,
108-
) -> Result<PathBuf, String> {
109-
let store = app_handle
110-
.get_store("settings.json")
111-
.ok_or_else(|| "Could not get settings store".to_string())?;
112-
113-
let screenshot_path = store
114-
.get("screenshot_path")
115-
.ok_or_else(|| "Screenshot path not found in settings".to_string())?;
116-
println!("screenshot_path: {:?}", screenshot_path);
117-
118-
// get value from Option<JsonValue>
119-
let screenshot_path = screenshot_path
120-
.as_object()
121-
.and_then(|obj| obj.get("value"))
122-
.and_then(|value| value.as_str())
123-
.unwrap();
124-
125-
// 获取 AppLocalData 路径
126-
// 如果 screenshot_path 为空,则使用 app_local_data
127-
let app_local_data = if screenshot_path.is_empty() {
128-
app_handle.path().app_local_data_dir().unwrap()
129-
} else {
130-
PathBuf::from(screenshot_path)
131-
};
132-
println!("app_local_data: {:?}", app_local_data);
133-
134-
// 创建 images 文件夹
135-
// path 如果为空,则使用 app_local_data
136-
let images_dir = if path.is_empty() {
137-
app_local_data
138-
} else {
139-
app_local_data.join(path)
140-
};
141-
142-
println!("images_dir: {:?}", images_dir);
143-
std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
144-
145-
// let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
146-
// let output_path = images_dir.join(&filename);
147-
148-
Ok(images_dir)
16+
pub async fn capture_window(app_handle: tauri::AppHandle, path: String) -> Result<String, String> {
17+
let filename = platform::capture_window(&app_handle, path).await?;
18+
Ok(filename)
14919
}

src-tauri/src/cmd/window.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use tauri::{AppHandle, Manager};
1+
use tauri::AppHandle;
22

33
use crate::window;
44

@@ -10,6 +10,7 @@ pub fn show_preview_window(app: AppHandle, path: String) -> Result<String, Strin
1010

1111
#[tauri::command]
1212
pub fn hide_preview_window(app: AppHandle) -> Result<(), String> {
13+
println!("hide_preview_window");
1314
window::hide_preview_window(&app);
1415
Ok(())
1516
}

src-tauri/src/cmd/xcreenshot.rs

Lines changed: 6 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,22 @@ use std::path::PathBuf;
22

33
use chrono::Local;
44
use std::time::Instant;
5-
use tauri::{Manager, Runtime};
6-
use tauri_plugin_store::StoreExt;
75
use xcap::{Monitor, Window};
86

7+
use crate::common::get_images_dir;
8+
99
#[tauri::command]
10-
pub async fn xcap_window<R: Runtime>(
11-
app_handle: tauri::AppHandle<R>,
12-
path: String,
13-
) -> Result<String, String> {
14-
let images_dir = get_images_dir(app_handle, path).unwrap();
10+
pub async fn xcap_window(app_handle: tauri::AppHandle, path: String) -> Result<String, String> {
11+
let images_dir = get_images_dir(&app_handle, path).unwrap();
1512

1613
let filename = window_capture(images_dir)?;
1714

1815
Ok(filename)
1916
}
2017

2118
#[tauri::command]
22-
pub async fn xcap_monitor<R: Runtime>(
23-
app_handle: tauri::AppHandle<R>,
24-
path: String,
25-
) -> Result<String, String> {
26-
let images_dir = get_images_dir(app_handle, path).unwrap();
19+
pub async fn xcap_monitor(app_handle: tauri::AppHandle, path: String) -> Result<String, String> {
20+
let images_dir = get_images_dir(&app_handle, path).unwrap();
2721

2822
let filename = monitor_capture(images_dir)?;
2923

@@ -104,49 +98,3 @@ fn monitor_capture(path: PathBuf) -> Result<String, String> {
10498

10599
Ok(filename)
106100
}
107-
108-
pub fn get_images_dir<R: Runtime>(
109-
app_handle: tauri::AppHandle<R>,
110-
path: String,
111-
) -> Result<PathBuf, String> {
112-
let store = app_handle
113-
.get_store("settings.json")
114-
.ok_or_else(|| "Could not get settings store".to_string())?;
115-
116-
let screenshot_path = store
117-
.get("screenshot_path")
118-
.ok_or_else(|| "Screenshot path not found in settings".to_string())?;
119-
println!("screenshot_path: {:?}", screenshot_path);
120-
121-
// get value from Option<JsonValue>
122-
let screenshot_path = screenshot_path
123-
.as_object()
124-
.and_then(|obj| obj.get("value"))
125-
.and_then(|value| value.as_str())
126-
.unwrap();
127-
128-
// 获取 AppLocalData 路径
129-
// 如果 screenshot_path 为空,则使用 app_local_data
130-
let app_local_data = if screenshot_path.is_empty() {
131-
app_handle.path().app_local_data_dir().unwrap()
132-
} else {
133-
PathBuf::from(screenshot_path)
134-
};
135-
println!("app_local_data: {:?}", app_local_data);
136-
137-
// 创建 images 文件夹
138-
// path 如果为空,则使用 app_local_data
139-
let images_dir = if path.is_empty() {
140-
app_local_data
141-
} else {
142-
app_local_data.join(path)
143-
};
144-
145-
println!("images_dir: {:?}", images_dir);
146-
std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
147-
148-
// let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
149-
// let output_path = images_dir.join(&filename);
150-
151-
Ok(images_dir)
152-
}

src-tauri/src/common.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use std::path::PathBuf;
2+
3+
use tauri::Manager;
4+
use tauri_plugin_store::StoreExt;
5+
6+
pub fn get_images_dir(app_handle: &tauri::AppHandle, path: String) -> Result<PathBuf, String> {
7+
let store = app_handle
8+
.get_store("settings.json")
9+
.ok_or_else(|| "Could not get settings store".to_string())?;
10+
11+
let screenshot_path = store
12+
.get("screenshot_path")
13+
.ok_or_else(|| "Screenshot path not found in settings".to_string())?;
14+
println!("screenshot_path: {:?}", screenshot_path);
15+
16+
// get value from Option<JsonValue>
17+
let screenshot_path = screenshot_path
18+
.as_object()
19+
.and_then(|obj| obj.get("value"))
20+
.and_then(|value| value.as_str())
21+
.unwrap();
22+
23+
// 获取 AppLocalData 路径
24+
// 如果 screenshot_path 为空,则使用 app_local_data
25+
let app_local_data = if screenshot_path.is_empty() {
26+
app_handle.path().app_local_data_dir().unwrap()
27+
} else {
28+
PathBuf::from(screenshot_path)
29+
};
30+
println!("app_local_data: {:?}", app_local_data);
31+
32+
// 创建 images 文件夹
33+
// path 如果为空,则使用 app_local_data
34+
let images_dir = if path.is_empty() {
35+
app_local_data
36+
} else {
37+
app_local_data.join(path)
38+
};
39+
40+
println!("images_dir: {:?}", images_dir);
41+
std::fs::create_dir_all(&images_dir).map_err(|e| e.to_string())?;
42+
43+
// let filename = format!("screenshot_{}.png", Local::now().format("%Y%m%d_%H%M%S"));
44+
// let output_path = images_dir.join(&filename);
45+
46+
Ok(images_dir)
47+
}

src-tauri/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use tauri::Manager;
33
use tauri_plugin_store::StoreExt;
44

55
mod cmd;
6+
mod common;
67
mod constants;
78
mod menu;
89
mod platform;

src-tauri/src/menu.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use tauri::{
77
AppHandle, Manager,
88
};
99

10-
use crate::window;
10+
use crate::{platform, window};
1111

1212
#[derive(Debug, Display, EnumString)]
1313
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
@@ -162,22 +162,38 @@ fn handle_tray_menu_events(app: &AppHandle, event: MenuEvent) {
162162
match menu_id {
163163
MenuID::CAPTURE_SCREEN => {
164164
println!("Capture Screen");
165+
let _ = tauri::async_runtime::block_on(platform::capture_screen(
166+
&app,
167+
"images".to_string(),
168+
));
169+
window::hide_main_window(app);
170+
window::show_preview_window(app);
165171
}
166172
MenuID::CAPTURE_SELECT => {
167173
println!("Capture Select");
174+
let _ = tauri::async_runtime::block_on(platform::capture_select(
175+
&app,
176+
"images".to_string(),
177+
));
168178
window::hide_main_window(app);
169179
window::show_preview_window(app);
170180
}
171181
MenuID::CAPTURE_WINDOW => {
172182
println!("Capture Window");
183+
let _ = tauri::async_runtime::block_on(platform::capture_window(
184+
&app,
185+
"images".to_string(),
186+
));
187+
window::hide_main_window(app);
188+
window::show_preview_window(app);
173189
}
174190
MenuID::SHOW_MAIN_WINDOW => {
175191
println!("Show Home");
176-
window::show_main_window(app);
192+
window::show_main_window(&app);
177193
}
178194
MenuID::SHOW_SETTING_WINDOW => {
179195
println!("Setting Manager");
180-
window::show_setting_window(app);
196+
window::show_setting_window(&app);
181197
}
182198
MenuID::EXIT => {
183199
println!("Exit");

src-tauri/src/platform/linux/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod linux;
2+
3+
pub use linux::*;

src-tauri/src/platform/mac/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod screenshot;
2+
mod window;
3+
4+
pub use screenshot::*;
5+
pub use window::*;

0 commit comments

Comments
 (0)