Skip to content

Commit 10d3967

Browse files
committed
fix
1 parent 4fee642 commit 10d3967

3 files changed

Lines changed: 62 additions & 12 deletions

File tree

.github/workflows/cleanup-artifacts.yml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ on:
66
workflow_dispatch:
77
inputs:
88
keep_last:
9-
description: 'Number of successful artifacts to keep'
9+
description: 'Number of successful builds to keep artifacts from'
1010
required: false
11-
default: '3'
11+
default: '1'
1212
type: number
1313
keep_runs_days:
1414
description: 'Delete runs older than N days'
@@ -24,7 +24,7 @@ jobs:
2424
uses: actions/github-script@v7
2525
with:
2626
script: |
27-
const KEEP_LAST = ${{ github.event.inputs.keep_last || 3 }};
27+
const KEEP_LAST = ${{ github.event.inputs.keep_last || 1 }};
2828
const KEEP_RUNS_DAYS = ${{ github.event.inputs.keep_runs_days || 30 }};
2929
const cutoffDate = new Date(Date.now() - KEEP_RUNS_DAYS * 24 * 60 * 60 * 1000);
3030
@@ -59,8 +59,12 @@ jobs:
5959
const failed = artifacts
6060
.filter(a => !successRunIds.has(a.workflow_run?.id));
6161
62+
// Group successful artifacts by run, keep all artifacts from the last N runs
63+
const runIds = [...new Set(successful.map(a => a.workflow_run?.id))];
64+
const keepRunIds = new Set(runIds.slice(0, KEEP_LAST));
65+
6266
const toDelete = [
63-
...successful.slice(KEEP_LAST),
67+
...successful.filter(a => !keepRunIds.has(a.workflow_run?.id)),
6468
...failed,
6569
];
6670
@@ -73,7 +77,7 @@ jobs:
7377
});
7478
}
7579
76-
console.log(`\nArtifacts — Kept: ${Math.min(KEEP_LAST, successful.length)}, Deleted: ${toDelete.length}`);
80+
console.log(`\nArtifacts — Kept runs: ${keepRunIds.size}, Deleted artifacts: ${toDelete.length}`);
7781
7882
// --- Cleanup Draft Releases ---
7983
console.log(`\n=== Draft Release Cleanup ===\n`);

src-tauri/src/lib.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ pub struct AppState {
2222
pub preferences: std::sync::Mutex<config::Preferences>,
2323
pub last_tray_rect: std::sync::Mutex<Option<tauri::Rect>>,
2424
pub sidecar_child: std::sync::Mutex<Option<CommandChild>>,
25+
/// True while we're waiting for the window to gain focus after being shown.
26+
/// Blocks spurious `Focused(false)` events that fire before `Focused(true)`
27+
/// (a known issue on Linux/X11 and some Windows configurations).
28+
/// Cleared when `Focused(true)` fires, so subsequent focus-loss auto-hides normally.
29+
pub expect_focus_gain: std::sync::Mutex<bool>,
2530
}
2631

2732
/// Find an available port starting from the default.
@@ -250,6 +255,7 @@ pub fn run() {
250255
preferences: std::sync::Mutex::new(preferences.clone()),
251256
last_tray_rect: std::sync::Mutex::new(None),
252257
sidecar_child: std::sync::Mutex::new(None),
258+
expect_focus_gain: std::sync::Mutex::new(false),
253259
})
254260
.invoke_handler(tauri::generate_handler![
255261
display::get_monitors,
@@ -334,8 +340,25 @@ pub fn run() {
334340
let app_handle = app.handle().clone();
335341
window.on_window_event(move |event| {
336342
match event {
343+
tauri::WindowEvent::Focused(true) => {
344+
// Window gained focus: clear the flag so future focus-loss hides normally.
345+
if let Some(state) = app_handle.try_state::<AppState>() {
346+
if let Ok(mut e) = state.expect_focus_gain.lock() {
347+
*e = false;
348+
}
349+
}
350+
}
337351
tauri::WindowEvent::Focused(false) => {
338-
let _ = win_clone.hide();
352+
// Skip hide if we're still waiting for the window to gain focus.
353+
// On Linux/X11 a spurious Focused(false) fires before Focused(true)
354+
// right after show(); the boolean flag blocks that false positive.
355+
let expecting = app_handle
356+
.try_state::<AppState>()
357+
.and_then(|s| s.expect_focus_gain.lock().ok().map(|e| *e))
358+
.unwrap_or(false);
359+
if !expecting {
360+
let _ = win_clone.hide();
361+
}
339362
}
340363
tauri::WindowEvent::Resized(_) => {
341364
if win_clone.is_visible().unwrap_or(false) {

src-tauri/src/tray.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,28 @@ fn http_get_then_emit(url: String, app: AppHandle, event: &'static str) {
2727
});
2828
}
2929

30+
/// Shows the popup window, emits refresh events, and sets focus.
31+
/// Used by both the tray left-click handler and the "Show Window" menu item.
32+
/// Sets `expect_focus_gain` so the focus-loss handler won't hide us until
33+
/// the window actually receives `Focused(true)`.
34+
fn show_popup_window(app: &AppHandle) {
35+
if let Some(window) = app.get_webview_window("main") {
36+
// Set flag so the focus-loss handler won't hide us until the window actually
37+
// receives Focused(true). This suppresses the spurious Focused(false) that
38+
// fires on Linux/X11 (and occasionally Windows) before focus arrives.
39+
if let Some(state) = app.try_state::<crate::AppState>() {
40+
if let Ok(mut e) = state.expect_focus_gain.lock() {
41+
*e = true;
42+
}
43+
}
44+
let _ = window.show();
45+
let _ = window.set_focus();
46+
let _ = app.emit("monitors-changed", ());
47+
let _ = app.emit("dark-mode-changed", ());
48+
let _ = app.emit("volume-changed", ());
49+
}
50+
}
51+
3052
/// Builds the system tray icon, context menu, and event handlers.
3153
/// Handles left-click (toggle popup) and menu actions (dark/light mode, profiles, debug, quit).
3254
pub fn setup_tray(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
@@ -38,6 +60,7 @@ pub fn setup_tray(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
3860
}
3961
};
4062

63+
let show_window = MenuItemBuilder::with_id("show_window", "Show Window").build(app)?;
4164
let dark_mode = MenuItemBuilder::with_id("dark_mode", "Dark Mode").build(app)?;
4265
let light_mode = MenuItemBuilder::with_id("light_mode", "Light Mode").build(app)?;
4366

@@ -93,6 +116,8 @@ pub fn setup_tray(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
93116
let quit = MenuItemBuilder::with_id("quit", "Quit").build(app)?;
94117

95118
let menu = MenuBuilder::new(app)
119+
.item(&show_window)
120+
.separator()
96121
.items(&[&dark_mode, &light_mode])
97122
.separator()
98123
.item(&profiles_submenu)
@@ -110,6 +135,9 @@ pub fn setup_tray(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
110135
.menu(&menu)
111136
.show_menu_on_left_click(false)
112137
.on_menu_event(move |app, event| match event.id().as_ref() {
138+
"show_window" => {
139+
show_popup_window(app);
140+
}
113141
"bridge" => {
114142
let url = base_url();
115143
let _ = open::that(&url);
@@ -207,12 +235,7 @@ pub fn setup_tray(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>
207235
);
208236
}
209237
}
210-
let _ = window.show();
211-
let _ = window.set_focus();
212-
// Emit refresh events so frontend fetches latest monitor/dark-mode/volume state
213-
let _ = app.emit("monitors-changed", ());
214-
let _ = app.emit("dark-mode-changed", ());
215-
let _ = app.emit("volume-changed", ());
238+
show_popup_window(app);
216239
}
217240
}
218241
}

0 commit comments

Comments
 (0)