feat(ui): add file icon resolver with Nerd/ASCII sets, env override, and breadcrumb display
- Introduce `IconMode` in core config (default Auto) and bump schema version to 1.4.0. - Add `FileIconSet`, `IconDetection`, and `FileIconResolver` to resolve per‑file icons with configurable fallbacks and environment variable `OWLEN_TUI_ICONS`. - Export resolver types from `owlen-tui::state::file_icons`. - Extend `ChatApp` with `file_icons` field, initialize it from config, and expose via `file_icons()` accessor. - Append system status line showing selected icon set and detection source. - Implement breadcrumb construction (`repo > path > file`) and display in code pane headers. - Render icons in file tree, handle unsaved file markers, hidden files, and Git decorations with proper styling. - Add helper `collect_unsaved_relative_paths` and tree line computation for visual guides. - Provide `Workspace::panes()` iterator for unsaved tracking. - Update UI imports and tests to cover new breadcrumb feature.
This commit is contained in:
@@ -28,10 +28,10 @@ use crate::config;
|
||||
use crate::events::Event;
|
||||
use crate::model_info_panel::ModelInfoPanel;
|
||||
use crate::state::{
|
||||
CodeWorkspace, CommandPalette, FileFilterMode, FileNode, FileTreeState, ModelPaletteEntry,
|
||||
PaletteSuggestion, PaneDirection, PaneRestoreRequest, RepoSearchMessage, RepoSearchState,
|
||||
SplitAxis, SymbolSearchMessage, SymbolSearchState, WorkspaceSnapshot, spawn_repo_search_task,
|
||||
spawn_symbol_search_task,
|
||||
CodeWorkspace, CommandPalette, FileFilterMode, FileIconResolver, FileNode, FileTreeState,
|
||||
ModelPaletteEntry, PaletteSuggestion, PaneDirection, PaneRestoreRequest, RepoSearchMessage,
|
||||
RepoSearchState, SplitAxis, SymbolSearchMessage, SymbolSearchState, WorkspaceSnapshot,
|
||||
spawn_repo_search_task, spawn_symbol_search_task,
|
||||
};
|
||||
use crate::ui::format_tool_output;
|
||||
// Agent executor moved to separate binary `owlen-agent`. The TUI no longer directly
|
||||
@@ -224,6 +224,7 @@ pub struct ChatApp {
|
||||
resize_snap_index: usize, // Cycles through 25/50/75 snaps
|
||||
last_snap_direction: Option<PaneDirection>,
|
||||
file_tree: FileTreeState, // Workspace file tree state
|
||||
file_icons: FileIconResolver, // Icon resolver with Nerd/ASCII fallback
|
||||
file_panel_collapsed: bool, // Whether the file panel is collapsed
|
||||
file_panel_width: u16, // Cached file panel width
|
||||
saved_sessions: Vec<SessionMeta>, // Cached list of saved sessions
|
||||
@@ -384,6 +385,7 @@ impl ChatApp {
|
||||
let show_cursor_outside_insert = config_guard.ui.show_cursor_outside_insert;
|
||||
let syntax_highlighting = config_guard.ui.syntax_highlighting;
|
||||
let show_timestamps = config_guard.ui.show_timestamps;
|
||||
let icon_mode = config_guard.ui.icon_mode;
|
||||
drop(config_guard);
|
||||
let theme = owlen_core::theme::get_theme(&theme_name).unwrap_or_else(|| {
|
||||
eprintln!("Warning: Theme '{}' not found, using default", theme_name);
|
||||
@@ -392,6 +394,7 @@ impl ChatApp {
|
||||
|
||||
let workspace_root = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
||||
let file_tree = FileTreeState::new(workspace_root);
|
||||
let file_icons = FileIconResolver::from_mode(icon_mode);
|
||||
|
||||
let mut app = Self {
|
||||
controller,
|
||||
@@ -454,6 +457,7 @@ impl ChatApp {
|
||||
resize_snap_index: 0,
|
||||
last_snap_direction: None,
|
||||
file_tree,
|
||||
file_icons,
|
||||
file_panel_collapsed: true,
|
||||
file_panel_width: 32,
|
||||
saved_sessions: Vec::new(),
|
||||
@@ -479,6 +483,12 @@ impl ChatApp {
|
||||
show_message_timestamps: show_timestamps,
|
||||
};
|
||||
|
||||
app.append_system_status(&format!(
|
||||
"Icons: {} ({})",
|
||||
app.file_icons.status_label(),
|
||||
app.file_icons.detection_label()
|
||||
));
|
||||
|
||||
app.update_command_palette_catalog();
|
||||
|
||||
if let Err(err) = app.restore_workspace_layout().await {
|
||||
@@ -973,6 +983,10 @@ impl ChatApp {
|
||||
&mut self.file_tree
|
||||
}
|
||||
|
||||
pub fn file_icons(&self) -> &FileIconResolver {
|
||||
&self.file_icons
|
||||
}
|
||||
|
||||
pub fn workspace(&self) -> &CodeWorkspace {
|
||||
&self.code_workspace
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user