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
25		Self { CurrentPhase:Arc::new(StandardMutex::new(1)) }
26	}
27}
28
29impl LifecyclePhaseState {
30	/// Return the current lifecycle phase.
31	pub fn GetPhase(&self) -> Phase { self.CurrentPhase.lock().ok().map(|Guard| *Guard).unwrap_or(1) }
32
33	/// Advance the lifecycle phase. Only advances forward - never backwards.
34	pub fn SetPhase(&self, NewPhase:Phase) {
35		if let Ok(mut Guard) = self.CurrentPhase.lock() {
36			if NewPhase > *Guard {
37				dev_log!("lifecycle", "[LifecyclePhaseState] Phase advanced: {} → {}", *Guard, NewPhase);
38
39				*Guard = NewPhase;
40			}
41		}
42	}
43
44	/// Advance the phase and emit a `sky://lifecycle/phaseChanged` Tauri
45	/// event so the workbench (subscribed via
46	/// `TauriChannel("lifecycle").listen("onDidChangePhase")`) can gate
47	/// long-running services (extension discovery, telemetry, heavy
48	/// providers) until the editor is fully restored. Mirrors VS Code's
49	/// `ILifecycleService.onDidChangePhase` signal.
50	pub fn AdvanceAndBroadcast<R:tauri::Runtime>(&self, NewPhase:Phase, ApplicationHandle:&tauri::AppHandle<R>) {
51		// Local `use tauri::Emitter` removed - now routed through
52		// `LogSkyEmit` which carries the trait import internally.
53		let Previous = self.GetPhase();
54
55		if NewPhase <= Previous {
56			return;
57		}
58
59		self.SetPhase(NewPhase);
60
61		let Label = match NewPhase {
62			1 => "Starting",
63
64			2 => "Ready",
65
66			3 => "Restored",
67
68			4 => "Eventually",
69
70			_ => "Unknown",
71		};
72
73		if let Err(Error) = LogSkyEmit(
74			ApplicationHandle,
75			SkyEvent::LifecyclePhaseChanged.AsStr(),
76			serde_json::json!({
77				"phase": NewPhase,
78				"previous": Previous,
79				"label": Label,
80			}),
81		) {
82			dev_log!(
83				"lifecycle",
84				"warn: [LifecyclePhaseState] sky://lifecycle/phaseChanged emit failed: {}",
85				Error
86			);
87		}
88	}
89}