app
Shotlog - Screenshot Log
Public Made by Adomby adom
See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Bridge child-window arrays via --meta.
← Commit history
Publish 0.26.2
9 files changed
+28−12
Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "adom-shotlog"-version = "0.26.1"+version = "0.26.2" dependencies = [ "axum", "base64",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-shotlog"-version = "0.26.1"+version = "0.26.2" edition = "2021" description = "Screenshot log viewer and CLI for Adom" license = "MIT"
VERSION+1−1@@ -1 +1 @@-0.26.1+0.26.2
bin/adom-shotlog⋯ 1 unchanged line ⋯
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.26.1",+ "version": "0.26.2", "type": "app", "title": "Shotlog - Screenshot Log", "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Bridge child-window arrays via --meta.",
page.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-shotlog",- "version": "0.26.1",+ "version": "0.26.2", "type": "app", "title": "Shotlog - Screenshot Log", "description": "See the shots your AI never showed you, and know it actually SAW them. adom-shotlog streams every screenshot the AI gathers into a live gallery (webview/pup/browser/phone), reports whether a human is really watching and on which surface, and ingests Adom Bridge child-window arrays via --meta.",
src/html/index.html+10−2@@ -1694,8 +1694,16 @@ body.compact .card-popups .ph { padding-top: 4px; } t=setTimeout(reset,3000); return; } reset(); entries=[]; renderAll();- await fetch('api/clear-all?channel='+encodeURIComponent(channel),{method:'DELETE'}).catch(()=>{});- showToast('cleared');+ try{+ const r=await fetch('api/clear-all?channel='+encodeURIComponent(channel),{method:'DELETE'}).then(x=>x.json());+ const b=r.bytes_freed||0;+ // Human-readable: GB once it's a gigabyte-scale cleanup, else MB/KB.+ const size = b>=1024*1024*1024 ? (b/(1024*1024*1024)).toFixed(2)+' GB'+ : b>=1024*1024 ? (b/(1024*1024)).toFixed(1)+' MB'+ : b>0 ? Math.max(1,Math.round(b/1024))+' KB'+ : '0 KB';+ showToast('cleared '+(r.cleared??0)+' shot'+((r.cleared??0)===1?'':'s')+' - freed '+size+' of disk', 7000);+ }catch{ showToast('cleared'); } }); })();
src/server.rs+3−2@@ -1445,8 +1445,9 @@ async fn clear_all( Query(q): Query<ChannelQuery>, ) -> Json<serde_json::Value> { let channel = q.channel.unwrap_or_else(|| "default".into());- let count = state.store.clear_all(&channel).await;- Json(serde_json::json!({ "ok": true, "cleared": count, "files_deleted": true }))+ let (count, bytes_freed) = state.store.clear_all(&channel).await;+ println!("{} CLEAR '{channel}': {count} shot(s), {bytes_freed} bytes freed.", ts());+ Json(serde_json::json!({ "ok": true, "cleared": count, "files_deleted": true, "bytes_freed": bytes_freed })) } #[derive(Deserialize)]
src/store.rs+10−3@@ -580,8 +580,12 @@ impl Store { } /// Clear entries AND delete all files for a channel.- pub async fn clear_all(&self, channel_name: &str) -> usize {+ /// Returns (shots cleared, BYTES actually freed from disk) - the byte count+ /// sums every deleted file (safe PNGs, __full pairs, __popup child windows,+ /// .json sidecars), so the human can be told how much space came back.+ pub async fn clear_all(&self, channel_name: &str) -> (usize, u64) { let count = self.clear_log(channel_name).await;+ let mut bytes_freed: u64 = 0; let channel_dir = self.base_dir.join(channel_name); if channel_dir.is_dir() { if let Ok(entries) = fs::read_dir(&channel_dir) {@@ -591,13 +595,16 @@ impl Store { // sidecars and __popup child-window PNGs must go too, or the // folder fills with orphaned metadata. match p.extension().and_then(|e| e.to_str()) {- Some("png") | Some("json") => { fs::remove_file(&p).ok(); }+ Some("png") | Some("json") => {+ let sz = fs::metadata(&p).map(|m| m.len()).unwrap_or(0);+ if fs::remove_file(&p).is_ok() { bytes_freed += sz; }+ } _ => {} } } } }- count+ (count, bytes_freed) } /// List all channel names.