Skip to main content

Mountain/ApplicationState/State/FeatureState/LifecyclePhase/
LifecyclePhaseState.rs

1use std::sync::{Arc, Mutex as StandardMutex};
2
3use CommonLibrary::IPC::SkyEvent::SkyEvent;
4
5use crate::{IPC::SkyEmit::LogSkyEmit, dev_log};
6
7/// Application lifecycle phases (mirrors VS Code LifecyclePhase).
8/// 1 = Starting, 2 = Ready, 3 = Restored, 4 = Eventually
9pub type Phase = u8;
10
11/// Tracks the current application lifecycle phase.
12/// Components poll this to defer work until the editor is fully initialised.
13#[derive(Clone)]
14pub struct LifecyclePhaseState {
15	CurrentPhase:Arc<StandardMutex<Phase>>,
16}
17
18impl Default for LifecyclePhaseState {
19	fn default() -> Self {
20		dev_log!(
21			"lifecycle",
22			"[LifecyclePhaseState] Initializing default lifecycle state (phase 1: Starting)..."
23		);
24		Self { CurrentPhase:Arc::new(StandardMutex::new(1)) }
25	}
26}
27
28impl LifecyclePhaseState {
29	/// Return the current lifecycle phase.
30	pub fn GetPhase(&self) -> Phase { self.CurrentPhase.lock().ok().map(|Guard| *Guard).unwrap_or(1) }
31
32	/// Advance the lifecycle phase. Only advances forward - never backwards.
33	pub fn SetPhase(&self, NewPhase:Phase) {
34		if let Ok(mut Guard) = self.CurrentPhase.lock() {
35			if NewPhase > *Guard {
36				dev_log!("lifecycle", "[LifecyclePhaseState] Phase advanced: {} → {}", *Guard, NewPhase);
37				*Guard = NewPhase;
38			}
39		}
40	}
41
42	/// Advance the phase and emit a `sky://lifecycle/phaseChanged` Tauri
43	/// event so the workbench (subscribed via
44	/// `TauriChannel("lifecycle").listen("onDidChangePhase")`) can gate
45	/// long-running services (extension discovery, telemetry, heavy
46	/// providers) until the editor is fully restored. Mirrors VS Code's
47	/// `ILifecycleService.onDidChangePhase` signal.
48	pub fn AdvanceAndBroadcast<R:tauri::Runtime>(&self, NewPhase:Phase, ApplicationHandle:&tauri::AppHandle<R>) {
49		// Local `use tauri::Emitter` removed - now routed through
50		// `LogSkyEmit` which carries the trait import internally.
51		let Previous = self.GetPhase();
52		if NewPhase <= Previous {
53			return;
54		}
55		self.SetPhase(NewPhase);
56		let Label = match NewPhase {
57			1 => "Starting",
58			2 => "Ready",
59			3 => "Restored",
60			4 => "Eventually",
61			_ => "Unknown",
62		};
63		if let Err(Error) = LogSkyEmit(
64			ApplicationHandle,
65			SkyEvent::LifecyclePhaseChanged.AsStr(),
66			serde_json::json!({
67				"phase": NewPhase,
68				"previous": Previous,
69				"label": Label,
70			}),
71		) {
72			dev_log!(
73				"lifecycle",
74				"warn: [LifecyclePhaseState] sky://lifecycle/phaseChanged emit failed: {}",
75				Error
76			);
77		}
78	}
79}