pake-cli 1.3.1 → 2.0.0-alpha7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,39 +1,5 @@
1
- /**
2
- * @typedef {string} KeyboardKey `event.key` 的代号,
3
- * 见 <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values>
4
- * @typedef {() => void} OnKeyDown 使用者按下 [CtrlKey] 或者 ⌘ [KeyboardKey]时应该执行的行为
5
- * 以 Ctrl键或者Meta 键 (⌘) 为首的快捷键清单。
6
- * 每个写在这里的 shortcuts 都会运行 {@link Event.preventDefault}.
7
- * @type {Record<KeyboardKey, OnKeyDown>}
8
- */
9
-
10
- const metaKeyShortcuts = {
11
- ArrowUp: () => scrollTo(0, 0),
12
- ArrowDown: () => scrollTo(0, document.body.scrollHeight),
13
- "[": () => window.history.back(),
14
- "]": () => window.history.forward(),
15
- r: () => window.location.reload(),
16
- "-": () => zoomOut(),
17
- "=": () => zoomIn(),
18
- "+": () => zoomIn(),
19
- 0: () => zoomCommon(() => "100%"),
20
- };
21
-
22
- const ctrlKeyShortcuts = {
23
- ArrowUp: () => scrollTo(0, 0),
24
- ArrowDown: () => scrollTo(0, document.body.scrollHeight),
25
- ArrowLeft: () => window.history.back(),
26
- ArrowRight: () => window.history.forward(),
27
- r: () => window.location.reload(),
28
- "-": () => zoomOut(),
29
- "=": () => zoomIn(),
30
- "+": () => zoomIn(),
31
- 0: () => zoomCommon(() => "100%"),
32
- };
33
-
34
- window.addEventListener("DOMContentLoaded", (_event) => {
35
- const style = document.createElement("style");
36
- style.innerHTML = `
1
+ window.addEventListener('DOMContentLoaded', (_event) => {
2
+ const css = `
37
3
  #page #footer-wrapper,
38
4
  .drawing-board .toolbar .toolbar-action,
39
5
  .c-swiper-container,
@@ -49,6 +15,8 @@ window.addEventListener("DOMContentLoaded", (_event) => {
49
15
  #masthead-ad,
50
16
  #app > header > div > div.menu,
51
17
  #root > div > div.fixed.top-0.left-0.w-64.h-screen.p-10.pb-0.flex.flex-col.justify-between > div > div.space-y-4 > a:nth-child(3),
18
+ #app > div.layout > div.main-container > div.side-bar > div,
19
+ #app > div.layout > div.main-container > div.side-bar > li.divider,
52
20
  #Rightbar > div:nth-child(6) > div.sidebar_compliance {
53
21
  display: none !important;
54
22
  }
@@ -68,7 +36,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
68
36
  }
69
37
 
70
38
  .fui-FluentProvider .fui-Button[data-testid="HomeButton"]{
71
- padding-top: 20px;
39
+ padding-top: 20px;
72
40
  }
73
41
 
74
42
  .chakra-ui-light #app .chakra-heading,
@@ -77,7 +45,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
77
45
  .chakra-ui-dark #app .chakra-stack,
78
46
  .app-main .sidebar-mouse-in-out,
79
47
  .chakra-modal__content-container .chakra-modal__header > div > div {
80
- padding-top: 10px;
48
+ padding-top: 10px;
81
49
  }
82
50
 
83
51
  #__next .overflow-hidden>.hidden.bg-gray-900 span.rounded-md.bg-yellow-200 {
@@ -89,7 +57,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
89
57
  }
90
58
 
91
59
  #__next .absolute .px-3.pt-2.pb-3.text-center {
92
- visibility: hidden;
60
+ visibility: hidden;
93
61
  }
94
62
 
95
63
  .lark > .dashboard-sidebar, .lark > .dashboard-sidebar > .sidebar-user-info , .lark > .dashboard-sidebar .index-module_wrapper_F-Wbq{
@@ -130,7 +98,8 @@ window.addEventListener("DOMContentLoaded", (_event) => {
130
98
  top: 30px;
131
99
  }
132
100
 
133
- .geist-page nav.dashboard_nav__PRmJv {
101
+ .geist-page nav.dashboard_nav__PRmJv,
102
+ #app > div.layout > div.header-container.showSearchBoxOrHeaderFixed > header > a {
134
103
  padding-top:10px;
135
104
  }
136
105
 
@@ -285,6 +254,29 @@ window.addEventListener("DOMContentLoaded", (_event) => {
285
254
  }
286
255
  }
287
256
 
257
+ @media (min-width:1024px){
258
+ #__next .text-base.lg\\:max-w-xl, #__next form.stretch.lg\\:max-w-2xl {
259
+ max-width: 44rem;
260
+ }
261
+ }
262
+
263
+ @media (min-width:1280px){
264
+ #__next .text-base.xl\\:max-w-3xl, #__next form.stretch.xl\\:max-w-3xl {
265
+ max-width: 48rem;
266
+ }
267
+ }
268
+
269
+ @media (min-width:640px){
270
+ #__next .sticky.top-0{
271
+ padding-top: 15px;
272
+ }
273
+ }
274
+
275
+ #__next .prose ol li p {
276
+ margin: 0;
277
+ display: inline;
278
+ }
279
+
288
280
  #pack-top-dom:active {
289
281
  cursor: grabbing;
290
282
  cursor: -webkit-grabbing;
@@ -297,109 +289,13 @@ window.addEventListener("DOMContentLoaded", (_event) => {
297
289
  width: 100%;
298
290
  height: 20px;
299
291
  cursor: grab;
300
- cursor: -webkit-grab;
292
+ -webkit-app-region: drag;
301
293
  user-select: none;
294
+ -webkit-user-select: none;
302
295
  z-index: 90000;
303
296
  }
304
297
  `;
305
- document.head.append(style);
306
- const topDom = document.createElement("div");
307
- topDom.id = "pack-top-dom";
308
- document.body.appendChild(topDom);
309
-
310
- const domEl = document.getElementById("pack-top-dom");
311
-
312
- domEl.addEventListener("mousedown", (e) => {
313
- e && e.preventDefault();
314
- if (e.buttons === 1 && e.detail !== 2) {
315
- window.ipc.postMessage("drag_window");
316
- }
317
- });
318
-
319
- domEl.addEventListener("touchstart", () => {
320
- window.ipc.postMessage("drag_window");
321
- });
322
-
323
- domEl.addEventListener("dblclick", () => {
324
- window.ipc.postMessage("fullscreen");
325
- });
326
-
327
- document.addEventListener("keyup", function (event) {
328
- const preventDefault = (f) => {
329
- event.preventDefault();
330
- f();
331
- };
332
- if (/windows|linux/i.test(navigator.userAgent)) {
333
- if (event.ctrlKey && event.key in ctrlKeyShortcuts) {
334
- preventDefault(ctrlKeyShortcuts[event.key]);
335
- }
336
- }
337
- if (/macintosh|mac os x/i.test(navigator.userAgent)) {
338
- if (event.metaKey && event.key in metaKeyShortcuts) {
339
- preventDefault(metaKeyShortcuts[event.key]);
340
- }
341
- }
342
- });
343
-
344
- document.addEventListener("click", (e) => {
345
- const origin = e.target.closest("a");
346
- if (origin && origin.href) {
347
- const target = origin.target
348
- origin.target = "_self";
349
- const hrefUrl = new URL(origin.href)
350
-
351
- if (
352
- window.location.host !== hrefUrl.host && // 如果 a 标签内链接的域名和当前页面的域名不一致 且
353
- target === '_blank' // a 标签内链接的 target 属性为 _blank 时
354
- ) {
355
- e.preventDefault();
356
- window.ipc.postMessage(`open_browser:${origin.href}`);
357
- }
358
- }
359
- });
298
+ const styleElement = document.createElement('style');
299
+ styleElement.innerHTML = css;
300
+ document.head.appendChild(styleElement);
360
301
  });
361
-
362
- setDefaultZoom();
363
-
364
- function setDefaultZoom() {
365
- const htmlZoom = window.localStorage.getItem("htmlZoom");
366
- if (htmlZoom) {
367
- document.getElementsByTagName("html")[0].style.zoom = htmlZoom;
368
- }
369
- }
370
-
371
- /**
372
- * @param {(htmlZoom: string) => string} [zoomRule]
373
- */
374
- function zoomCommon(zoomRule) {
375
- const htmlZoom = window.localStorage.getItem("htmlZoom") || "100%";
376
- const html = document.getElementsByTagName("html")[0];
377
- const zoom = zoomRule(htmlZoom);
378
- html.style.zoom = zoom;
379
- window.localStorage.setItem("htmlZoom", zoom);
380
- }
381
-
382
- function zoomIn() {
383
- zoomCommon((htmlZoom) => `${Math.min(parseInt(htmlZoom) + 10, 200)}%`);
384
- }
385
-
386
- function zoomOut() {
387
- zoomCommon((htmlZoom) => `${Math.max(parseInt(htmlZoom) - 10, 30)}%`);
388
- }
389
-
390
-
391
- function pakeToast(msg) {
392
- const m = document.createElement('div');
393
- m.innerHTML = msg;
394
- m.style.cssText = "max-width:60%;min-width: 180px;padding:0 8px;height: 36px;color: rgb(255, 255, 255);line-height: 36px;text-align: center;border-radius: 4px;position: fixed;bottom:16px;right: 16px;transform: translate(-50%, -50%);z-index: 999999;background: rgba(0, 0, 0,.9);font-size: 14px;";
395
- document.body.appendChild(m);
396
- setTimeout(function() {
397
- const d = 0.5;
398
- m.style.transition = 'transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
399
- m.style.opacity = '0';
400
- setTimeout(function() {
401
- document.body.removeChild(m)
402
- }, d * 1000);
403
- }, 2500);
404
- }
405
-
@@ -1,278 +1,73 @@
1
- // at the top of main.rs - that will prevent the console from showing
2
- #![windows_subsystem = "windows"]
3
- extern crate image;
4
-
5
- use dirs::download_dir;
6
- use std::path::PathBuf;
7
- use tauri_utils::config::{Config, WindowConfig};
8
- use wry::{
9
- application::{
10
- event::{Event, StartCause, WindowEvent},
11
- event_loop::{ControlFlow, EventLoop},
12
- menu::MenuType,
13
- window::{Fullscreen, Window, WindowBuilder},
14
- },
15
- webview::WebViewBuilder,
16
- };
17
-
18
- #[cfg(target_os = "macos")]
19
- use wry::application::{
20
- accelerator::{Accelerator, SysMods},
21
- keyboard::KeyCode,
22
- menu::{MenuBar as Menu, MenuItem, MenuItemAttributes},
23
- platform::macos::WindowBuilderExtMacOS,
24
- };
1
+ #![cfg_attr(
2
+ all(not(debug_assertions), target_os = "windows"),
3
+ windows_subsystem = "windows"
4
+ )]
5
+
6
+ mod app;
7
+ mod util;
8
+
9
+ use app::{invoke, menu, window};
10
+ use invoke::{download_file, drag_window, fullscreen, open_browser};
11
+ use menu::{get_menu, menu_event_handle};
12
+ use tauri_plugin_window_state::Builder as windowStatePlugin;
13
+ use util::{get_data_dir, get_pake_config};
14
+ use window::get_window;
15
+
16
+ pub fn run_app() {
17
+ let (pake_config, tauri_config) = get_pake_config();
18
+ let show_menu = pake_config.show_menu();
19
+ let menu = get_menu();
20
+ let data_dir = get_data_dir(tauri_config);
21
+
22
+ let mut tauri_app = tauri::Builder::default();
23
+
24
+ if show_menu {
25
+ tauri_app = tauri_app.menu(menu).on_menu_event(menu_event_handle);
26
+ }
25
27
 
26
- #[cfg(target_os = "windows")]
27
- use wry::application::window::Icon;
28
+ #[cfg(not(target_os = "macos"))]
29
+ {
30
+ use menu::{get_system_tray, system_tray_handle};
28
31
 
29
- #[cfg(any(target_os = "linux", target_os = "windows"))]
30
- use wry::webview::WebContext;
32
+ let show_system_tray = pake_config.show_system_tray();
33
+ let system_tray = get_system_tray(show_menu);
31
34
 
32
- enum UserEvent {
33
- DownloadStarted(String, String),
34
- DownloadComplete(Option<PathBuf>, bool),
35
- }
36
-
37
- fn main() -> wry::Result<()> {
38
- #[cfg(target_os = "macos")]
39
- let (menu_bar_menu, close_item) = {
40
- let mut menu_bar_menu = Menu::new();
41
- let mut first_menu = Menu::new();
42
- first_menu.add_native_item(MenuItem::Hide);
43
- first_menu.add_native_item(MenuItem::EnterFullScreen);
44
- first_menu.add_native_item(MenuItem::Minimize);
45
- first_menu.add_native_item(MenuItem::Separator);
46
- first_menu.add_native_item(MenuItem::Copy);
47
- first_menu.add_native_item(MenuItem::Cut);
48
- first_menu.add_native_item(MenuItem::Paste);
49
- first_menu.add_native_item(MenuItem::Undo);
50
- first_menu.add_native_item(MenuItem::Redo);
51
- first_menu.add_native_item(MenuItem::SelectAll);
52
- first_menu.add_native_item(MenuItem::Separator);
53
- let close_item = first_menu.add_item(
54
- MenuItemAttributes::new("CloseWindow")
55
- .with_accelerators(&Accelerator::new(SysMods::Cmd, KeyCode::KeyW)),
56
- );
57
- first_menu.add_native_item(MenuItem::Quit);
58
- menu_bar_menu.add_submenu("App", true, first_menu);
59
- (menu_bar_menu, close_item)
60
- };
35
+ if show_system_tray {
36
+ tauri_app = tauri_app
37
+ .system_tray(system_tray)
38
+ .on_system_tray_event(system_tray_handle);
39
+ }
40
+ }
61
41
 
62
- #[cfg(any(target_os = "linux", target_os = "windows"))]
63
- let (
64
- package_name,
65
- WindowConfig {
66
- url,
67
- width,
68
- height,
69
- resizable,
42
+ tauri_app
43
+ .plugin(windowStatePlugin::default().build())
44
+ .invoke_handler(tauri::generate_handler![
45
+ drag_window,
70
46
  fullscreen,
71
- ..
72
- },
73
- ) = {
74
- let (package_name, windows_config) = get_windows_config();
75
- (
76
- package_name
77
- .expect("can't get package name in config file")
78
- .to_lowercase(),
79
- windows_config.unwrap_or_default(),
80
- )
81
- };
82
-
83
- #[cfg(target_os = "macos")]
84
- let WindowConfig {
85
- url,
86
- width,
87
- height,
88
- resizable,
89
- transparent,
90
- fullscreen,
91
- ..
92
- } = get_windows_config().1.unwrap_or_default();
93
-
94
- let event_loop: EventLoop<UserEvent> = EventLoop::with_user_event();
95
- let proxy = event_loop.create_proxy();
96
- let common_window = WindowBuilder::new()
97
- .with_title("")
98
- .with_resizable(resizable)
99
- .with_fullscreen(if fullscreen {
100
- Some(Fullscreen::Borderless(None))
101
- } else {
102
- None
47
+ open_browser,
48
+ download_file
49
+ ])
50
+ .setup(|app| {
51
+ let _window = get_window(app, pake_config, data_dir);
52
+ // Prevent initial shaking
53
+ _window.show().unwrap();
54
+ Ok(())
103
55
  })
104
- .with_inner_size(wry::application::dpi::LogicalSize::new(width, height));
105
-
106
- #[cfg(target_os = "windows")]
107
- let window = {
108
- let mut icon_path = format!("png/{}_32.ico", package_name);
109
- // If there is no setting, use the default one.
110
- if !std::path::Path::new(&icon_path).exists() {
111
- icon_path = "png/icon_32.ico".to_string();
112
- }
113
- let icon = load_icon(std::path::Path::new(&icon_path));
114
- common_window
115
- .with_decorations(true)
116
- .with_window_icon(Some(icon))
117
- .build(&event_loop)
118
- .unwrap()
119
- };
120
-
121
- #[cfg(target_os = "linux")]
122
- let window = common_window.build(&event_loop).unwrap();
123
-
124
- #[cfg(target_os = "macos")]
125
- let window = common_window
126
- .with_fullsize_content_view(true)
127
- .with_titlebar_buttons_hidden(false)
128
- .with_titlebar_transparent(transparent)
129
- .with_title_hidden(true)
130
- .with_menu(menu_bar_menu)
131
- .build(&event_loop)
132
- .unwrap();
133
-
134
- // Handling events of JS -> Rust
135
- let handler = move |window: &Window, req: String| {
136
- if req == "drag_window" {
137
- let _ = window.drag_window();
138
- } else if req == "fullscreen" {
139
- let is_maximized = window.is_maximized();
140
- window.set_maximized(!is_maximized);
141
- } else if req.starts_with("open_browser") {
142
- let href = req.replace("open_browser:", "");
143
- webbrowser::open(&href).expect("no browser");
144
- }
145
- };
146
-
147
- let download_started = {
148
- let proxy = proxy.clone();
149
- move |uri: String, default_path: &mut PathBuf| {
150
- let path = download_dir()
151
- .unwrap()
152
- .join(default_path.display().to_string())
153
- .as_path()
154
- .to_path_buf();
155
- *default_path = path.clone();
156
- let submitted = proxy
157
- .send_event(UserEvent::DownloadStarted(uri, path.display().to_string()))
158
- .is_ok();
159
- submitted
160
- }
161
- };
162
-
163
- let download_completed = {
164
- move |_uri, path, success| {
165
- let _ = proxy.send_event(UserEvent::DownloadComplete(path, success));
166
- }
167
- };
168
-
169
- #[cfg(target_os = "macos")]
170
- let webview = {
171
- let user_agent_string = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.1 Safari/605.1.15";
172
- WebViewBuilder::new(window)?
173
- .with_user_agent(user_agent_string)
174
- .with_url(&url.to_string())?
175
- .with_devtools(cfg!(feature = "devtools"))
176
- .with_initialization_script(include_str!("pake.js"))
177
- .with_ipc_handler(handler)
178
- .with_back_forward_navigation_gestures(true)
179
- .with_download_started_handler(download_started)
180
- .with_download_completed_handler(download_completed)
181
- .build()?
182
- };
183
-
184
- #[cfg(any(target_os = "linux", target_os = "windows"))]
185
- let webview = {
186
- let home_dir = match home::home_dir() {
187
- Some(path1) => path1,
188
- None => panic!("Error, can't found you home dir!!"),
189
- };
190
- #[cfg(target_os = "windows")]
191
- let data_dir = home_dir.join("AppData").join("Roaming").join(package_name);
192
- #[cfg(target_os = "linux")]
193
- let data_dir = home_dir.join(".config").join(package_name);
194
- if !data_dir.exists() {
195
- std::fs::create_dir(&data_dir)
196
- .unwrap_or_else(|_| panic!("can't create dir {}", data_dir.display()));
197
- }
198
- let mut web_content = WebContext::new(Some(data_dir));
199
- #[cfg(target_os = "windows")]
200
- let user_agent_string = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
201
- #[cfg(target_os = "linux")]
202
- let user_agent_string = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36";
203
- WebViewBuilder::new(window)?
204
- .with_user_agent(user_agent_string)
205
- .with_url(&url.to_string())?
206
- .with_devtools(cfg!(feature = "devtools"))
207
- .with_initialization_script(include_str!("pake.js"))
208
- .with_ipc_handler(handler)
209
- .with_web_context(&mut web_content)
210
- .with_download_started_handler(download_started)
211
- .with_download_completed_handler(download_completed)
212
- .build()?
213
- };
214
- #[cfg(feature = "devtools")]
215
- {
216
- webview.open_devtools();
217
- }
56
+ .on_window_event(|event| {
57
+ if let tauri::WindowEvent::CloseRequested { api, .. } = event.event() {
58
+ #[cfg(target_os = "macos")]
59
+ event.window().minimize().unwrap();
218
60
 
219
- event_loop.run(move |event, _, control_flow| {
220
- *control_flow = ControlFlow::Wait;
61
+ #[cfg(not(target_os = "macos"))]
62
+ event.window().close().unwrap();
221
63
 
222
- match event {
223
- Event::NewEvents(StartCause::Init) => println!("Wry has started!"),
224
- Event::WindowEvent {
225
- event: WindowEvent::CloseRequested,
226
- ..
227
- } => *control_flow = ControlFlow::Exit,
228
- Event::MenuEvent {
229
- menu_id,
230
- origin: MenuType::MenuBar,
231
- ..
232
- } => {
233
- #[cfg(target_os = "macos")]
234
- if menu_id == close_item.clone().id() {
235
- webview.window().set_minimized(true);
236
- }
237
- println!("Clicked on {menu_id:?}");
238
- }
239
- Event::UserEvent(UserEvent::DownloadStarted(uri, temp_dir)) => {
240
- println!("Download: {uri}");
241
- println!("Will write to: {temp_dir:?}");
242
- }
243
- Event::UserEvent(UserEvent::DownloadComplete(_, success)) => {
244
- println!("Succeeded: {success}");
245
- if success {
246
- let _ = webview
247
- .evaluate_script("window.pakeToast('Downloaded to download folder~')");
248
- } else {
249
- println!("No output path")
250
- }
64
+ api.prevent_close();
251
65
  }
252
- _ => (),
253
- }
254
- });
255
- }
256
-
257
- fn get_windows_config() -> (Option<String>, Option<WindowConfig>) {
258
- let config_file = include_str!("../tauri.conf.json");
259
- let config: Config = serde_json::from_str(config_file).expect("failed to parse windows config");
260
- (
261
- config.package.product_name.clone(),
262
- config.tauri.windows.first().cloned(),
263
- )
66
+ })
67
+ .run(tauri::generate_context!())
68
+ .expect("error while running tauri application");
264
69
  }
265
70
 
266
- #[cfg(target_os = "windows")]
267
- fn load_icon(path: &std::path::Path) -> Icon {
268
- let (icon_rgba, icon_width, icon_height) = {
269
- // alternatively, you can embed the icon in the binary through `include_bytes!` macro and use `image::load_from_memory`
270
- let image = image::open(path)
271
- .expect("Failed to open icon path")
272
- .into_rgba8();
273
- let (width, height) = image.dimensions();
274
- let rgba = image.into_raw();
275
- (rgba, width, height)
276
- };
277
- Icon::from_rgba(icon_rgba, icon_width, icon_height).expect("Failed to open icon")
71
+ fn main() {
72
+ run_app()
278
73
  }
@@ -0,0 +1,78 @@
1
+ use crate::app::config::PakeConfig;
2
+ use std::env;
3
+ use std::path::PathBuf;
4
+ use tauri::{api, Config, Window};
5
+
6
+ pub fn get_pake_config() -> (PakeConfig, Config) {
7
+ let pake_config: PakeConfig =
8
+ serde_json::from_str(include_str!("../pake.json")).expect("Failed to parse pake config");
9
+
10
+ let tauri_config: Config = serde_json::from_str(include_str!("../tauri.conf.json"))
11
+ .expect("Failed to parse tauri config");
12
+
13
+ (pake_config, tauri_config)
14
+ }
15
+
16
+ pub fn get_data_dir(_tauri_config: Config) -> PathBuf {
17
+ {
18
+ let package_name = _tauri_config.package.product_name.unwrap();
19
+ let data_dir = api::path::config_dir()
20
+ .expect("Failed to get data dirname")
21
+ .join(package_name);
22
+
23
+ if !data_dir.exists() {
24
+ std::fs::create_dir(&data_dir)
25
+ .unwrap_or_else(|_| panic!("Can't create dir {}", data_dir.display()));
26
+ }
27
+ data_dir
28
+ }
29
+ }
30
+
31
+ pub fn show_toast(window: &Window, message: &str) {
32
+ let script = format!(r#"pakeToast("{}");"#, message);
33
+ window.eval(&script).unwrap();
34
+ }
35
+
36
+ pub fn get_download_message() -> String {
37
+ let default_message = "Download successful, saved to download directory~";
38
+ let chinese_message = "下载成功,已保存到下载目录~";
39
+
40
+ env::var("LANG")
41
+ .map(|lang| {
42
+ if lang.starts_with("zh") {
43
+ chinese_message
44
+ } else {
45
+ default_message
46
+ }
47
+ })
48
+ .unwrap_or(default_message)
49
+ .to_string()
50
+ }
51
+
52
+ // Check if the file exists, if it exists, add a number to file name
53
+ pub fn check_file_or_append(file_path: &str) -> String {
54
+ let mut new_path = PathBuf::from(file_path);
55
+ let mut counter = 0;
56
+
57
+ while new_path.exists() {
58
+ let file_stem = new_path.file_stem().unwrap().to_string_lossy().to_string();
59
+ let extension = new_path.extension().unwrap().to_string_lossy().to_string();
60
+ let parent_dir = new_path.parent().unwrap();
61
+
62
+ let new_file_stem = match file_stem.rfind('-') {
63
+ Some(index) if file_stem[index + 1..].parse::<u32>().is_ok() => {
64
+ let base_name = &file_stem[..index];
65
+ counter = file_stem[index + 1..].parse::<u32>().unwrap() + 1;
66
+ format!("{}-{}", base_name, counter)
67
+ }
68
+ _ => {
69
+ counter += 1;
70
+ format!("{}-{}", file_stem, counter)
71
+ }
72
+ };
73
+
74
+ new_path = parent_dir.join(format!("{}.{}", new_file_stem, extension));
75
+ }
76
+
77
+ new_path.to_string_lossy().into_owned()
78
+ }