tweak hotkeys, add info panel, optimize fonts and hotkeys for about and info panel.
This commit is contained in:
parent
ffe451edaa
commit
6f238cdf25
@ -29,7 +29,8 @@ use crate::ui::cpu::{
|
|||||||
};
|
};
|
||||||
use crate::ui::modal::{ModalAction, ModalManager, ModalType};
|
use crate::ui::modal::{ModalAction, ModalManager, ModalType};
|
||||||
use crate::ui::processes::{
|
use crate::ui::processes::{
|
||||||
ProcSortBy, processes_handle_key_with_selection, processes_handle_mouse_with_selection,
|
ProcSortBy, ProcessKeyParams, processes_handle_key_with_selection,
|
||||||
|
processes_handle_mouse_with_selection,
|
||||||
};
|
};
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
disks::draw_disks, gpu::draw_gpu, header::draw_header, mem::draw_mem, net::draw_net_spark,
|
disks::draw_disks, gpu::draw_gpu, header::draw_header, mem::draw_mem, net::draw_net_spark,
|
||||||
@ -661,6 +662,11 @@ impl App {
|
|||||||
self.modal_manager.push_modal(ModalType::About);
|
self.modal_manager.push_modal(ModalType::About);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Show Help modal on 'h' or 'H'
|
||||||
|
if matches!(k.code, KeyCode::Char('h') | KeyCode::Char('H')) {
|
||||||
|
self.modal_manager.push_modal(ModalType::Help);
|
||||||
|
}
|
||||||
|
|
||||||
// Per-core scroll via keys (Up/Down/PageUp/PageDown/Home/End)
|
// Per-core scroll via keys (Up/Down/PageUp/PageDown/Home/End)
|
||||||
let sz = terminal.size()?;
|
let sz = terminal.size()?;
|
||||||
let area = Rect::new(0, 0, sz.width, sz.height);
|
let area = Rect::new(0, 0, sz.width, sz.height);
|
||||||
@ -681,22 +687,14 @@ impl App {
|
|||||||
let content = per_core_content_area(top[1]);
|
let content = per_core_content_area(top[1]);
|
||||||
|
|
||||||
// First try process selection (only handles arrows if a process is selected)
|
// First try process selection (only handles arrows if a process is selected)
|
||||||
let process_handled = if let Some(p_area) = self.last_procs_area {
|
let process_handled = if self.last_procs_area.is_some() {
|
||||||
let page = p_area.height.saturating_sub(3).max(1) as usize; // borders (2) + header (1)
|
processes_handle_key_with_selection(ProcessKeyParams {
|
||||||
let total_rows = self
|
selected_process_pid: &mut self.selected_process_pid,
|
||||||
.last_metrics
|
selected_process_index: &mut self.selected_process_index,
|
||||||
.as_ref()
|
key: k,
|
||||||
.map(|m| m.top_processes.len())
|
metrics: self.last_metrics.as_ref(),
|
||||||
.unwrap_or(0);
|
sort_by: self.procs_sort_by,
|
||||||
processes_handle_key_with_selection(
|
})
|
||||||
&mut self.procs_scroll_offset,
|
|
||||||
&mut self.selected_process_pid,
|
|
||||||
&mut self.selected_process_index,
|
|
||||||
k,
|
|
||||||
page,
|
|
||||||
total_rows,
|
|
||||||
self.last_metrics.as_ref(),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
@ -710,6 +708,48 @@ impl App {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Auto-scroll to keep selected process visible
|
||||||
|
if let (Some(selected_idx), Some(p_area)) =
|
||||||
|
(self.selected_process_index, self.last_procs_area)
|
||||||
|
{
|
||||||
|
// Calculate viewport size (excluding borders and header)
|
||||||
|
let viewport_rows = p_area.height.saturating_sub(3) as usize; // borders (2) + header (1)
|
||||||
|
|
||||||
|
// Build sorted index list to find display position
|
||||||
|
if let Some(m) = self.last_metrics.as_ref() {
|
||||||
|
let mut idxs: Vec<usize> = (0..m.top_processes.len()).collect();
|
||||||
|
match self.procs_sort_by {
|
||||||
|
ProcSortBy::CpuDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].cpu_usage;
|
||||||
|
let bb = m.top_processes[b].cpu_usage;
|
||||||
|
bb.partial_cmp(&aa).unwrap_or(std::cmp::Ordering::Equal)
|
||||||
|
}),
|
||||||
|
ProcSortBy::MemDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].mem_bytes;
|
||||||
|
let bb = m.top_processes[b].mem_bytes;
|
||||||
|
bb.cmp(&aa)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the display position of the selected process
|
||||||
|
if let Some(display_pos) =
|
||||||
|
idxs.iter().position(|&idx| idx == selected_idx)
|
||||||
|
{
|
||||||
|
// Adjust scroll offset to keep selection visible
|
||||||
|
if display_pos < self.procs_scroll_offset {
|
||||||
|
// Selection is above viewport, scroll up
|
||||||
|
self.procs_scroll_offset = display_pos;
|
||||||
|
} else if display_pos
|
||||||
|
>= self.procs_scroll_offset + viewport_rows
|
||||||
|
{
|
||||||
|
// Selection is below viewport, scroll down
|
||||||
|
self.procs_scroll_offset =
|
||||||
|
display_pos.saturating_sub(viewport_rows - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if process selection changed and clear details if so
|
// Check if process selection changed and clear details if so
|
||||||
if self.selected_process_pid != self.prev_selected_process_pid {
|
if self.selected_process_pid != self.prev_selected_process_pid {
|
||||||
self.clear_process_details();
|
self.clear_process_details();
|
||||||
|
|||||||
@ -42,8 +42,8 @@ pub fn per_core_content_area(area: Rect) -> Rect {
|
|||||||
/// Handles key events for per-core CPU bars.
|
/// Handles key events for per-core CPU bars.
|
||||||
pub fn per_core_handle_key(scroll_offset: &mut usize, key: KeyEvent, page_size: usize) {
|
pub fn per_core_handle_key(scroll_offset: &mut usize, key: KeyEvent, page_size: usize) {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Up => *scroll_offset = scroll_offset.saturating_sub(1),
|
KeyCode::Left => *scroll_offset = scroll_offset.saturating_sub(1),
|
||||||
KeyCode::Down => *scroll_offset = scroll_offset.saturating_add(1),
|
KeyCode::Right => *scroll_offset = scroll_offset.saturating_add(1),
|
||||||
KeyCode::PageUp => {
|
KeyCode::PageUp => {
|
||||||
let step = page_size.max(1);
|
let step = page_size.max(1);
|
||||||
*scroll_offset = scroll_offset.saturating_sub(step);
|
*scroll_offset = scroll_offset.saturating_sub(step);
|
||||||
|
|||||||
@ -46,7 +46,7 @@ pub fn draw_header(
|
|||||||
parts.push(tok_txt.into());
|
parts.push(tok_txt.into());
|
||||||
}
|
}
|
||||||
parts.push(intervals);
|
parts.push(intervals);
|
||||||
parts.push("(a: about, q: quit)".into());
|
parts.push("(a: about, h: help, q: quit)".into());
|
||||||
let title = parts.join(" | ");
|
let title = parts.join(" | ");
|
||||||
f.render_widget(Block::default().title(title).borders(Borders::BOTTOM), area);
|
f.render_widget(Block::default().title(title).borders(Borders::BOTTOM), area);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,7 @@ impl ModalManager {
|
|||||||
ModalButton::Ok
|
ModalButton::Ok
|
||||||
}
|
}
|
||||||
Some(ModalType::About) => ModalButton::Ok,
|
Some(ModalType::About) => ModalButton::Ok,
|
||||||
|
Some(ModalType::Help) => ModalButton::Ok,
|
||||||
Some(ModalType::Confirmation { .. }) => ModalButton::Confirm,
|
Some(ModalType::Confirmation { .. }) => ModalButton::Confirm,
|
||||||
Some(ModalType::Info { .. }) => ModalButton::Ok,
|
Some(ModalType::Info { .. }) => ModalButton::Ok,
|
||||||
None => ModalButton::Ok,
|
None => ModalButton::Ok,
|
||||||
@ -68,6 +69,7 @@ impl ModalManager {
|
|||||||
ModalType::ConnectionError { .. } => ModalButton::Retry,
|
ModalType::ConnectionError { .. } => ModalButton::Retry,
|
||||||
ModalType::ProcessDetails { .. } => ModalButton::Ok,
|
ModalType::ProcessDetails { .. } => ModalButton::Ok,
|
||||||
ModalType::About => ModalButton::Ok,
|
ModalType::About => ModalButton::Ok,
|
||||||
|
ModalType::Help => ModalButton::Ok,
|
||||||
ModalType::Confirmation { .. } => ModalButton::Confirm,
|
ModalType::Confirmation { .. } => ModalButton::Confirm,
|
||||||
ModalType::Info { .. } => ModalButton::Ok,
|
ModalType::Info { .. } => ModalButton::Ok,
|
||||||
};
|
};
|
||||||
@ -211,6 +213,10 @@ impl ModalManager {
|
|||||||
self.pop_modal();
|
self.pop_modal();
|
||||||
ModalAction::Dismiss
|
ModalAction::Dismiss
|
||||||
}
|
}
|
||||||
|
(Some(ModalType::Help), ModalButton::Ok) => {
|
||||||
|
self.pop_modal();
|
||||||
|
ModalAction::Dismiss
|
||||||
|
}
|
||||||
(Some(ModalType::Confirmation { .. }), ModalButton::Confirm) => ModalAction::Confirm,
|
(Some(ModalType::Confirmation { .. }), ModalButton::Confirm) => ModalAction::Confirm,
|
||||||
(Some(ModalType::Confirmation { .. }), ModalButton::Cancel) => ModalAction::Cancel,
|
(Some(ModalType::Confirmation { .. }), ModalButton::Cancel) => ModalAction::Cancel,
|
||||||
(Some(ModalType::Info { .. }), ModalButton::Ok) => {
|
(Some(ModalType::Info { .. }), ModalButton::Ok) => {
|
||||||
@ -261,7 +267,11 @@ impl ModalManager {
|
|||||||
}
|
}
|
||||||
ModalType::About => {
|
ModalType::About => {
|
||||||
// About modal uses medium size
|
// About modal uses medium size
|
||||||
self.centered_rect(60, 60, area)
|
self.centered_rect(90, 90, area)
|
||||||
|
}
|
||||||
|
ModalType::Help => {
|
||||||
|
// Help modal uses medium size
|
||||||
|
self.centered_rect(80, 80, area)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Other modals use smaller size
|
// Other modals use smaller size
|
||||||
@ -287,6 +297,7 @@ impl ModalManager {
|
|||||||
self.render_process_details(f, modal_area, *pid, data)
|
self.render_process_details(f, modal_area, *pid, data)
|
||||||
}
|
}
|
||||||
ModalType::About => self.render_about(f, modal_area),
|
ModalType::About => self.render_about(f, modal_area),
|
||||||
|
ModalType::Help => self.render_help(f, modal_area),
|
||||||
ModalType::Confirmation {
|
ModalType::Confirmation {
|
||||||
title,
|
title,
|
||||||
message,
|
message,
|
||||||
@ -415,7 +426,7 @@ impl ModalManager {
|
|||||||
let block = Block::default()
|
let block = Block::default()
|
||||||
.title(" About socktop ")
|
.title(" About socktop ")
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.style(Style::default().bg(Color::Black).fg(Color::Green));
|
.style(Style::default().bg(Color::Black).fg(Color::DarkGray));
|
||||||
f.render_widget(block, area);
|
f.render_widget(block, area);
|
||||||
|
|
||||||
// Calculate inner area manually to avoid any parent styling
|
// Calculate inner area manually to avoid any parent styling
|
||||||
@ -423,7 +434,7 @@ impl ModalManager {
|
|||||||
x: area.x + 1,
|
x: area.x + 1,
|
||||||
y: area.y + 1,
|
y: area.y + 1,
|
||||||
width: area.width.saturating_sub(2),
|
width: area.width.saturating_sub(2),
|
||||||
height: area.height.saturating_sub(3), // Leave room for button at bottom
|
height: area.height.saturating_sub(2), // Leave room for button at bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
// Render content area with explicit black background
|
// Render content area with explicit black background
|
||||||
@ -438,7 +449,80 @@ impl ModalManager {
|
|||||||
// Button area
|
// Button area
|
||||||
let button_area = Rect {
|
let button_area = Rect {
|
||||||
x: area.x + 1,
|
x: area.x + 1,
|
||||||
y: area.y + area.height.saturating_sub(3),
|
y: area.y + area.height.saturating_sub(2),
|
||||||
|
width: area.width.saturating_sub(2),
|
||||||
|
height: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ok_style = if self.active_button == ModalButton::Ok {
|
||||||
|
Style::default()
|
||||||
|
.bg(Color::Blue)
|
||||||
|
.fg(Color::White)
|
||||||
|
.add_modifier(Modifier::BOLD)
|
||||||
|
} else {
|
||||||
|
Style::default().fg(Color::Blue).bg(Color::Black)
|
||||||
|
};
|
||||||
|
|
||||||
|
f.render_widget(
|
||||||
|
Paragraph::new("[ Enter ] Close")
|
||||||
|
.style(ok_style)
|
||||||
|
.alignment(Alignment::Center),
|
||||||
|
button_area,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_help(&self, f: &mut Frame, area: Rect) {
|
||||||
|
let help_text = "\
|
||||||
|
GLOBAL
|
||||||
|
q/Q/Esc ........ Quit │ a/A ....... About │ h/H ....... Help
|
||||||
|
|
||||||
|
PROCESS LIST
|
||||||
|
↑/↓ ............ Select/navigate processes
|
||||||
|
Enter .......... Open Process Details
|
||||||
|
x/X ............ Clear selection
|
||||||
|
Click header ... Sort by column (CPU/Mem)
|
||||||
|
Click row ...... Select process
|
||||||
|
|
||||||
|
CPU PER-CORE
|
||||||
|
←/→ ............ Scroll cores │ PgUp/PgDn ... Page up/down
|
||||||
|
Home/End ....... Jump to first/last core
|
||||||
|
|
||||||
|
PROCESS DETAILS MODAL
|
||||||
|
x/X ............ Close modal (all parent modals)
|
||||||
|
p/P ............ Navigate to parent process
|
||||||
|
j/k ............ Scroll threads ↓/↑ (1 line)
|
||||||
|
d/u ............ Scroll threads ↓/↑ (10 lines)
|
||||||
|
[ / ] .......... Scroll journal ↑/↓
|
||||||
|
Esc/Enter ...... Close modal";
|
||||||
|
|
||||||
|
// Render the border block
|
||||||
|
let block = Block::default()
|
||||||
|
.title(" Hotkey Help ")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.style(Style::default().bg(Color::Black).fg(Color::DarkGray));
|
||||||
|
f.render_widget(block, area);
|
||||||
|
|
||||||
|
// Calculate inner area manually to avoid any parent styling
|
||||||
|
let inner_area = Rect {
|
||||||
|
x: area.x + 1,
|
||||||
|
y: area.y + 1,
|
||||||
|
width: area.width.saturating_sub(2),
|
||||||
|
height: area.height.saturating_sub(2), // Leave room for button at bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render content area with explicit black background
|
||||||
|
f.render_widget(
|
||||||
|
Paragraph::new(help_text)
|
||||||
|
.style(Style::default().fg(Color::Cyan).bg(Color::Black))
|
||||||
|
.alignment(Alignment::Left)
|
||||||
|
.wrap(Wrap { trim: false }),
|
||||||
|
inner_area,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Button area
|
||||||
|
let button_area = Rect {
|
||||||
|
x: area.x + 1,
|
||||||
|
y: area.y + area.height.saturating_sub(2),
|
||||||
width: area.width.saturating_sub(2),
|
width: area.width.saturating_sub(2),
|
||||||
height: 1,
|
height: 1,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -39,6 +39,7 @@ pub enum ModalType {
|
|||||||
pid: u32,
|
pid: u32,
|
||||||
},
|
},
|
||||||
About,
|
About,
|
||||||
|
Help,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
Confirmation {
|
Confirmation {
|
||||||
title: String,
|
title: String,
|
||||||
|
|||||||
@ -254,6 +254,15 @@ fn fmt_cpu_pct(v: f32) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Handle keyboard scrolling (Up/Down/PageUp/PageDown/Home/End)
|
/// Handle keyboard scrolling (Up/Down/PageUp/PageDown/Home/End)
|
||||||
|
/// Parameters for process key event handling
|
||||||
|
pub struct ProcessKeyParams<'a> {
|
||||||
|
pub selected_process_pid: &'a mut Option<u32>,
|
||||||
|
pub selected_process_index: &'a mut Option<usize>,
|
||||||
|
pub key: crossterm::event::KeyEvent,
|
||||||
|
pub metrics: Option<&'a Metrics>,
|
||||||
|
pub sort_by: ProcSortBy,
|
||||||
|
}
|
||||||
|
|
||||||
/// LEGACY: Use processes_handle_key_with_selection for enhanced functionality
|
/// LEGACY: Use processes_handle_key_with_selection for enhanced functionality
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn processes_handle_key(
|
pub fn processes_handle_key(
|
||||||
@ -264,24 +273,93 @@ pub fn processes_handle_key(
|
|||||||
crate::ui::cpu::per_core_handle_key(scroll_offset, key, page_size);
|
crate::ui::cpu::per_core_handle_key(scroll_offset, key, page_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enhanced keyboard handler that also manages process selection
|
pub fn processes_handle_key_with_selection(params: ProcessKeyParams) -> bool {
|
||||||
pub fn processes_handle_key_with_selection(
|
|
||||||
_scroll_offset: &mut usize,
|
|
||||||
selected_process_pid: &mut Option<u32>,
|
|
||||||
selected_process_index: &mut Option<usize>,
|
|
||||||
key: crossterm::event::KeyEvent,
|
|
||||||
_page_size: usize,
|
|
||||||
_total_rows: usize,
|
|
||||||
_metrics: Option<&Metrics>,
|
|
||||||
) -> bool {
|
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
|
|
||||||
match key.code {
|
match params.key.code {
|
||||||
|
KeyCode::Up => {
|
||||||
|
// Build sorted index list to navigate through display order
|
||||||
|
if let Some(m) = params.metrics {
|
||||||
|
let mut idxs: Vec<usize> = (0..m.top_processes.len()).collect();
|
||||||
|
match params.sort_by {
|
||||||
|
ProcSortBy::CpuDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].cpu_usage;
|
||||||
|
let bb = m.top_processes[b].cpu_usage;
|
||||||
|
bb.partial_cmp(&aa).unwrap_or(Ordering::Equal)
|
||||||
|
}),
|
||||||
|
ProcSortBy::MemDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].mem_bytes;
|
||||||
|
let bb = m.top_processes[b].mem_bytes;
|
||||||
|
bb.cmp(&aa)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.selected_process_index.is_none() || params.selected_process_pid.is_none()
|
||||||
|
{
|
||||||
|
// No selection - select the first process in sorted order
|
||||||
|
if !idxs.is_empty() {
|
||||||
|
let first_idx = idxs[0];
|
||||||
|
*params.selected_process_index = Some(first_idx);
|
||||||
|
*params.selected_process_pid = Some(m.top_processes[first_idx].pid);
|
||||||
|
}
|
||||||
|
} else if let Some(current_idx) = *params.selected_process_index {
|
||||||
|
// Find current position in sorted list
|
||||||
|
if let Some(pos) = idxs.iter().position(|&idx| idx == current_idx)
|
||||||
|
&& pos > 0
|
||||||
|
{
|
||||||
|
// Move up in sorted list
|
||||||
|
let new_idx = idxs[pos - 1];
|
||||||
|
*params.selected_process_index = Some(new_idx);
|
||||||
|
*params.selected_process_pid = Some(m.top_processes[new_idx].pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true // Handled
|
||||||
|
}
|
||||||
|
KeyCode::Down => {
|
||||||
|
// Build sorted index list to navigate through display order
|
||||||
|
if let Some(m) = params.metrics {
|
||||||
|
let mut idxs: Vec<usize> = (0..m.top_processes.len()).collect();
|
||||||
|
match params.sort_by {
|
||||||
|
ProcSortBy::CpuDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].cpu_usage;
|
||||||
|
let bb = m.top_processes[b].cpu_usage;
|
||||||
|
bb.partial_cmp(&aa).unwrap_or(Ordering::Equal)
|
||||||
|
}),
|
||||||
|
ProcSortBy::MemDesc => idxs.sort_by(|&a, &b| {
|
||||||
|
let aa = m.top_processes[a].mem_bytes;
|
||||||
|
let bb = m.top_processes[b].mem_bytes;
|
||||||
|
bb.cmp(&aa)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.selected_process_index.is_none() || params.selected_process_pid.is_none()
|
||||||
|
{
|
||||||
|
// No selection - select the first process in sorted order
|
||||||
|
if !idxs.is_empty() {
|
||||||
|
let first_idx = idxs[0];
|
||||||
|
*params.selected_process_index = Some(first_idx);
|
||||||
|
*params.selected_process_pid = Some(m.top_processes[first_idx].pid);
|
||||||
|
}
|
||||||
|
} else if let Some(current_idx) = *params.selected_process_index {
|
||||||
|
// Find current position in sorted list
|
||||||
|
if let Some(pos) = idxs.iter().position(|&idx| idx == current_idx)
|
||||||
|
&& pos + 1 < idxs.len()
|
||||||
|
{
|
||||||
|
// Move down in sorted list
|
||||||
|
let new_idx = idxs[pos + 1];
|
||||||
|
*params.selected_process_index = Some(new_idx);
|
||||||
|
*params.selected_process_pid = Some(m.top_processes[new_idx].pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true // Handled
|
||||||
|
}
|
||||||
KeyCode::Char('x') | KeyCode::Char('X') => {
|
KeyCode::Char('x') | KeyCode::Char('X') => {
|
||||||
// Unselect any selected process
|
// Unselect any selected process
|
||||||
if selected_process_pid.is_some() || selected_process_index.is_some() {
|
if params.selected_process_pid.is_some() || params.selected_process_index.is_some() {
|
||||||
*selected_process_pid = None;
|
*params.selected_process_pid = None;
|
||||||
*selected_process_index = None;
|
*params.selected_process_index = None;
|
||||||
true // Handled
|
true // Handled
|
||||||
} else {
|
} else {
|
||||||
false // No selection to clear
|
false // No selection to clear
|
||||||
@ -289,7 +367,7 @@ pub fn processes_handle_key_with_selection(
|
|||||||
}
|
}
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
// Signal that Enter was pressed with a selection
|
// Signal that Enter was pressed with a selection
|
||||||
selected_process_pid.is_some() // Return true if we have a selection to handle
|
params.selected_process_pid.is_some() // Return true if we have a selection to handle
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// No other keys handled - let scrollbar handle all navigation
|
// No other keys handled - let scrollbar handle all navigation
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user