-
Notifications
You must be signed in to change notification settings - Fork 1.3k
perf(desktop): defer hidden dashboard startup #5498
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,6 +365,12 @@ pub struct Startup { | |
| /// before `live`, and never held across an await. | ||
| reporting: Mutex<()>, | ||
| running: AtomicBool, | ||
| /// Whether this window has already left the bundled bootstrap surface. | ||
| /// | ||
| /// Explicit open actions can arrive repeatedly from the tray, the single-instance hook, and | ||
| /// the shell command. Navigating on every action would recreate the React application and | ||
| /// discard renderer state, so the transition is owned here and consumed exactly once per run. | ||
| dashboard_loaded: AtomicBool, | ||
| /// Which run the state belongs to. | ||
| /// | ||
| /// A run's deadline guard outlives the run it was started for, and a retry that begins before | ||
|
|
@@ -385,6 +391,7 @@ impl Startup { | |
| }), | ||
| reporting: Mutex::new(()), | ||
| running: AtomicBool::new(false), | ||
| dashboard_loaded: AtomicBool::new(false), | ||
| generation: AtomicU64::new(0), | ||
| registered: Mutex::new(None), | ||
| } | ||
|
|
@@ -460,6 +467,11 @@ impl Startup { | |
| live.consent = ConsentState::Idle; | ||
| live.reported.clear(); | ||
| live.latest = Progress::new(Phase::NotStarted, 0); | ||
| self.dashboard_loaded.store(false, Ordering::Release); | ||
| } | ||
|
|
||
| fn should_navigate_dashboard(&self) -> bool { | ||
| !self.dashboard_loaded.swap(true, Ordering::AcqRel) | ||
| } | ||
|
|
||
| /// Whether the run has already said how it ended. | ||
|
|
@@ -1379,12 +1391,51 @@ fn finish(app: &AppHandle, started: Instant, endpoint: ProxyEndpoint) { | |
| return; | ||
| } | ||
| if let Some(window) = app.get_webview_window("main") { | ||
| // justified: replacing the bootstrap page with the dashboard is how this window has always | ||
| // navigated, and the string is a URL this process resolved, not anything a page supplied. | ||
| let _ = window.eval(format!("window.location.replace({dashboard:?})")); | ||
| let visible = window.is_visible().unwrap_or(true); | ||
| if loads_dashboard_on_ready(LaunchOrigin::detect(), visible) { | ||
| if app | ||
| .try_state::<Startup>() | ||
| .map_or(true, |startup| startup.should_navigate_dashboard()) | ||
| { | ||
| navigate_dashboard(&window, &dashboard); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Open the full dashboard only when a person asks for it. | ||
| /// | ||
| /// A hidden login launch deliberately leaves its WebView on the tiny bundled startup surface after | ||
| /// the runtime becomes ready. The tray, a second ordinary application launch, or the bootstrap | ||
| /// command reaches this function and pays the dashboard cost at that point. If startup is still in | ||
| /// progress the bootstrap is merely shown; `finish` observes the now-visible window and performs | ||
| /// the navigation once the endpoint is ready. | ||
| pub fn open_dashboard(app: &AppHandle) { | ||
| let dashboard = app.try_state::<Startup>().and_then(|startup| { | ||
| let progress = startup.latest(); | ||
| (progress.phase == Phase::Ready.id()) | ||
| .then_some(progress.dashboard) | ||
| .flatten() | ||
| .filter(|_| startup.should_navigate_dashboard()) | ||
| }); | ||
| if let Some(window) = app.get_webview_window("main") { | ||
| if let Some(dashboard) = dashboard { | ||
| navigate_dashboard(&window, &dashboard); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '800,885p' desktop/src-tauri/src/startup.rs
sed -n '1,140p' structure/decisions/ADR-5494-lightweight-background-startup.md
sed -n '65,90p' structure/desktop-shell.md
rg -n "open_dashboard|navigate_dashboard|location\.replace|Phase::Ready|dashboard" desktop/src-tauri/src/startup.rs desktop/src-tauri/src/lib.rs desktop/src-tauri/src/tray.rsRepository: lidge-jun/opencodex Length of output: 11378 🏁 Script executed: sed -n '180,360p' desktop/src-tauri/src/startup.rs
sed -n '110,180p' desktop/src-tauri/src/lib.rs
sed -n '145,175p' desktop/src-tauri/src/tray.rs
sed -n '1,110p' structure/desktop-shell.mdRepository: lidge-jun/opencodex Length of output: 18432 Navigate the dashboard only once after startup.
Track whether the dashboard has already been opened. Call 🤖 Prompt for AI Agents |
||
| } | ||
| crate::window::show(&window); | ||
|
Comment on lines
+1413
to
+1425
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: sed -n '1370,1450p' desktop/src-tauri/src/startup.rs
rg -n 'finish\(|open_dashboard\(|phase.*Ready|window\.is_visible|LaunchOrigin::detect' desktop/src-tauri/src/startup.rs desktop/src-tauri/src/lib.rs desktop/src-tauri/src/tray.rsRepository: lidge-jun/opencodex Length of output: 4583 🏁 Script executed: set -eu
printf '%s\n' '--- startup state and publication ---'
sed -n '240,345p' desktop/src-tauri/src/startup.rs
rg -n 'fn emit|emit\(|fn latest|latest\(|should_navigate_dashboard|dashboard_loaded|restart|fn show|show\(' desktop/src-tauri/src/startup.rs desktop/src-tauri/src/window.rs desktop/src-tauri/src/lib.rs desktop/src-tauri/src/tray.rs
printf '%s\n' '--- finish callers and startup scheduling ---'
sed -n '880,1040p' desktop/src-tauri/src/startup.rs
sed -n '1240,1305p' desktop/src-tauri/src/startup.rs
printf '%s\n' '--- reachable open_dashboard callers ---'
sed -n '110,215p' desktop/src-tauri/src/lib.rs
sed -n '145,180p' desktop/src-tauri/src/tray.rs
printf '%s\n' '--- relevant tests ---'
rg -n -C 5 'open_dashboard|should_navigate_dashboard|loads_dashboard_on_ready|dashboard_loaded|Phase::Ready|LaunchOrigin' desktop/src-tauri/src --glob '*test*' --glob '*.rs'Repository: lidge-jun/opencodex Length of output: 41821 🏁 Script executed: set -eu
printf '%s\n' '--- Startup exact state/publication methods ---'
sed -n '350,485p' desktop/src-tauri/src/startup.rs
sed -n '1510,1540p' desktop/src-tauri/src/startup.rs
printf '%s\n' '--- startup entry and async scheduling ---'
rg -n -C 8 'pub fn begin|fn begin|tokio::spawn|spawn\(|run_sequence|startup::begin|begin\(&' desktop/src-tauri/src/startup.rs desktop/src-tauri/src/lib.rs
printf '%s\n' '--- command, single-instance, and tray caller context ---'
sed -n '128,205p' desktop/src-tauri/src/lib.rs
sed -n '220,275p' desktop/src-tauri/src/lib.rs
sed -n '120,178p' desktop/src-tauri/src/tray.rs
printf '%s\n' '--- window wrapper and relevant configuration/dependencies ---'
sed -n '1,100p' desktop/src-tauri/src/window.rs
rg -n -C 3 'tauri\s*=|tauri =|tauri-plugin-single-instance|tokio' desktop/src-tauri/Cargo.toml Cargo.toml desktop/src-tauri/tauri.conf.jsonRepository: lidge-jun/opencodex Length of output: 29289 🏁 Script executed: set -eu
printf '%s\n' '--- remaining Startup synchronization and startup task ---'
sed -n '485,570p' desktop/src-tauri/src/startup.rs
sed -n '570,655p' desktop/src-tauri/src/startup.rs
printf '%s\n' '--- exact dependency lock entries ---'
rg -n -A8 -B2 'name = "(tauri|tauri-runtime|tao)"' desktop/src-tauri/Cargo.lock | head -80Repository: lidge-jun/opencodex Length of output: 7728 🌐 Web query:
💡 Result: <source_evidence> Citations:
🌐 Web query:
💡 Result: <source_evidence> Citations:
🏁 Script executed: set -eu
base=https://raw.githubusercontent.com/tauri-apps/tauri/tauri-2.11.6
for path in \
crates/tauri/src/window/mod.rs \
crates/tauri/src/webview/webview_window.rs \
crates/tauri-runtime-wry/src/lib.rs \
crates/tauri-runtime/src/window.rs \
crates/tauri-runtime/src/webview.rs
do
url="$base/$path"
body=$(curl -LfsS "$url" 2>/dev/null || true)
if [ -n "$body" ]; then
printf '%s\n' "--- $url ---"
printf '%s\n' "$body" | rg -n -C 6 'fn (show|is_visible)|send_user_message|set_visible' | head -160
else
printf '%s\n' "--- unavailable $url ---"
fi
doneRepository: lidge-jun/opencodex Length of output: 758 🏁 Script executed: set -eu
printf '%s\n' '--- tauri 2.11.6 WebviewWindow methods ---'
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download |
tar -xzO tauri-2.11.6/src/webview/webview_window.rs |
rg -n -C 8 'pub fn (show|is_visible)|fn (show|is_visible)' | head -120
printf '%s\n' '--- locked runtime package versions ---'
rg -n -A3 -B1 'name = "tauri-runtime(-wry)?"' desktop/src-tauri/Cargo.lock
printf '%s\n' '--- runtime show/visibility implementations ---'
for spec in 'tauri-runtime/2.11.3' 'tauri-runtime-wry/2.11.3'; do
crate=${spec%/*}; version=${spec#*/}
printf '%s\n' "--- $crate $version ---"
curl -LfsS "https://static.crates.io/crates/$crate/$version/download" |
tar -tzf - | rg 'src/(window|webview|lib)\.rs$' | head -20
doneRepository: lidge-jun/opencodex Length of output: 2308 🏁 Script executed: set -eu
printf '%s\n' '--- tauri-runtime 2.11.3 traits ---'
curl -LfsS https://static.crates.io/crates/tauri-runtime/2.11.3/download |
tar -xzO tauri-runtime-2.11.3/src/window.rs |
rg -n -C 12 'fn (show|is_visible)' | head -160
printf '%s\n' '--- tauri-runtime-wry 2.11.4 implementation ---'
curl -LfsS https://static.crates.io/crates/tauri-runtime-wry/2.11.4/download |
tar -xzO tauri-runtime-wry-2.11.4/src/lib.rs |
rg -n -C 14 'fn (show|is_visible)|send_user_message|set_visible|WindowMessage|UserMessage' | head -260Repository: lidge-jun/opencodex Length of output: 8263 🏁 Script executed: set -eu
printf '%s\n' '--- locked runtime-wry 2.11.4 method bodies ---'
curl -LfsS https://static.crates.io/crates/tauri-runtime-wry/2.11.4/download |
tar -xzO tauri-runtime-wry-2.11.4/src/lib.rs |
awk '
/impl<T: UserEvent> WindowDispatch<T> for WryWindowDispatcher/ {on=1}
on && /fn (show|is_visible|hide|set_focus)/ {start=NR-3; end=NR+12}
on && NR>=start && NR<=end {print NR ":" $0}
on && /impl<T: UserEvent> WebviewDispatch/ {exit}
' | head -180
printf '%s\n' '--- Tauri 2.11.6 command invocation scheduling ---'
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download |
tar -xzO tauri-2.11.6/src/app.rs |
rg -n -C 12 'invoke_handler|run_invoke_handler|InvokeHandler|on_message|ipc' | head -260Repository: lidge-jun/opencodex Length of output: 12673 🏁 Script executed: set -eu
printf '%s\n' '--- Tauri 2.11.6 IPC callback path ---'
for path in \
tauri-2.11.6/src/manager/webview/mod.rs \
tauri-2.11.6/src/manager/webview.rs \
tauri-2.11.6/src/ipc/mod.rs \
tauri-2.11.6/src/app.rs
do
printf '%s\n' "--- $path ---"
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download |
tar -xzO "$path" 2>/dev/null |
rg -n -C 18 'invoke_handler|on_message|handle_ipc|InvokeHandler|invoke\(' | head -220 || true
doneRepository: lidge-jun/opencodex Length of output: 12770 🏁 Script executed: set -eu
archive=$(mktemp)
trap 'rm -f "$archive"' EXIT
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download > "$archive"
printf '%s\n' '--- relevant source paths ---'
tar -tzf "$archive" | rg 'tauri-2\.11\.6/src/.+\.rs$' | rg '(manager|webview|ipc|app)' | head -80
printf '%s\n' '--- IPC and invoke locations ---'
for path in $(tar -tzf "$archive" | rg 'tauri-2\.11\.6/src/.+\.rs$' | rg '(manager|webview|ipc|app)'); do
hits=$(tar -xzO -f "$archive" "$path" 2>/dev/null | rg -n 'on_message|process_ipc_message|invoke_handler|AppManager.*invoke|\.invoke\(' || true)
if [ -n "$hits" ]; then
printf '%s\n' "--- $path ---"
printf '%s\n' "$hits"
fi
doneRepository: lidge-jun/opencodex Length of output: 3441 🏁 Script executed: set -eu
archive=$(mktemp)
trap 'rm -f "$archive"' EXIT
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download > "$archive"
printf '%s\n' '--- Tauri Webview IPC dispatch ---'
tar -xzO -f "$archive" tauri-2.11.6/src/webview/mod.rs | sed -n '1725,1920p'
printf '%s\n' '--- Tauri IPC protocol callback registration ---'
tar -xzO -f "$archive" tauri-2.11.6/src/ipc/protocol.rs | sed -n '55,95p'
tar -xzO -f "$archive" tauri-2.11.6/src/ipc/protocol.rs | sed -n '295,325p'Repository: lidge-jun/opencodex Length of output: 8758 🏁 Script executed: set -eu
archive=$(mktemp)
trap 'rm -f "$archive"' EXIT
curl -LfsS https://static.crates.io/crates/tauri-runtime-wry/2.11.4/download > "$archive"
printf '%s\n' '--- Wry webview message callback path ---'
tar -xzO -f "$archive" tauri-runtime-wry-2.11.4/src/lib.rs |
rg -n -C 18 'on_message|WebviewEvent|Ipc|Message.*Webview|handle_user_message' | head -360
printf '%s\n' '--- Tauri tray callback registration path ---'
curl -LfsS https://static.crates.io/crates/tauri/2.11.6/download |
tar -xzO tauri-2.11.6/src/manager/tray.rs |
rg -n -C 16 'on_tray|callback|TrayIconEvent|event_loop|send_event' | head -260Repository: lidge-jun/opencodex Length of output: 13410 🏁 Script executed: set -eu
for spec in 'tauri-runtime-wry 2.11.4 tauri-runtime-wry-2.11.4/src/lib.rs' 'tauri 2.11.6 tauri-2.11.6/src/manager/mod.rs'; do
set -- $spec
crate=$1; version=$2; path=$3
printf '%s\n' "--- $crate $version $path ---"
curl -LfsS "https://static.crates.io/crates/$crate/$version/download" |
tar -xzO "$path" |
rg -n 'IpcHandler|ipc_handler|on_tray_icon_event|global_event_listeners|event_listeners.*Tray|TrayIconEvent' | head -120
doneRepository: lidge-jun/opencodex Length of output: 925 🏁 Script executed: set -eu
curl -LfsS https://static.crates.io/crates/tauri-runtime-wry/2.11.4/download |
tar -xzO tauri-runtime-wry-2.11.4/src/lib.rs |
sed -n '5070,5190p;5368,5425p'Repository: lidge-jun/opencodex Length of output: 5543 🏁 Script executed: set -eu
printf '%s\n' '--- locked single-instance version ---'
rg -n -A3 -B1 'name = "tauri-plugin-single-instance"' desktop/src-tauri/Cargo.lock
printf '%s\n' '--- locked single-instance callback implementation ---'
curl -LfsS https://static.crates.io/crates/tauri-plugin-single-instance/2.4.0/download |
tar -tzf - | rg 'src/.+\.rs$' | head -30
curl -LfsS https://static.crates.io/crates/tauri-plugin-single-instance/2.4.0/download |
tar -xzO tauri-plugin-single-instance-2.4.0/src/lib.rs |
rg -n -C 18 'callback|spawn|send_event|run_on_main_thread|secondary|instance' | head -320Repository: lidge-jun/opencodex Length of output: 4278 🏁 Script executed: set -eu
archive=$(mktemp)
trap 'rm -f "$archive"' EXIT
curl -LfsS https://static.crates.io/crates/tauri-plugin-single-instance/2.4.0/download > "$archive"
for path in \
tauri-plugin-single-instance-2.4.0/src/platform_impl/linux.rs \
tauri-plugin-single-instance-2.4.0/src/platform_impl/macos.rs \
tauri-plugin-single-instance-2.4.0/src/platform_impl/windows.rs
do
printf '%s\n' "--- $path ---"
tar -xzO -f "$archive" "$path" |
rg -n -C 18 'callback|spawn|run_on_main_thread|send_event|invoke|thread' | head -260
doneRepository: lidge-jun/opencodex Length of output: 9354 Preserve an explicit dashboard-open request across the Ready transition. On macOS, Record the explicit-open request before reading the phase, and make Suggested fix pub struct Startup {
live: Mutex<Live>,
reporting: Mutex<()>,
running: AtomicBool,
dashboard_loaded: AtomicBool,
+ dashboard_open_requested: AtomicBool,
generation: AtomicU64,
registered: Mutex<Option<Registration>>,
}
running: AtomicBool::new(false),
dashboard_loaded: AtomicBool::new(false),
+ dashboard_open_requested: AtomicBool::new(false),
generation: AtomicU64::new(0),
registered: Mutex::new(None),
@@
live.latest = Progress::new(Phase::NotStarted, 0);
self.dashboard_loaded.store(false, Ordering::Release);
+ self.dashboard_open_requested.store(false, Ordering::Release);
}
+ fn request_dashboard_open(&self) {
+ self.dashboard_open_requested.store(true, Ordering::Release);
+ }
+
+ fn dashboard_open_requested(&self) -> bool {
+ self.dashboard_open_requested.load(Ordering::Acquire)
+ }
+
@@
- if loads_dashboard_on_ready(LaunchOrigin::detect(), visible) {
+ let requested = app
+ .try_state::<Startup>()
+ .map_or(false, |startup| startup.dashboard_open_requested());
+ if loads_dashboard_on_ready(LaunchOrigin::detect(), visible) || requested {
if app
.try_state::<Startup>()
.map_or(true, |startup| startup.should_navigate_dashboard())
@@
pub fn open_dashboard(app: &AppHandle) {
let dashboard = app.try_state::<Startup>().and_then(|startup| {
+ startup.request_dashboard_open();
let progress = startup.latest();🤖 Prompt for AI Agents |
||
| } | ||
| } | ||
|
|
||
| fn loads_dashboard_on_ready(origin: LaunchOrigin, window_visible: bool) -> bool { | ||
| origin == LaunchOrigin::User || window_visible | ||
| } | ||
|
|
||
| fn navigate_dashboard(window: &tauri::WebviewWindow, dashboard: &str) { | ||
| // justified: replacing the bootstrap page with the dashboard is how this window has always | ||
| // navigated, and the string is a URL this process resolved, not anything a page supplied. | ||
| let _ = window.eval(format!("window.location.replace({dashboard:?})")); | ||
| } | ||
|
|
||
| #[allow(clippy::too_many_arguments)] | ||
| fn fail( | ||
| app: &AppHandle, | ||
|
|
@@ -1489,9 +1540,9 @@ fn elapsed(started: Instant) -> u64 { | |
| #[cfg(test)] | ||
| mod tests { | ||
| use super::{ | ||
| approval_still_current, attach_plan, claim_after_silence, shows_window, | ||
| stop_after_approval, unavailable, AttachPlan, ConsentState, Expiry, LaunchOrigin, Phase, | ||
| Progress, Startup, AUTOSTART_FLAG, DEADLINE, PHASES, POLL, | ||
| approval_still_current, attach_plan, claim_after_silence, loads_dashboard_on_ready, | ||
| shows_window, stop_after_approval, unavailable, AttachPlan, ConsentState, Expiry, | ||
| LaunchOrigin, Phase, Progress, Startup, AUTOSTART_FLAG, DEADLINE, PHASES, POLL, | ||
| }; | ||
| use crate::claim::ClaimResult; | ||
| use crate::ownership::{Claim, Consent, Owner, Recorded}; | ||
|
|
@@ -1773,6 +1824,25 @@ mod tests { | |
| )); | ||
| } | ||
|
|
||
| #[test] | ||
| fn only_a_hidden_login_launch_defers_the_full_dashboard() { | ||
| assert!(loads_dashboard_on_ready(LaunchOrigin::User, false)); | ||
| assert!(loads_dashboard_on_ready(LaunchOrigin::User, true)); | ||
| assert!(loads_dashboard_on_ready(LaunchOrigin::Autostart, true)); | ||
| assert!(!loads_dashboard_on_ready(LaunchOrigin::Autostart, false)); | ||
| } | ||
|
|
||
| #[test] | ||
| fn explicit_dashboard_navigation_is_consumed_once_per_run() { | ||
| let startup = Startup::new(); | ||
| assert!(startup.should_navigate_dashboard()); | ||
| assert!(!startup.should_navigate_dashboard()); | ||
|
|
||
| startup.restart(); | ||
| assert!(startup.should_navigate_dashboard()); | ||
| assert!(!startup.should_navigate_dashboard()); | ||
| } | ||
|
|
||
| #[test] | ||
| fn a_login_launch_hides_only_where_there_is_a_tray_to_hide_in() { | ||
| assert!(!shows_window( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| # ADR-5494 — decision recorded under "Startup, quit and the tray" | ||
|
|
||
| - Contract owner: [desktop-shell.md](../desktop-shell.md#startup-quit-and-the-tray) | ||
|
|
||
| ## Decision record | ||
|
|
||
| - 목적과 의도: Keep a login-started desktop shell ready in the background without paying the full dashboard's render and polling cost before a person opens it. | ||
| - 기존 구현 및 제약 조건: The shell already owns a small bundled startup surface, but every successful startup replaced it with the loopback dashboard even when the main window remained hidden behind a usable tray. | ||
| - 검토한 주요 대안: Destroy and recreate the WebView on every open; add a second dashboard window; suspend individual dashboard pollers; or retain the existing startup surface until the first explicit open. | ||
| - 선택한 방식: A hidden autostart launch stays on the bundled ready surface. Manual launches and any visible no-tray launch keep eager dashboard navigation; tray Open Dashboard, a second ordinary launch, and the shell command lazily navigate before showing. | ||
| - 다른 대안 대신 이 방식을 선택한 이유: It removes background React work without adding a window, renderer lifecycle, daemon, or new state owner, and it preserves the already-tested visible startup and failure surface. | ||
| - 장점, 단점 및 영향: Background login uses less work and explicit opens remain immediate after one navigation. The first open after hidden startup now pays the dashboard load once, while visible/manual behavior is unchanged. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,6 +159,28 @@ describe("desktop startup surface", () => { | |
| expect(page).toContain("progress.failedPhase"); | ||
| }); | ||
|
|
||
| test("a hidden login launch keeps the lightweight surface until an explicit open", () => { | ||
| const finish = startup.slice( | ||
| startup.indexOf("fn finish("), | ||
| startup.indexOf("pub fn diagnostic("), | ||
| ); | ||
| expect(finish).toContain("loads_dashboard_on_ready(LaunchOrigin::detect(), visible)"); | ||
| expect(finish).toContain("window.is_visible()"); | ||
| expect(finish).toContain("pub fn open_dashboard("); | ||
| expect(finish).toContain("progress.phase == Phase::Ready.id()"); | ||
| expect(finish).toContain("startup.should_navigate_dashboard()"); | ||
| expect(finish).toContain("crate::window::show(&window)"); | ||
| expect(startup).toContain("fn explicit_dashboard_navigation_is_consumed_once_per_run()"); | ||
| expect(startup).toContain("assert!(startup.should_navigate_dashboard())"); | ||
| expect(startup).toContain("assert!(!startup.should_navigate_dashboard())"); | ||
|
|
||
| expect(lib).toContain("startup::open_dashboard(&app)"); | ||
| expect(lib).toContain("startup::open_dashboard(app)"); | ||
| const tray = code(repoPath(`${SRC}/tray.rs`)); | ||
| expect(tray).toContain('"open-dashboard" =>'); | ||
| expect(tray).toContain("crate::startup::open_dashboard(app)"); | ||
| }); | ||
|
Comment on lines
+167
to
+182
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Test the first-open navigation invariant. This test passes when As per path instructions, “A behavior change in src/ should come with a focused regression test near the existing tests for that subsystem.” Based on learnings, tests should assert relevant postconditions and invariants. 🤖 Prompt for AI AgentsSources: Path instructions, Learnings |
||
|
|
||
| test("the snapshot answers with a state rather than with nothing", () => { | ||
| // The page returns early on a falsy progress, so an absent answer was not a neutral one: it | ||
| // was a window frozen on its own markup, with no diagnostic in it and no event coming. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: lidge-jun/opencodex
Length of output: 6058
🏁 Script executed:
Repository: lidge-jun/opencodex
Length of output: 14164
🌐 Web query:
official Tauri 2.11.6 WebviewWindow eval Result contract💡 Result:
<source_evidence>
Citations:
Retry dashboard navigation after an evaluation error.
should_navigate_dashboard()consumesdashboard_loadedbeforenavigate_dashboard()callsWebviewWindow::eval. IfevalreturnsErr,navigate_dashboard()discards the error, and later tray or command opens cannot retry the dashboard navigation. Handle the error and release the consumed guard so a later open can retry. Do not mark the dashboard as loaded based onOk(()): Tauri'sevalreturnsResult<()>, which reports the evaluation request status and does not provide a completed-navigation result.🤖 Prompt for AI Agents