Skip to content

Commit 4c6603e

Browse files
committed
feat: show per-avatar message counts in avatar view
1 parent f40ed93 commit 4c6603e

File tree

3 files changed

+50
-5
lines changed

3 files changed

+50
-5
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fur-cli"
3-
version = "1.4.0"
3+
version = "1.5.0"
44
edition = "2021"
55
authors = ["Andrew Garcia"]
66
description = "Turn your AI chats into a durable, local-first diary. Save messages, attach notes, organize conversations, and stop losing context every time the model forgets you exist."

src/commands/avatar.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,38 @@
1+
use std::fs;
2+
use std::path::Path;
3+
use std::collections::HashMap;
4+
use serde_json::Value;
5+
16
use crate::frs::avatars::{load_avatars, save_avatars, get_random_emoji_for_name};
27
use crate::frs::emojis::{preview_emojis, search_emojis};
38
use serde_json::json;
49
use colored::*;
510
use crate::renderer::table::render_table;
611
use crate::commands::utils::input::{ask_string, ask_raw, ask_yes_no, default_yes};
712

13+
fn count_messages_per_avatar() -> HashMap<String, usize> {
14+
let mut counts = HashMap::new();
15+
let messages_dir = Path::new(".fur/messages");
16+
17+
if !messages_dir.exists() {
18+
return counts;
19+
}
20+
21+
if let Ok(entries) = fs::read_dir(messages_dir) {
22+
for entry in entries.flatten() {
23+
if let Ok(content) = fs::read_to_string(entry.path()) {
24+
if let Ok(json) = serde_json::from_str::<Value>(&content) {
25+
if let Some(avatar) = json["avatar"].as_str() {
26+
*counts.entry(avatar.to_string()).or_insert(0) += 1;
27+
}
28+
}
29+
}
30+
}
31+
}
32+
33+
counts
34+
}
35+
836
pub fn run_avatar_view() {
937
let avatars = load_avatars();
1038

@@ -17,19 +45,36 @@ pub fn run_avatar_view() {
1745
let mut rows = Vec::new();
1846
let mut active_idx = None;
1947

48+
let msg_counts = count_messages_per_avatar();
49+
2050
for (i, (name, val)) in map.iter().enumerate() {
2151
if name == "main" {
2252
if let Some(target) = val.as_str() {
23-
rows.push(vec!["⭐ main".to_string(), target.to_string()]);
53+
let count = msg_counts.get(target).copied().unwrap_or(0);
54+
rows.push(vec![
55+
"⭐ main".to_string(),
56+
target.to_string(),
57+
count.to_string(),
58+
]);
2459
active_idx = Some(i);
2560
}
2661
} else {
2762
let emoji = val.as_str().unwrap_or("🐾");
28-
rows.push(vec![name.to_string(), emoji.to_string()]);
63+
let count = msg_counts.get(name).copied().unwrap_or(0);
64+
rows.push(vec![
65+
name.to_string(),
66+
emoji.to_string(),
67+
count.to_string(),
68+
]);
2969
}
3070
}
3171

32-
render_table("Avatars", &["Role", "Emoji"], rows, active_idx);
72+
render_table(
73+
"Avatars",
74+
&["Role", "Emoji", "Messages"],
75+
rows,
76+
active_idx,
77+
);
3378
}
3479
}
3580

0 commit comments

Comments
 (0)