summaryrefslogtreecommitdiff
path: root/makima/src/daemon/tui/views/tasks.rs
diff options
context:
space:
mode:
authorsoryu <soryu@soryu.co>2026-01-19 13:47:32 +0000
committerGitHub <noreply@github.com>2026-01-19 13:47:32 +0000
commit0833fb1f30c0c3b920157deb882e0e902c3af02a (patch)
tree45110fb8cb9277dfbaccfeb53ed9c1f76975022b /makima/src/daemon/tui/views/tasks.rs
parent786510379bed060db2b3742b7dfca671552d2c34 (diff)
downloadsoryu-0833fb1f30c0c3b920157deb882e0e902c3af02a.tar.gz
soryu-0833fb1f30c0c3b920157deb882e0e902c3af02a.zip
Add interactive TUI browser for tasks, contracts, and files (makima view) (#7)
* feat(tui): Implement fuzzy search with real-time filtering and highlighting Adds comprehensive fuzzy search functionality to the TUI browser: ## Fuzzy Matching (fuzzy.rs) - FuzzyMatcher wrapper using SkimMatcherV2 from fuzzy-matcher crate - fuzzy_match() returns score and matched character indices - fuzzy_match_all() supports multi-term search (space-separated) - Recency-aware scoring to boost recent items in results - Unit tests for all matching scenarios ## App State (app.rs) - FilteredItem struct with index, score, and matched_indices - apply_filter() uses fuzzy matching with score-based sorting - match_count() and has_no_matches() helper methods - Results sorted by match score (highest first) ## List View (list_view.rs) - Highlighted matched characters in search results - Yellow bold styling for matched chars - Status icons with color coding ## Search Input (search_input.rs) - Real-time match count display (X/Y matches) - Visual feedback for no matches (red border) - Placeholder text when search is empty - Active search mode indication (yellow border) ## Event Handling (event.rs) - Arrow key navigation while in search mode - Ctrl+K/J for vim-style navigation during search - Delete key support alongside backspace - Ctrl+U to clear search query - Tab toggles preview while searching - Escape clears search and exits search mode Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Task completion checkpoint * [WIP] Heartbeat checkpoint - 2026-01-19 11:20:34 UTC * Task completion checkpoint * [WIP] Heartbeat checkpoint - 2026-01-19 11:31:19 UTC * Task completion checkpoint * [WIP] Heartbeat checkpoint - 2026-01-19 11:39:07 UTC * fix(tui): Fix module exports and main binary integration - Update mod.rs to properly export app, event, fuzzy, and ui modules - Add run() function for TUI entry point - Fix run_view() to use ViewCommand enum instead of ViewArgs - Fix event handling to use poll_event and handle_key_event Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Diffstat (limited to 'makima/src/daemon/tui/views/tasks.rs')
-rw-r--r--makima/src/daemon/tui/views/tasks.rs71
1 files changed, 71 insertions, 0 deletions
diff --git a/makima/src/daemon/tui/views/tasks.rs b/makima/src/daemon/tui/views/tasks.rs
new file mode 100644
index 0000000..fd52b11
--- /dev/null
+++ b/makima/src/daemon/tui/views/tasks.rs
@@ -0,0 +1,71 @@
+//! Tasks view implementation.
+
+use uuid::Uuid;
+
+use crate::daemon::api::ApiClient;
+use crate::daemon::tui::app::ListItem;
+
+/// Load tasks from API
+pub async fn load_tasks(
+ client: &ApiClient,
+ contract_id: Option<Uuid>,
+) -> Result<Vec<ListItem>, Box<dyn std::error::Error>> {
+ let Some(contract_id) = contract_id else {
+ // TODO: Implement listing all tasks across contracts
+ return Ok(Vec::new());
+ };
+
+ let result = client.supervisor_tasks(contract_id).await?;
+
+ // Parse JSON response into ListItem
+ let tasks: Vec<serde_json::Value> = serde_json::from_value(result.0)?;
+
+ let items = tasks
+ .into_iter()
+ .filter_map(|t| {
+ let id_str = t.get("id")?.as_str()?;
+ let id = Uuid::parse_str(id_str).ok()?;
+
+ Some(ListItem {
+ id,
+ name: t
+ .get("name")
+ .and_then(|v| v.as_str())
+ .unwrap_or("Unnamed")
+ .to_string(),
+ status: t.get("status").and_then(|v| v.as_str()).map(String::from),
+ description: t
+ .get("progressSummary")
+ .and_then(|v| v.as_str())
+ .map(String::from),
+ updated_at: t
+ .get("updatedAt")
+ .and_then(|v| v.as_str())
+ .unwrap_or_default()
+ .to_string(),
+ extra: t,
+ })
+ })
+ .collect();
+
+ Ok(items)
+}
+
+/// Get full task details for preview
+pub async fn get_task_preview(
+ client: &ApiClient,
+ task_id: Uuid,
+) -> Result<String, Box<dyn std::error::Error>> {
+ let result = client.supervisor_get_task(task_id).await?;
+ let task: serde_json::Value = result.0;
+
+ Ok(format!(
+ "Name: {}\nStatus: {}\nPlan: {}\n\nProgress:\n{}",
+ task.get("name").and_then(|v| v.as_str()).unwrap_or("-"),
+ task.get("status").and_then(|v| v.as_str()).unwrap_or("-"),
+ task.get("plan").and_then(|v| v.as_str()).unwrap_or("-"),
+ task.get("progressSummary")
+ .and_then(|v| v.as_str())
+ .unwrap_or("-"),
+ ))
+}