mirror of
https://github.com/forkless/NotAlterra.git
synced 2026-08-16 00:26:38 +02:00
v0.4.3: dashboard count fixes, mtime preservation, nav bound fix
This commit is contained in:
@@ -4,6 +4,14 @@ All notable changes to NotAlterra are documented in this file.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## [v0.4.3] — 2026-06-09
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **Dashboard counts** — "Saves" now shows `.bak` recovery file count, "Backups" shows `.tar.gz` archive count
|
||||||
|
- **Backup mtime preservation** — tar archives now store source file modification times, preventing epoch dates on restored files
|
||||||
|
- **Navigation bound** — restore backup picker no longer stops before migrated entries
|
||||||
|
- **Save folder dialog** — pre-fills with the current path if one is already set
|
||||||
|
|
||||||
## [v0.4.2] — 2026-06-09
|
## [v0.4.2] — 2026-06-09
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
Generated
+1
-1
@@ -540,7 +540,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notalterra"
|
name = "notalterra"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "notalterra"
|
name = "notalterra"
|
||||||
version = "0.4.2"
|
version = "0.4.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["NotAlterra"]
|
authors = ["NotAlterra"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
+7
-16
@@ -6,23 +6,14 @@ extract, and run.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### v0.4.2 — Pinned headers & layout polish
|
### v0.4.3 — Dashboard & backup integrity fixes
|
||||||
|
|
||||||
**UI**
|
**Fixed**
|
||||||
• Restore backup picker: pinned column headers, wider Backup column, right-aligned Size
|
• Dashboard counts now correct: "Saves" shows `.bak` recovery file count, "Backups" shows `.tar.gz` archive count
|
||||||
• INI restore picker: matching pinned header with "INI Backup" / "Size" columns
|
• Backup archives now preserve source file modification times — restored files keep their original dates instead of showing 1970-01-01 on Windows
|
||||||
• All picker highlight colour changed to yellow for better visibility
|
• Restore backup picker navigation no longer stops before migrated entries
|
||||||
• Main menu entries shifted 1 left; INI submenu entries aligned with main menu
|
• Save folder input dialog pre-fills with the currently set path
|
||||||
• Spacer row between list content and status bar on all screens
|
• SLSA provenance attestation re-enabled (`upload-assets: true`)
|
||||||
• Non-blocking info dialog for backup-in-progress (no button, auto-replaced)
|
|
||||||
|
|
||||||
**Layout**
|
|
||||||
• Backup column widened from 30→38 chars; header/data total widths matched
|
|
||||||
• Size header right-aligned above file-size values in both restore pickers
|
|
||||||
• INI submenu header changed to cyan, shifted 3 right
|
|
||||||
|
|
||||||
**Backup flow**
|
|
||||||
• No intermediate spinner page — info popup followed by summary dialog
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ What happened? What did you expect to happen instead?
|
|||||||
### Environment
|
### Environment
|
||||||
|
|
||||||
- **OS**: (e.g. Windows 11, Ubuntu 24.04, Steam Deck)
|
- **OS**: (e.g. Windows 11, Ubuntu 24.04, Steam Deck)
|
||||||
- **NotAlterra version**: (shown in the title bar, e.g. v0.4.2)
|
- **NotAlterra version**: (shown in the title bar, e.g. v0.4.3)
|
||||||
- **Subnautica 2 install**: (Steam, Xbox, Epic, custom)
|
- **Subnautica 2 install**: (Steam, Xbox, Epic, custom)
|
||||||
|
|
||||||
### Logs
|
### Logs
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ triggers the issue.
|
|||||||
|
|
||||||
### Affected versions
|
### Affected versions
|
||||||
|
|
||||||
- NotAlterra version(s): (e.g. v0.4.2)
|
- NotAlterra version(s): (e.g. v0.4.3)
|
||||||
- Platform: (Windows / Linux / both)
|
- Platform: (Windows / Linux / both)
|
||||||
|
|
||||||
### Impact assessment
|
### Impact assessment
|
||||||
|
|||||||
+4
-3
@@ -139,9 +139,10 @@ fn exe_dir() -> PathBuf {
|
|||||||
/// any backup/restore operation.
|
/// any backup/restore operation.
|
||||||
fn refresh_stats(tui_state: &mut tui::AppState, save_folder: Option<&Path>) {
|
fn refresh_stats(tui_state: &mut tui::AppState, save_folder: Option<&Path>) {
|
||||||
tui_state.save_path = save_folder.map(|p| p.display().to_string());
|
tui_state.save_path = save_folder.map(|p| p.display().to_string());
|
||||||
let (live, bak, ini) = ops::folder_stats(save_folder);
|
let (_live, _bak, ini) = ops::folder_stats(save_folder);
|
||||||
tui_state.live_save_count = live;
|
// "Saves" = .bak recovery files (the restore points in the save folder)
|
||||||
tui_state.backup_count = bak;
|
tui_state.live_save_count = _bak;
|
||||||
|
tui_state.backup_count = ops::list_full_backups().len();
|
||||||
tui_state.has_ini_backup = ini;
|
tui_state.has_ini_backup = ini;
|
||||||
tui_state.context_path = Some(crate::config::get_backup_root().display().to_string());
|
tui_state.context_path = Some(crate::config::get_backup_root().display().to_string());
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -138,6 +138,15 @@ fn create_tar_gz(
|
|||||||
.with_context(|| format!("failed to set path '{name}' in tar header"))?;
|
.with_context(|| format!("failed to set path '{name}' in tar header"))?;
|
||||||
header.set_size(data.len() as u64);
|
header.set_size(data.len() as u64);
|
||||||
header.set_mode(0o644); // owner read/write, group/other read
|
header.set_mode(0o644); // owner read/write, group/other read
|
||||||
|
// Preserve the source file's mtime so the extracted file keeps its
|
||||||
|
// original date. Without this, the mtime defaults to epoch (1970).
|
||||||
|
if let Ok(src_meta) = fs::metadata(&src_path) {
|
||||||
|
if let Ok(mtime) = src_meta.modified() {
|
||||||
|
if let Ok(dur) = mtime.duration_since(std::time::UNIX_EPOCH) {
|
||||||
|
header.set_mtime(dur.as_secs());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
header.set_cksum();
|
header.set_cksum();
|
||||||
tar_builder
|
tar_builder
|
||||||
.append(&header, &data[..])
|
.append(&header, &data[..])
|
||||||
@@ -358,8 +367,12 @@ pub fn list_bak_files_with_meta(save_folder: &Path) -> Vec<BakFileSummary> {
|
|||||||
let filename = entry.file_name().to_string_lossy().to_string();
|
let filename = entry.file_name().to_string_lossy().to_string();
|
||||||
let meta = fs::metadata(&path).ok();
|
let meta = fs::metadata(&path).ok();
|
||||||
let size = meta.as_ref().map(|m| m.len()).unwrap_or(0);
|
let size = meta.as_ref().map(|m| m.len()).unwrap_or(0);
|
||||||
let mtime = meta.as_ref().and_then(|m| m.modified().ok()).and_then(|t| {
|
let mtime = meta.as_ref().and_then(|m| {
|
||||||
|
// Try modified time first; fall back to creation time (Windows)
|
||||||
|
let t = m.modified().or_else(|_| m.created()).ok()?;
|
||||||
let secs = t.duration_since(std::time::UNIX_EPOCH).ok()?.as_secs();
|
let secs = t.duration_since(std::time::UNIX_EPOCH).ok()?.as_secs();
|
||||||
|
// Reject epoch (Jan 1 1970) — indicates filesystem couldn't provide a real time
|
||||||
|
if secs == 0 { return None; }
|
||||||
Local
|
Local
|
||||||
.timestamp_opt(secs as i64, 0)
|
.timestamp_opt(secs as i64, 0)
|
||||||
.single()
|
.single()
|
||||||
|
|||||||
Reference in New Issue
Block a user