pake-cli 3.11.1 โ 3.11.3
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.
- package/README.md +4 -5
- package/dist/cli.js +406 -269
- package/package.json +3 -3
- package/src-tauri/Cargo.lock +1 -3
- package/src-tauri/Cargo.toml +3 -3
- package/src-tauri/pake.json +3 -3
- package/src-tauri/src/app/setup.rs +37 -29
- package/src-tauri/src/app/window.rs +44 -13
- package/src-tauri/src/inject/event.js +59 -23
- package/src-tauri/src/inject/style.js +31 -6
- package/src-tauri/src/lib.rs +8 -9
- package/src-tauri/tauri.conf.json +1 -1
- package/dist/code-review-graph.js +0 -283
- package/src-tauri/.pake/pake.json +0 -45
- package/src-tauri/.pake/tauri.conf.json +0 -46
- package/src-tauri/.pake/tauri.linux.conf.json +0 -12
- package/src-tauri/.pake/tauri.macos.conf.json +0 -32
- package/src-tauri/.pake/tauri.windows.conf.json +0 -15
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pake-cli",
|
|
3
|
-
"version": "3.11.
|
|
3
|
+
"version": "3.11.3",
|
|
4
4
|
"description": "๐คฑ๐ป Turn any webpage into a desktop app with one command. ๐คฑ๐ป ไธ้ฎๆๅ
็ฝ้กต็ๆ่ฝป้ๆก้ขๅบ็จใ",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=18.0.0"
|
|
@@ -73,7 +73,6 @@
|
|
|
73
73
|
"@rollup/plugin-terser": "^0.4.4",
|
|
74
74
|
"@types/fs-extra": "^11.0.4",
|
|
75
75
|
"@types/node": "^25.3.2",
|
|
76
|
-
"@types/page-icon": "^0.3.6",
|
|
77
76
|
"@types/prompts": "^2.4.9",
|
|
78
77
|
"@types/tmp": "^0.2.6",
|
|
79
78
|
"@types/update-notifier": "^6.0.8",
|
|
@@ -88,7 +87,8 @@
|
|
|
88
87
|
},
|
|
89
88
|
"pnpm": {
|
|
90
89
|
"overrides": {
|
|
91
|
-
"sharp": "^0.34.5"
|
|
90
|
+
"sharp": "^0.34.5",
|
|
91
|
+
"@img/sharp-libvips-darwin-arm64": "1.2.4"
|
|
92
92
|
},
|
|
93
93
|
"onlyBuiltDependencies": [
|
|
94
94
|
"esbuild",
|
package/src-tauri/Cargo.lock
CHANGED
|
@@ -2564,7 +2564,7 @@ dependencies = [
|
|
|
2564
2564
|
|
|
2565
2565
|
[[package]]
|
|
2566
2566
|
name = "pake"
|
|
2567
|
-
version = "3.11.
|
|
2567
|
+
version = "3.11.3"
|
|
2568
2568
|
dependencies = [
|
|
2569
2569
|
"serde",
|
|
2570
2570
|
"serde_json",
|
|
@@ -4575,9 +4575,7 @@ dependencies = [
|
|
|
4575
4575
|
"bytes",
|
|
4576
4576
|
"libc",
|
|
4577
4577
|
"mio",
|
|
4578
|
-
"parking_lot",
|
|
4579
4578
|
"pin-project-lite",
|
|
4580
|
-
"signal-hook-registry",
|
|
4581
4579
|
"socket2",
|
|
4582
4580
|
"tokio-macros",
|
|
4583
4581
|
"windows-sys 0.61.2",
|
package/src-tauri/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "pake"
|
|
3
|
-
version = "3.11.
|
|
3
|
+
version = "3.11.3"
|
|
4
4
|
description = "๐คฑ๐ป Turn any webpage into a desktop app with Rust."
|
|
5
5
|
authors = ["Tw93"]
|
|
6
6
|
license = "MIT"
|
|
@@ -20,7 +20,7 @@ tauri-build = { version = "2.5.5", features = [] }
|
|
|
20
20
|
[dependencies]
|
|
21
21
|
serde_json = "1.0.149"
|
|
22
22
|
serde = { version = "1.0.228", features = ["derive"] }
|
|
23
|
-
tokio = { version = "1.49.0", features = ["
|
|
23
|
+
tokio = { version = "1.49.0", features = ["time"] }
|
|
24
24
|
tauri = { version = "2.10.2", features = [
|
|
25
25
|
"tray-icon",
|
|
26
26
|
"image-ico",
|
|
@@ -48,7 +48,7 @@ custom-protocol = ["tauri/custom-protocol"]
|
|
|
48
48
|
|
|
49
49
|
[profile.release]
|
|
50
50
|
panic = "abort"
|
|
51
|
-
codegen-units =
|
|
51
|
+
codegen-units = 1
|
|
52
52
|
lto = "thin"
|
|
53
53
|
opt-level = "z"
|
|
54
54
|
strip = true
|
package/src-tauri/pake.json
CHANGED
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
}
|
|
25
25
|
],
|
|
26
26
|
"user_agent": {
|
|
27
|
-
"macos": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/
|
|
28
|
-
"linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
29
|
-
"windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/
|
|
27
|
+
"macos": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Safari/605.1.15",
|
|
28
|
+
"linux": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36",
|
|
29
|
+
"windows": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36"
|
|
30
30
|
},
|
|
31
31
|
"system_tray": {
|
|
32
32
|
"macos": false,
|
|
@@ -39,7 +39,7 @@ pub fn set_system_tray(
|
|
|
39
39
|
|
|
40
40
|
app.app_handle().remove_tray_by_id("pake-tray");
|
|
41
41
|
|
|
42
|
-
let
|
|
42
|
+
let mut tray_builder = TrayIconBuilder::new()
|
|
43
43
|
.menu(&menu)
|
|
44
44
|
.on_menu_event(move |app, event| match event.id().as_ref() {
|
|
45
45
|
"new_window" => {
|
|
@@ -47,12 +47,12 @@ pub fn set_system_tray(
|
|
|
47
47
|
}
|
|
48
48
|
"hide_app" => {
|
|
49
49
|
if let Some(window) = app.get_webview_window("pake") {
|
|
50
|
-
window.minimize()
|
|
50
|
+
let _ = window.minimize();
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
"show_app" => {
|
|
54
54
|
if let Some(window) = app.get_webview_window("pake") {
|
|
55
|
-
window.show()
|
|
55
|
+
let _ = window.show();
|
|
56
56
|
#[cfg(target_os = "linux")]
|
|
57
57
|
if _init_fullscreen && !window.is_fullscreen().unwrap_or(false) {
|
|
58
58
|
let _ = window.set_fullscreen(true);
|
|
@@ -61,8 +61,8 @@ pub fn set_system_tray(
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
"quit" => {
|
|
64
|
-
app.save_window_state(StateFlags::all())
|
|
65
|
-
|
|
64
|
+
let _ = app.save_window_state(StateFlags::all());
|
|
65
|
+
app.exit(0);
|
|
66
66
|
}
|
|
67
67
|
_ => (),
|
|
68
68
|
})
|
|
@@ -72,10 +72,10 @@ pub fn set_system_tray(
|
|
|
72
72
|
if let Some(window) = tray.app_handle().get_webview_window("pake") {
|
|
73
73
|
let is_visible = window.is_visible().unwrap_or(false);
|
|
74
74
|
if is_visible {
|
|
75
|
-
window.hide()
|
|
75
|
+
let _ = window.hide();
|
|
76
76
|
} else {
|
|
77
|
-
window.show()
|
|
78
|
-
window.set_focus()
|
|
77
|
+
let _ = window.show();
|
|
78
|
+
let _ = window.set_focus();
|
|
79
79
|
#[cfg(target_os = "linux")]
|
|
80
80
|
if _init_fullscreen && !window.is_fullscreen().unwrap_or(false) {
|
|
81
81
|
let _ = window.set_fullscreen(true);
|
|
@@ -85,20 +85,23 @@ pub fn set_system_tray(
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
_ => {}
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
.
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
let resolved_icon = if tray_icon_path.is_empty() {
|
|
91
|
+
app.default_window_icon().cloned()
|
|
92
|
+
} else {
|
|
93
|
+
tauri::image::Image::from_path(tray_icon_path)
|
|
94
|
+
.ok()
|
|
95
|
+
.or_else(|| app.default_window_icon().cloned())
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if let Some(icon) = resolved_icon {
|
|
99
|
+
tray_builder = tray_builder.icon(icon);
|
|
100
|
+
} else {
|
|
101
|
+
eprintln!("[Pake] No tray icon available; tray will build without an icon.");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let tray = tray_builder.build(app)?;
|
|
102
105
|
|
|
103
106
|
tray.set_icon_as_template(false)?;
|
|
104
107
|
Ok(())
|
|
@@ -114,7 +117,10 @@ pub fn set_global_shortcut(
|
|
|
114
117
|
}
|
|
115
118
|
|
|
116
119
|
let app_handle = app.clone();
|
|
117
|
-
let shortcut_hotkey = Shortcut::from_str(&shortcut)
|
|
120
|
+
let shortcut_hotkey = match Shortcut::from_str(&shortcut) {
|
|
121
|
+
Ok(s) => s,
|
|
122
|
+
Err(_) => return Ok(()),
|
|
123
|
+
};
|
|
118
124
|
let last_triggered = Arc::new(Mutex::new(Instant::now()));
|
|
119
125
|
|
|
120
126
|
app_handle
|
|
@@ -123,7 +129,9 @@ pub fn set_global_shortcut(
|
|
|
123
129
|
.with_handler({
|
|
124
130
|
let last_triggered = Arc::clone(&last_triggered);
|
|
125
131
|
move |app, event, _shortcut| {
|
|
126
|
-
let mut last_triggered = last_triggered.lock()
|
|
132
|
+
let Ok(mut last_triggered) = last_triggered.lock() else {
|
|
133
|
+
return;
|
|
134
|
+
};
|
|
127
135
|
if Instant::now().duration_since(*last_triggered)
|
|
128
136
|
< Duration::from_millis(300)
|
|
129
137
|
{
|
|
@@ -133,12 +141,12 @@ pub fn set_global_shortcut(
|
|
|
133
141
|
|
|
134
142
|
if shortcut_hotkey.eq(event) {
|
|
135
143
|
if let Some(window) = app.get_webview_window("pake") {
|
|
136
|
-
let is_visible = window.is_visible().
|
|
144
|
+
let is_visible = window.is_visible().unwrap_or(false);
|
|
137
145
|
if is_visible {
|
|
138
|
-
window.hide()
|
|
146
|
+
let _ = window.hide();
|
|
139
147
|
} else {
|
|
140
|
-
window.show()
|
|
141
|
-
window.set_focus()
|
|
148
|
+
let _ = window.show();
|
|
149
|
+
let _ = window.set_focus();
|
|
142
150
|
#[cfg(target_os = "linux")]
|
|
143
151
|
if _init_fullscreen && !window.is_fullscreen().unwrap_or(false)
|
|
144
152
|
{
|
|
@@ -153,7 +161,7 @@ pub fn set_global_shortcut(
|
|
|
153
161
|
)
|
|
154
162
|
.expect("Failed to set global shortcut");
|
|
155
163
|
|
|
156
|
-
app.global_shortcut().register(shortcut_hotkey)
|
|
164
|
+
let _ = app.global_shortcut().register(shortcut_hotkey);
|
|
157
165
|
|
|
158
166
|
Ok(())
|
|
159
167
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
use crate::app::config::PakeConfig;
|
|
2
2
|
use crate::util::get_data_dir;
|
|
3
|
-
use std::{
|
|
3
|
+
use std::{
|
|
4
|
+
path::PathBuf,
|
|
5
|
+
str::FromStr,
|
|
6
|
+
sync::atomic::{AtomicU32, Ordering},
|
|
7
|
+
};
|
|
4
8
|
use tauri::{
|
|
5
9
|
webview::{NewWindowFeatures, NewWindowResponse},
|
|
6
10
|
AppHandle, Config, Manager, Url, WebviewUrl, WebviewWindow, WebviewWindowBuilder,
|
|
@@ -28,7 +32,7 @@ fn build_proxy_browser_arg(url: &Url) -> Option<String> {
|
|
|
28
32
|
pub struct MultiWindowState {
|
|
29
33
|
pub pake_config: PakeConfig,
|
|
30
34
|
pub tauri_config: Config,
|
|
31
|
-
next_window_index:
|
|
35
|
+
next_window_index: AtomicU32,
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
impl MultiWindowState {
|
|
@@ -36,14 +40,13 @@ impl MultiWindowState {
|
|
|
36
40
|
Self {
|
|
37
41
|
pake_config,
|
|
38
42
|
tauri_config,
|
|
39
|
-
next_window_index:
|
|
43
|
+
next_window_index: AtomicU32::new(0),
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
|
|
43
47
|
fn next_window_label(&self) -> String {
|
|
44
|
-
let
|
|
45
|
-
|
|
46
|
-
format!("pake-{}", *index)
|
|
48
|
+
let index = self.next_window_index.fetch_add(1, Ordering::Relaxed) + 1;
|
|
49
|
+
format!("pake-{index}")
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
|
|
@@ -124,9 +127,25 @@ fn build_window_with_label(
|
|
|
124
127
|
.first()
|
|
125
128
|
.expect("At least one window configuration is required");
|
|
126
129
|
let url = match window_config.url_type.as_str() {
|
|
127
|
-
"web" =>
|
|
130
|
+
"web" => {
|
|
131
|
+
let parsed = window_config.url.parse().map_err(|err| {
|
|
132
|
+
tauri::Error::Io(std::io::Error::new(
|
|
133
|
+
std::io::ErrorKind::InvalidInput,
|
|
134
|
+
format!(
|
|
135
|
+
"Invalid 'web' url '{}' in pake.json: {err}",
|
|
136
|
+
window_config.url
|
|
137
|
+
),
|
|
138
|
+
))
|
|
139
|
+
})?;
|
|
140
|
+
WebviewUrl::App(parsed)
|
|
141
|
+
}
|
|
128
142
|
"local" => WebviewUrl::App(PathBuf::from(&window_config.url)),
|
|
129
|
-
|
|
143
|
+
other => {
|
|
144
|
+
return Err(tauri::Error::Io(std::io::Error::new(
|
|
145
|
+
std::io::ErrorKind::InvalidInput,
|
|
146
|
+
format!("url_type must be 'web' or 'local', got '{other}'"),
|
|
147
|
+
)));
|
|
148
|
+
}
|
|
130
149
|
};
|
|
131
150
|
|
|
132
151
|
build_window(
|
|
@@ -154,7 +173,10 @@ fn build_window(
|
|
|
154
173
|
visible,
|
|
155
174
|
new_window_features,
|
|
156
175
|
} = opts;
|
|
157
|
-
let package_name = tauri_config
|
|
176
|
+
let package_name = tauri_config
|
|
177
|
+
.product_name
|
|
178
|
+
.clone()
|
|
179
|
+
.unwrap_or_else(|| "pake".to_string());
|
|
158
180
|
let _data_dir = get_data_dir(app, package_name);
|
|
159
181
|
|
|
160
182
|
let window_config = config
|
|
@@ -166,7 +188,7 @@ fn build_window(
|
|
|
166
188
|
|
|
167
189
|
let config_script = format!(
|
|
168
190
|
"window.pakeConfig = {}",
|
|
169
|
-
serde_json::to_string(&window_config).
|
|
191
|
+
serde_json::to_string(&window_config).unwrap_or_else(|_| "{}".to_string())
|
|
170
192
|
);
|
|
171
193
|
|
|
172
194
|
// Platform-specific title: macOS prefers empty, others fallback to product name
|
|
@@ -369,11 +391,20 @@ fn build_window(
|
|
|
369
391
|
}
|
|
370
392
|
|
|
371
393
|
if let Some(features) = new_window_features {
|
|
372
|
-
//
|
|
394
|
+
// macOS popup webviews must reuse the opener webview configuration.
|
|
373
395
|
#[cfg(target_os = "macos")]
|
|
374
396
|
{
|
|
375
|
-
let
|
|
376
|
-
|
|
397
|
+
if let Some(position) = features.position() {
|
|
398
|
+
window_builder = window_builder.position(position.x, position.y);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if let Some(size) = features.size() {
|
|
402
|
+
window_builder = window_builder.inner_size(size.width, size.height);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
window_builder = window_builder
|
|
406
|
+
.with_webview_configuration(features.opener().target_configuration.clone())
|
|
407
|
+
.focused(true);
|
|
377
408
|
}
|
|
378
409
|
|
|
379
410
|
#[cfg(not(target_os = "macos"))]
|
|
@@ -257,6 +257,21 @@ function isDownloadableFile(url) {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
function normalizeAnchorHref(rawHref) {
|
|
261
|
+
return typeof rawHref === "string" ? rawHref.trim() : "";
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function shouldBypassPakeLinkHandling(rawHref) {
|
|
265
|
+
const normalizedHref = normalizeAnchorHref(rawHref).toLowerCase();
|
|
266
|
+
if (!normalizedHref) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return (
|
|
271
|
+
normalizedHref.startsWith("javascript:") || normalizedHref.startsWith("#")
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
260
275
|
document.addEventListener("DOMContentLoaded", () => {
|
|
261
276
|
const tauri = window.__TAURI__;
|
|
262
277
|
const appWindow = tauri.window.getCurrentWindow();
|
|
@@ -506,6 +521,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
506
521
|
const anchorElement = e.target.closest("a");
|
|
507
522
|
|
|
508
523
|
if (anchorElement && anchorElement.href) {
|
|
524
|
+
const rawHref = anchorElement.getAttribute("href") || "";
|
|
525
|
+
if (shouldBypassPakeLinkHandling(rawHref)) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
|
|
509
529
|
const target = anchorElement.target;
|
|
510
530
|
const hrefUrl = new URL(anchorElement.href);
|
|
511
531
|
const absoluteUrl = hrefUrl.href;
|
|
@@ -534,7 +554,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
534
554
|
return;
|
|
535
555
|
}
|
|
536
556
|
|
|
537
|
-
// Handle _blank links:
|
|
557
|
+
// Handle _blank links: internal links stay in-app, external links open in the system browser
|
|
538
558
|
if (target === "_blank") {
|
|
539
559
|
if (forceInternalNavigation) {
|
|
540
560
|
e.preventDefault();
|
|
@@ -550,13 +570,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
550
570
|
|
|
551
571
|
e.preventDefault();
|
|
552
572
|
e.stopImmediatePropagation();
|
|
553
|
-
|
|
554
|
-
window,
|
|
555
|
-
absoluteUrl,
|
|
556
|
-
"_blank",
|
|
557
|
-
"width=1200,height=800,scrollbars=yes,resizable=yes",
|
|
558
|
-
);
|
|
559
|
-
if (!newWindow) handleExternalLink(absoluteUrl);
|
|
573
|
+
handleExternalLink(absoluteUrl);
|
|
560
574
|
return;
|
|
561
575
|
}
|
|
562
576
|
|
|
@@ -587,7 +601,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
587
601
|
return;
|
|
588
602
|
}
|
|
589
603
|
|
|
590
|
-
// Handle regular links: internal URLs allow normal navigation, external
|
|
604
|
+
// Handle regular links: internal URLs allow normal navigation, external links open in the system browser
|
|
591
605
|
if (!target || target === "_self") {
|
|
592
606
|
// Optimization: Allow previewable media to be handled by the app/browser directly
|
|
593
607
|
// This fixes issues where CDN links are treated as external
|
|
@@ -602,13 +616,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
602
616
|
|
|
603
617
|
e.preventDefault();
|
|
604
618
|
e.stopImmediatePropagation();
|
|
605
|
-
|
|
606
|
-
window,
|
|
607
|
-
absoluteUrl,
|
|
608
|
-
"_blank",
|
|
609
|
-
"width=1200,height=800,scrollbars=yes,resizable=yes",
|
|
610
|
-
);
|
|
611
|
-
if (!newWindow) handleExternalLink(absoluteUrl);
|
|
619
|
+
handleExternalLink(absoluteUrl);
|
|
612
620
|
}
|
|
613
621
|
}
|
|
614
622
|
}
|
|
@@ -623,6 +631,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
623
631
|
// Rewrite the window.open function.
|
|
624
632
|
const originalWindowOpen = window.open;
|
|
625
633
|
window.open = function (url, name, specs) {
|
|
634
|
+
const normalizedUrl = normalizeAnchorHref(url);
|
|
635
|
+
if (normalizedUrl.startsWith("#")) {
|
|
636
|
+
window.location.href = new URL(normalizedUrl, window.location.href).href;
|
|
637
|
+
return window;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (shouldBypassPakeLinkHandling(url)) {
|
|
641
|
+
return originalWindowOpen.call(window, url, name, specs);
|
|
642
|
+
}
|
|
643
|
+
|
|
626
644
|
// Allow authentication popups to open normally
|
|
627
645
|
if (window.isAuthPopup(url, name)) {
|
|
628
646
|
return originalWindowOpen.call(window, url, name, specs);
|
|
@@ -1009,23 +1027,41 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
1009
1027
|
|
|
1010
1028
|
document.addEventListener("DOMContentLoaded", function () {
|
|
1011
1029
|
let permVal = "granted";
|
|
1030
|
+
let lastNotifTime = 0;
|
|
1031
|
+
let lastNotif = null;
|
|
1032
|
+
|
|
1033
|
+
window.addEventListener("focus", () => {
|
|
1034
|
+
if (lastNotif?.onclick && Date.now() - lastNotifTime < 5000) {
|
|
1035
|
+
lastNotif.onclick(new Event("click"));
|
|
1036
|
+
lastNotif = null;
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1012
1040
|
window.Notification = function (title, options) {
|
|
1013
1041
|
const { invoke } = window.__TAURI__.core;
|
|
1014
1042
|
const body = options?.body || "";
|
|
1015
1043
|
let icon = options?.icon || "";
|
|
1016
1044
|
|
|
1017
|
-
// If the icon is a relative path, convert to full path using URI
|
|
1018
1045
|
if (icon.startsWith("/")) {
|
|
1019
1046
|
icon = window.location.origin + icon;
|
|
1020
1047
|
}
|
|
1021
1048
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
},
|
|
1049
|
+
const notif = {
|
|
1050
|
+
onclick: null,
|
|
1051
|
+
onclose: null,
|
|
1052
|
+
onshow: null,
|
|
1053
|
+
onerror: null,
|
|
1054
|
+
close: () => {},
|
|
1055
|
+
};
|
|
1056
|
+
|
|
1057
|
+
lastNotifTime = Date.now();
|
|
1058
|
+
lastNotif = notif;
|
|
1059
|
+
|
|
1060
|
+
invoke("send_notification", { params: { title, body, icon } }).then(() => {
|
|
1061
|
+
if (notif.onshow) notif.onshow(new Event("show"));
|
|
1028
1062
|
});
|
|
1063
|
+
|
|
1064
|
+
return notif;
|
|
1029
1065
|
};
|
|
1030
1066
|
|
|
1031
1067
|
window.Notification.requestPermission = async () => "granted";
|
|
@@ -119,15 +119,18 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
119
119
|
|
|
120
120
|
#react-root [data-testid="placementTracking"] article,
|
|
121
121
|
#react-root a[href*="quick_promote_web"],
|
|
122
|
-
#react-root [data-testid="AppTabBar_Explore_Link"],
|
|
123
122
|
#react-root a[href*="/lists"][role="link"][aria-label],
|
|
124
123
|
#react-root a[href*="/i/communitynotes"][role="link"][aria-label],
|
|
125
124
|
#react-root a[role="link"][aria-label="Communities"],
|
|
125
|
+
#react-root a[role="link"][aria-label="Premium"],
|
|
126
|
+
#react-root a[role="link"][aria-label="SuperGrok"],
|
|
126
127
|
#react-root a[href*="/i/verified-orgs-signup"][role="link"][aria-label] {
|
|
127
128
|
display: none !important;
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
#react-root [data-testid="DMDrawer"],
|
|
132
|
+
#react-root [data-testid="GrokDrawer"],
|
|
133
|
+
#react-root [data-testid="chat-drawer-root"],
|
|
131
134
|
#root > main > footer.justify-center.ease-in {
|
|
132
135
|
visibility: hidden !important;
|
|
133
136
|
}
|
|
@@ -231,6 +234,28 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
231
234
|
}
|
|
232
235
|
}
|
|
233
236
|
|
|
237
|
+
@media only screen and (min-width: 1000px) and (max-width: 1264px) {
|
|
238
|
+
#react-root [data-testid="sidebarColumn"] form[role="search"] {
|
|
239
|
+
visibility: visible !important;
|
|
240
|
+
position: fixed !important;
|
|
241
|
+
top: 12px !important;
|
|
242
|
+
right: 16px !important;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
#react-root [data-testid="sidebarColumn"] input[placeholder="Search"] {
|
|
246
|
+
width: 150px;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
#react-root [data-testid="sidebarColumn"] form[role="search"]:focus-within {
|
|
250
|
+
width: 280px !important;
|
|
251
|
+
backdrop-filter: blur(12px) !important;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
#react-root [data-testid="sidebarColumn"] input[placeholder="Search"]:focus {
|
|
255
|
+
width: 234px !important;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
234
259
|
@media only screen and (min-width: 1265px) {
|
|
235
260
|
#react-root [data-testid="sidebarColumn"] form[role="search"] {
|
|
236
261
|
visibility: visible !important;
|
|
@@ -239,7 +264,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
239
264
|
right: 16px !important;
|
|
240
265
|
}
|
|
241
266
|
|
|
242
|
-
#react-root [data-testid="sidebarColumn"] input[placeholder="Search
|
|
267
|
+
#react-root [data-testid="sidebarColumn"] input[placeholder="Search"] {
|
|
243
268
|
width: 150px;
|
|
244
269
|
}
|
|
245
270
|
|
|
@@ -248,7 +273,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
248
273
|
backdrop-filter: blur(12px) !important;
|
|
249
274
|
}
|
|
250
275
|
|
|
251
|
-
#react-root [data-testid="sidebarColumn"] input[placeholder="Search
|
|
276
|
+
#react-root [data-testid="sidebarColumn"] input[placeholder="Search"]:focus {
|
|
252
277
|
width: 328px !important;
|
|
253
278
|
}
|
|
254
279
|
|
|
@@ -300,7 +325,7 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
300
325
|
}
|
|
301
326
|
`;
|
|
302
327
|
const contentStyleElement = document.createElement("style");
|
|
303
|
-
contentStyleElement.
|
|
328
|
+
contentStyleElement.textContent = contentCSS;
|
|
304
329
|
document.head.appendChild(contentStyleElement);
|
|
305
330
|
|
|
306
331
|
// Top spacing adapts to head-hiding scenarios
|
|
@@ -471,10 +496,10 @@ window.addEventListener("DOMContentLoaded", (_event) => {
|
|
|
471
496
|
}
|
|
472
497
|
}
|
|
473
498
|
`;
|
|
474
|
-
const isMac =
|
|
499
|
+
const isMac = /Mac/i.test(navigator.userAgent);
|
|
475
500
|
if (window["pakeConfig"]?.hide_title_bar && isMac) {
|
|
476
501
|
const topPaddingStyleElement = document.createElement("style");
|
|
477
|
-
topPaddingStyleElement.
|
|
502
|
+
topPaddingStyleElement.textContent = topPaddingCSS;
|
|
478
503
|
document.head.appendChild(topPaddingStyleElement);
|
|
479
504
|
}
|
|
480
505
|
});
|
package/src-tauri/src/lib.rs
CHANGED
|
@@ -107,9 +107,8 @@ pub fn run_app() {
|
|
|
107
107
|
&pake_config.system_tray_path,
|
|
108
108
|
init_fullscreen,
|
|
109
109
|
multi_window,
|
|
110
|
-
)
|
|
111
|
-
.
|
|
112
|
-
set_global_shortcut(app.app_handle(), activation_shortcut, init_fullscreen).unwrap();
|
|
110
|
+
)?;
|
|
111
|
+
set_global_shortcut(app.app_handle(), activation_shortcut, init_fullscreen)?;
|
|
113
112
|
|
|
114
113
|
// Show window after state restoration to prevent position flashing
|
|
115
114
|
// Unless start_to_tray is enabled, then keep it hidden
|
|
@@ -117,13 +116,13 @@ pub fn run_app() {
|
|
|
117
116
|
let window_clone = window.clone();
|
|
118
117
|
tauri::async_runtime::spawn(async move {
|
|
119
118
|
tokio::time::sleep(tokio::time::Duration::from_millis(WINDOW_SHOW_DELAY)).await;
|
|
120
|
-
window_clone.show()
|
|
119
|
+
let _ = window_clone.show();
|
|
121
120
|
|
|
122
121
|
// Fixed: Linux fullscreen issue with virtual keyboard
|
|
123
122
|
#[cfg(target_os = "linux")]
|
|
124
123
|
{
|
|
125
124
|
if init_fullscreen {
|
|
126
|
-
window_clone.set_fullscreen(true)
|
|
125
|
+
let _ = window_clone.set_fullscreen(true);
|
|
127
126
|
// Ensure webview maintains focus for input after fullscreen
|
|
128
127
|
let _ = window_clone.set_focus();
|
|
129
128
|
} else {
|
|
@@ -148,22 +147,22 @@ pub fn run_app() {
|
|
|
148
147
|
#[cfg(target_os = "macos")]
|
|
149
148
|
{
|
|
150
149
|
if window.is_fullscreen().unwrap_or(false) {
|
|
151
|
-
window.set_fullscreen(false)
|
|
150
|
+
let _ = window.set_fullscreen(false);
|
|
152
151
|
tokio::time::sleep(Duration::from_millis(900)).await;
|
|
153
152
|
}
|
|
154
153
|
}
|
|
155
154
|
#[cfg(target_os = "linux")]
|
|
156
155
|
{
|
|
157
156
|
if window.is_fullscreen().unwrap_or(false) {
|
|
158
|
-
window.set_fullscreen(false)
|
|
157
|
+
let _ = window.set_fullscreen(false);
|
|
159
158
|
// Restore focus after exiting fullscreen to fix input issues
|
|
160
159
|
let _ = window.set_focus();
|
|
161
160
|
}
|
|
162
161
|
}
|
|
163
162
|
// On macOS, directly hide without minimize to avoid duplicate Dock icons
|
|
164
163
|
#[cfg(not(target_os = "macos"))]
|
|
165
|
-
window.minimize()
|
|
166
|
-
window.hide()
|
|
164
|
+
let _ = window.minimize();
|
|
165
|
+
let _ = window.hide();
|
|
167
166
|
});
|
|
168
167
|
api.prevent_close();
|
|
169
168
|
}
|