Skip to main content

modde_ui/views/
save_details.rs

1//! Save snapshot detail panel — rendered at the bottom of the left sidebar
2//! when a save snapshot is selected in the saves view.
3
4use modde_core::save::{FingerprintCheck, SaveFingerprint, SaveSnapshot};
5
6/// State for the currently-selected save snapshot's detail panel.
7#[derive(Debug, Clone)]
8pub struct SaveDetailsState {
9    /// Full commit hash — used to reject stale async results.
10    pub commit_id: String,
11    /// Short commit hash for display.
12    pub short_id: String,
13    /// Unix timestamp of the snapshot.
14    pub timestamp: i64,
15    /// Profile name extracted from the commit message.
16    pub profile_name: Option<String>,
17    /// Character/player name extracted from the save label.
18    pub character_name: Option<String>,
19    /// Save label (e.g. "Save 14").
20    pub save_label: Option<String>,
21    /// Save category (e.g. "manual", "auto", "quick").
22    pub category: Option<String>,
23    /// Number of files in this snapshot.
24    pub file_count: usize,
25    /// File paths in the snapshot tree. `None` until loaded.
26    pub file_paths: Option<Vec<String>>,
27    /// Mod fingerprint from the commit.
28    pub fingerprint: Option<SaveFingerprint>,
29    /// Compatibility check result against the current profile.
30    pub compatibility: Option<FingerprintCheck>,
31}
32
33impl SaveDetailsState {
34    /// Construct from a `SaveSnapshot` and an optional compatibility check result.
35    #[must_use]
36    pub fn from_snapshot(snap: &SaveSnapshot, compat: Option<FingerprintCheck>) -> Self {
37        Self {
38            commit_id: snap.id.clone(),
39            short_id: snap.short_id().to_string(),
40            timestamp: snap.timestamp,
41            profile_name: snap.profile_name.clone(),
42            character_name: snap.character_name.clone(),
43            save_label: snap.save_label.clone(),
44            category: snap.category.clone(),
45            file_count: snap.file_count,
46            file_paths: None,
47            fingerprint: snap.fingerprint.clone(),
48            compatibility: compat,
49        }
50    }
51
52    /// Formatted date string for display.
53    #[must_use]
54    pub fn formatted_date(&self) -> String {
55        modde_core::save::format_timestamp(self.timestamp)
56    }
57
58    /// Human-readable title: character + save label, or fallback.
59    #[must_use]
60    pub fn display_title(&self) -> String {
61        if let (Some(char_name), Some(label)) = (&self.character_name, &self.save_label) {
62            format!("{char_name} — {label}")
63        } else if let Some(char_name) = &self.character_name {
64            char_name.clone()
65        } else if let Some(label) = &self.save_label {
66            label.clone()
67        } else {
68            "Save snapshot".to_string()
69        }
70    }
71}