fix(ui): session manager UI fixes (#3226)

* fix(ui): display new session folder prompt always

* fix(ui): truncate session name and error on too long a name

* fix(ui): scrolling layout list in welcome screen

* style(fmt): rustfmt
This commit is contained in:
Aram Drevekenin 2024-03-26 16:37:42 +01:00 committed by GitHub
parent 69835df5fc
commit 631ffd9bc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 76 additions and 17 deletions

View file

@ -383,6 +383,14 @@ impl State {
fn handle_selection(&mut self) { fn handle_selection(&mut self) {
match self.active_screen { match self.active_screen {
ActiveScreen::NewSession => { ActiveScreen::NewSession => {
if self.new_session_info.name().len() >= 108 {
// this is due to socket path limitations
// TODO: get this from Zellij (for reference: this is part of the interprocess
// package, we should get if from there if possible because it's configurable
// through the package)
self.show_error("Session name must be shorter than 108 bytes");
return;
}
self.new_session_info.handle_selection(&self.session_name); self.new_session_info.handle_selection(&self.session_name);
}, },
ActiveScreen::AttachToSession => { ActiveScreen::AttachToSession => {

View file

@ -126,21 +126,28 @@ impl NewSessionInfo {
pub fn update_layout_list(&mut self, layout_info: Vec<LayoutInfo>) { pub fn update_layout_list(&mut self, layout_info: Vec<LayoutInfo>) {
self.layout_list.update_layout_list(layout_info); self.layout_list.update_layout_list(layout_info);
} }
pub fn layout_list(&self) -> Vec<(LayoutInfo, bool)> { pub fn layout_list(&self, max_rows: usize) -> Vec<(LayoutInfo, bool)> {
// bool - is_selected // bool - is_selected
let range_to_render = self.range_to_render(
max_rows,
self.layout_count(),
Some(self.layout_list.selected_layout_index),
);
self.layout_list self.layout_list
.layout_list .layout_list
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, l)| (l.clone(), i == self.layout_list.selected_layout_index)) .map(|(i, l)| (l.clone(), i == self.layout_list.selected_layout_index))
.take(range_to_render.1)
.skip(range_to_render.0)
.collect() .collect()
} }
pub fn layouts_to_render(&self) -> Vec<(LayoutInfo, Vec<usize>, bool)> { pub fn layouts_to_render(&self, max_rows: usize) -> Vec<(LayoutInfo, Vec<usize>, bool)> {
// (layout_info, // (layout_info,
// search_indices, // search_indices,
// is_selected) // is_selected)
if self.is_searching() { if self.is_searching() {
self.layout_search_results() self.layout_search_results(max_rows)
.into_iter() .into_iter()
.map(|(layout_search_result, is_selected)| { .map(|(layout_search_result, is_selected)| {
( (
@ -151,21 +158,48 @@ impl NewSessionInfo {
}) })
.collect() .collect()
} else { } else {
self.layout_list() self.layout_list(max_rows)
.into_iter() .into_iter()
.map(|(layout_info, is_selected)| (layout_info, vec![], is_selected)) .map(|(layout_info, is_selected)| (layout_info, vec![], is_selected))
.collect() .collect()
} }
} }
pub fn layout_search_results(&self) -> Vec<(LayoutSearchResult, bool)> { pub fn layout_search_results(&self, max_rows: usize) -> Vec<(LayoutSearchResult, bool)> {
// bool - is_selected // bool - is_selected
let range_to_render = self.range_to_render(
max_rows,
self.layout_list.layout_search_results.len(),
Some(self.layout_list.selected_layout_index),
);
self.layout_list self.layout_list
.layout_search_results .layout_search_results
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, l)| (l.clone(), i == self.layout_list.selected_layout_index)) .map(|(i, l)| (l.clone(), i == self.layout_list.selected_layout_index))
.take(range_to_render.1)
.skip(range_to_render.0)
.collect() .collect()
} }
// TODO: merge with similar function in resurrectable_sessions
fn range_to_render(
&self,
table_rows: usize,
results_len: usize,
selected_index: Option<usize>,
) -> (usize, usize) {
if table_rows <= results_len {
let row_count_to_render = table_rows.saturating_sub(1); // 1 for the title
let first_row_index_to_render = selected_index
.unwrap_or(0)
.saturating_sub(row_count_to_render / 2);
let last_row_index_to_render = first_row_index_to_render + row_count_to_render;
(first_row_index_to_render, last_row_index_to_render)
} else {
let first_row_index_to_render = 0;
let last_row_index_to_render = results_len;
(first_row_index_to_render, last_row_index_to_render)
}
}
pub fn is_searching(&self) -> bool { pub fn is_searching(&self) -> bool {
!self.layout_list.layout_search_term.is_empty() !self.layout_list.layout_search_term.is_empty()
} }

View file

@ -709,6 +709,23 @@ pub fn render_new_session_block(
long_instruction, long_instruction,
); );
} else { } else {
let space_for_new_session_name =
max_cols_of_new_session_block.saturating_sub(prompt.width() + 18);
let new_session_name = if new_session_name.width() > space_for_new_session_name {
let mut truncated = String::new();
for character in new_session_name.chars().rev() {
if truncated.width() + character.width().unwrap_or(0)
< space_for_new_session_name
{
truncated.push(character);
} else {
break;
}
}
format!("...{}", truncated.chars().rev().collect::<String>())
} else {
new_session_name.to_owned()
};
println!( println!(
"\u{1b}[m{}{} {}_ {}", "\u{1b}[m{}{} {}_ {}",
format!("\u{1b}[{};{}H", y + 1, x + 1), format!("\u{1b}[{};{}H", y + 1, x + 1),
@ -747,18 +764,23 @@ pub fn render_new_session_block(
} }
render_layout_selection_list( render_layout_selection_list(
new_session_info, new_session_info,
colors, max_rows_of_new_session_block.saturating_sub(8),
max_rows_of_new_session_block.saturating_sub(1),
max_cols_of_new_session_block, max_cols_of_new_session_block,
x, x,
y + 1, y + 1,
); );
} }
render_new_session_folder_prompt(
new_session_info,
colors,
x,
(y + max_rows_of_new_session_block).saturating_sub(3),
max_cols_of_new_session_block,
);
} }
pub fn render_layout_selection_list( pub fn render_layout_selection_list(
new_session_info: &NewSessionInfo, new_session_info: &NewSessionInfo,
colors: Colors,
max_rows_of_new_session_block: usize, max_rows_of_new_session_block: usize,
max_cols_of_new_session_block: usize, max_cols_of_new_session_block: usize,
x: usize, x: usize,
@ -786,8 +808,10 @@ pub fn render_layout_selection_list(
print_text_with_coordinates(layout_indication_line, x, y + 1, None, None); print_text_with_coordinates(layout_indication_line, x, y + 1, None, None);
println!(); println!();
let mut table = Table::new(); let mut table = Table::new();
for (i, (layout_info, indices, is_selected)) in for (i, (layout_info, indices, is_selected)) in new_session_info
new_session_info.layouts_to_render().into_iter().enumerate() .layouts_to_render(max_rows_of_new_session_block)
.into_iter()
.enumerate()
{ {
let layout_name = layout_info.name(); let layout_name = layout_info.name();
let layout_name_len = layout_name.width(); let layout_name_len = layout_name.width();
@ -818,13 +842,6 @@ pub fn render_layout_selection_list(
} }
let table_y = y + 3; let table_y = y + 3;
print_table_with_coordinates(table, x, table_y, None, None); print_table_with_coordinates(table, x, table_y, None, None);
render_new_session_folder_prompt(
new_session_info,
colors,
x,
(y + max_rows_of_new_session_block).saturating_sub(3),
max_cols_of_new_session_block,
);
} }
pub fn render_error(error_text: &str, rows: usize, columns: usize, x: usize, y: usize) { pub fn render_error(error_text: &str, rows: usize, columns: usize, x: usize, y: usize) {