Fix service selection cursor highlighting and bounds checking
Visual Highlighting Fixes: - Apply selection highlighting to individual text spans instead of entire paragraph - Eliminates highlighting of empty space below services on single-service hosts - Selection now only highlights actual service text content Selection Logic Improvements: - Add proper bounds checking in select_next() to prevent invalid selections - Automatically clamp selection index when services are updated - Add debug logging to track selection state and movement Bounds Safety: - Ensure selection index stays valid when service lists change - Prevent out-of-bounds access during service updates - Reset selection to last valid index when services are removed This fixes the issues where: 1. Single service hosts showed empty space highlighting 2. Multi-service hosts had no visible selection cursor 3. Selection could become invalid when services changed
This commit is contained in:
parent
c851590aaa
commit
999e7b5db5
@ -202,13 +202,15 @@ impl ServicesWidget {
|
|||||||
if self.selected_index > 0 {
|
if self.selected_index > 0 {
|
||||||
self.selected_index -= 1;
|
self.selected_index -= 1;
|
||||||
}
|
}
|
||||||
|
debug!("Service selection moved up to: {}", self.selected_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move selection down
|
/// Move selection down
|
||||||
pub fn select_next(&mut self, total_services: usize) {
|
pub fn select_next(&mut self, total_services: usize) {
|
||||||
if self.selected_index < total_services.saturating_sub(1) {
|
if total_services > 0 && self.selected_index < total_services.saturating_sub(1) {
|
||||||
self.selected_index += 1;
|
self.selected_index += 1;
|
||||||
}
|
}
|
||||||
|
debug!("Service selection: {}/{}", self.selected_index, total_services);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get currently selected service name (for actions)
|
/// Get currently selected service name (for actions)
|
||||||
@ -361,10 +363,18 @@ impl Widget for ServicesWidget {
|
|||||||
|
|
||||||
self.has_data = !self.parent_services.is_empty() || !self.sub_services.is_empty();
|
self.has_data = !self.parent_services.is_empty() || !self.sub_services.is_empty();
|
||||||
|
|
||||||
|
// Ensure selection index is within bounds after update
|
||||||
|
let total_count = self.get_total_services_count();
|
||||||
|
if self.selected_index >= total_count && total_count > 0 {
|
||||||
|
self.selected_index = total_count - 1;
|
||||||
|
}
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"Services widget updated: {} parent services, {} sub-service groups, status={:?}",
|
"Services widget updated: {} parent services, {} sub-service groups, total={}, selected={}, status={:?}",
|
||||||
self.parent_services.len(),
|
self.parent_services.len(),
|
||||||
self.sub_services.len(),
|
self.sub_services.len(),
|
||||||
|
total_count,
|
||||||
|
self.selected_index,
|
||||||
self.status
|
self.status
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -473,7 +483,7 @@ impl ServicesWidget {
|
|||||||
let actual_index = effective_scroll + i; // Real index in the full list
|
let actual_index = effective_scroll + i; // Real index in the full list
|
||||||
let is_selected = actual_index == self.selected_index;
|
let is_selected = actual_index == self.selected_index;
|
||||||
|
|
||||||
let spans = if *is_sub && sub_info.is_some() {
|
let mut spans = if *is_sub && sub_info.is_some() {
|
||||||
// Use custom sub-service span creation
|
// Use custom sub-service span creation
|
||||||
let (service_info, is_last) = sub_info.as_ref().unwrap();
|
let (service_info, is_last) = sub_info.as_ref().unwrap();
|
||||||
self.create_sub_service_spans(line_text, service_info, *is_last)
|
self.create_sub_service_spans(line_text, service_info, *is_last)
|
||||||
@ -482,17 +492,17 @@ impl ServicesWidget {
|
|||||||
StatusIcons::create_status_spans(*line_status, line_text)
|
StatusIcons::create_status_spans(*line_status, line_text)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut service_para = Paragraph::new(ratatui::text::Line::from(spans));
|
// Apply selection highlighting to spans
|
||||||
|
|
||||||
// Apply selection highlighting
|
|
||||||
if is_selected {
|
if is_selected {
|
||||||
service_para = service_para.style(
|
for span in spans.iter_mut() {
|
||||||
Style::default()
|
span.style = span.style
|
||||||
.bg(Theme::highlight())
|
.bg(Theme::highlight())
|
||||||
.fg(Theme::background())
|
.fg(Theme::background());
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let service_para = Paragraph::new(ratatui::text::Line::from(spans));
|
||||||
|
|
||||||
frame.render_widget(service_para, service_chunks[i]);
|
frame.render_widget(service_para, service_chunks[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user