diff --git a/server/build.rs b/server/build.rs index af36bd4..848267e 100644 --- a/server/build.rs +++ b/server/build.rs @@ -1,25 +1,29 @@ use std::process::Command; fn main() { - let git_hash = Command::new("git") + let mut git_hash = Command::new("git") .args(["rev-parse", "--short", "HEAD"]) .output() .ok() .and_then(|out| String::from_utf8(out.stdout).ok()) .unwrap_or_else(|| "unknown".to_string()); + + git_hash = git_hash.trim().to_string(); - let git_date = Command::new("git") - .args(["log", "-1", "--format=%cd", "--date=format:%y.%m.%d.%H%M%S"]) + let is_dirty = Command::new("git") + .args(["status", "--porcelain"]) .output() .ok() - .and_then(|out| String::from_utf8(out.stdout).ok()) - .unwrap_or_else(|| "unknown".to_string()); + .map(|out| !out.stdout.is_empty()) + .unwrap_or(false); - let version = format!( - "{} ({})", - git_date.trim(), - git_hash.trim() - ); + if is_dirty { + git_hash.push_str("-dirty"); + } + + let build_date = chrono::Local::now().format("%y.%m.%d.%H%M%S").to_string(); + + let version = format!("{} ({})", build_date, git_hash); println!("cargo:rustc-env=APP_VERSION={}", version); if std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default() == "windows" { diff --git a/server/src/dashboard.html b/server/src/dashboard.html index 2dc8deb..41585f3 100644 --- a/server/src/dashboard.html +++ b/server/src/dashboard.html @@ -893,6 +893,33 @@ } // --- WebSocket Activity Feed --- + const MAX_ACTIVITY_HISTORY = 100; + + function saveActivityHistory(time, htmlData) { + try { + let history = JSON.parse(localStorage.getItem('activityHistory') || '[]'); + history.push({ time, data: htmlData }); + if (history.length > MAX_ACTIVITY_HISTORY) history = history.slice(-MAX_ACTIVITY_HISTORY); + localStorage.setItem('activityHistory', JSON.stringify(history)); + } catch(e) {} + } + + function loadActivityHistory() { + try { + const feed = document.getElementById('activity-feed'); + let history = JSON.parse(localStorage.getItem('activityHistory') || '[]'); + history.forEach(item => { + const div = document.createElement('div'); + div.className = 'feed-entry'; + div.innerHTML = `[${item.time}] ${item.data}`; + feed.appendChild(div); + }); + if (history.length > 0) { + feed.scrollTop = feed.scrollHeight; + } + } catch(e) {} + } + function setupWS() { const protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; const ws = new WebSocket(`${protocol}//${location.host}/ws?client=ui`); @@ -908,6 +935,8 @@ div.innerHTML = `[${time}] ${data.data}`; feed.appendChild(div); + saveActivityHistory(time, data.data); + // Auto-scroll logic const isScrolledToBottom = feed.scrollHeight - feed.clientHeight <= feed.scrollTop + 20; if (isScrolledToBottom) { @@ -967,6 +996,7 @@ loadGraph(); loadTasks(); loadStickyNotes(); + loadActivityHistory(); setupWS(); // Listen to theme toggle changes to update graph font colors