teamctl_ui/tutorial.rs
1//! First-launch detection via a marker file under the user's config
2//! directory. PR-UI-1 ships only the plumbing: `is_completed()` reads
3//! the marker; the actual onboarding tutorial that writes the marker
4//! lands in PR-UI-7.
5
6use std::path::PathBuf;
7
8const MARKER_RELATIVE: &str = "teamctl/ui-tutorial-completed";
9
10/// Returns the path the marker file lives at. Honours `XDG_CONFIG_HOME`
11/// via `dirs::config_dir`, falling back to platform defaults.
12pub fn marker_path() -> Option<PathBuf> {
13 dirs::config_dir().map(|root| root.join(MARKER_RELATIVE))
14}
15
16/// Has the operator finished the onboarding tutorial on this machine?
17/// Returns `false` when the marker is absent, the config dir is
18/// unresolvable, or the file is unreadable for any reason — first-launch
19/// detection should never panic an otherwise-healthy launch.
20pub fn is_completed() -> bool {
21 marker_path().is_some_and(|p| p.exists())
22}
23
24/// Write the marker so subsequent launches skip the tutorial. Reserved
25/// for PR-UI-7's tutorial completion path; here only as the boundary
26/// of the public API so the rest of the crate can refer to it.
27#[allow(dead_code)]
28pub fn mark_completed() -> std::io::Result<()> {
29 let Some(path) = marker_path() else {
30 return Ok(());
31 };
32 if let Some(parent) = path.parent() {
33 std::fs::create_dir_all(parent)?;
34 }
35 std::fs::write(&path, b"")
36}