From ccdc470c60f267f5c10868ebeabfec31ee6c5614 Mon Sep 17 00:00:00 2001 From: AlexL Date: Wed, 14 Oct 2026 01:41:43 +0200 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src.7z | Bin 0 -> 10072 bytes src/library.rs | 48 +++++++++++++++++++++++++++++++++-- src/ui.rs | 66 ++++++++++++++++++++++++++++++++----------------- 3 files changed, 90 insertions(+), 24 deletions(-) create mode 100644 src.7z diff --git a/src.7z b/src.7z new file mode 100644 index 0000000000000000000000000000000000000000..ef9875ca4d05ecd9e83bb6cf2803ae914415d7b1 GIT binary patch literal 10072 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%0ADJ08SLyh6TVY7rnnHF$>=uP78^0)v#myTT> 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 literal 0 HcmV?d00001 diff --git a/src/library.rs b/src/library.rs index 801215b..aecebbb 100644 --- a/src/library.rs +++ b/src/library.rs @@ -1,3 +1,5 @@ +use ratatui::widgets::ListState; + use crate::track::Track; #[derive(Clone)] @@ -25,6 +27,10 @@ pub struct Library { pub sort_mode: SortMode, /// Активный фильтр поиска (пусто — без фильтра) pub filter: String, + /// Состояние скролла левой панели (сохраняется между кадрами) + pub left_state: ListState, + /// Состояние скролла правой панели + pub right_state: ListState, } impl Library { @@ -91,13 +97,25 @@ impl Library { }); } + // Вычисляем right_selected ДО перемещения artists + let right_selected = first_track_row_in(artists.first()); + + let mut left_state = ListState::default(); + let mut right_state = ListState::default(); + if !artists.is_empty() { + left_state.select(Some(0)); + } + right_state.select(Some(right_selected)); + Library { all_tracks, artists, artist_selected: 0, - right_selected: 0, + right_selected, sort_mode: mode, filter, + left_state, + right_state, } } @@ -120,13 +138,22 @@ impl Library { rows, }]; + let right_selected = first_track_row_in(artists.first()); + + let mut left_state = ListState::default(); + left_state.select(Some(0)); + let mut right_state = ListState::default(); + right_state.select(Some(right_selected)); + Library { all_tracks, artists, artist_selected: 0, - right_selected: 0, + right_selected, sort_mode: mode, filter, + left_state, + right_state, } } } @@ -163,6 +190,10 @@ impl Library { } self.artist_selected = new as usize; self.right_selected = self.first_track_row(); + + // Синхронизируем ListState — иначе ratatui не знает о смене позиции + self.left_state.select(Some(self.artist_selected)); + self.right_state.select(Some(self.right_selected)); } pub fn right_move(&mut self, delta: isize) { @@ -191,6 +222,7 @@ impl Library { } self.right_selected = track_rows[new_pos as usize]; + self.right_state.select(Some(self.right_selected)); } pub fn right_goto_start(&mut self) { @@ -215,8 +247,20 @@ impl Library { }) { self.artist_selected = ai; self.right_selected = pos; + self.left_state.select(Some(ai)); + self.right_state.select(Some(pos)); return; } } } +} + +fn first_track_row_in(artist: Option<&ArtistView>) -> usize { + artist + .and_then(|a| { + a.rows + .iter() + .position(|r| matches!(r, RightRow::Track { .. })) + }) + .unwrap_or(0) } \ No newline at end of file diff --git a/src/ui.rs b/src/ui.rs index 85f39fb..f3bb43c 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -1,6 +1,6 @@ use ratatui::prelude::*; use ratatui::widgets::{ - Bar, BarChart, BarGroup, Block, Borders, Gauge, List, ListItem, ListState, Paragraph, + Bar, BarChart, BarGroup, Block, Borders, Gauge, List, ListItem, Paragraph, }; use crate::app::{App, InputMode, Panel}; @@ -30,7 +30,7 @@ pub fn draw(f: &mut Frame, app: &mut App) { draw_status(f, app, chunks[3]); } -fn draw_left_panel(f: &mut Frame, app: &App, area: Rect) { +fn draw_left_panel(f: &mut Frame, app: &mut App, area: Rect) { let items: Vec = app .library .artists @@ -44,17 +44,20 @@ fn draw_left_panel(f: &mut Frame, app: &App, area: Rect) { Style::default().add_modifier(Modifier::DIM) }; - let mut list_state = ListState::default(); - if !app.library.artists.is_empty() { - list_state.select(Some(app.library.artist_selected)); - } + // Обновляем selected в сохранённом состоянии (не создаём новый ListState) + let sel = if app.library.artists.is_empty() { + None + } else { + Some(app.library.artist_selected) + }; + app.library.left_state.select(sel); let list = List::new(items) .block(Block::default().borders(Borders::ALL).title(" Исполнители ")) .highlight_style(highlight) .highlight_symbol("> "); - f.render_stateful_widget(list, area, &mut list_state); + f.render_stateful_widget(list, area, &mut app.library.left_state); } fn fmt_dur(d: std::time::Duration) -> String { @@ -65,7 +68,7 @@ fn fmt_dur(d: std::time::Duration) -> String { } } -fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) { +fn draw_right_panel(f: &mut Frame, app: &mut App, area: Rect) { let rows = app.library.current_right_rows(); let items: Vec = rows @@ -91,12 +94,12 @@ fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) { let pad = inner_width .saturating_sub(name.len() + total_str.len() + 3) .max(1); - let line = format!("{} {} {}", name, "─".repeat(pad), total_str); + let line = format!("{} ] {} {}", name, "─".repeat(pad), total_str); let album_color = Color::Rgb(100, 149, 237); ListItem::new(Line::from(vec![ - Span::styled("▶ ", Style::default().fg(album_color)), + Span::styled("[ ", Style::default().fg(album_color)), Span::styled( line, Style::default() @@ -137,6 +140,7 @@ fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) { }) .collect(); + // Заголовок с индикатором активного фильтра let title = match app.library.sort_mode { SortMode::ByArtist => { let artist_name = app @@ -145,9 +149,22 @@ fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) { .get(app.library.artist_selected) .map(|a| a.name.as_str()) .unwrap_or("—"); - format!(" Альбомы и треки — {} ", artist_name) + if app.library.filter.is_empty() { + format!(" Альбомы и треки — {} ", artist_name) + } else { + format!( + " Альбомы и треки — {} [{}] ", + artist_name, app.library.filter + ) + } + } + SortMode::ByFilename => { + if app.library.filter.is_empty() { + " Альбомы и треки ".into() + } else { + format!(" Альбомы и треки [{}] ", app.library.filter) + } } - SortMode::ByFilename => " Альбомы и треки ".into(), }; let highlight = if app.active_panel == Panel::Right { @@ -156,24 +173,26 @@ fn draw_right_panel(f: &mut Frame, app: &App, area: Rect) { Style::default().add_modifier(Modifier::DIM) }; - let mut list_state = ListState::default(); - if !rows.is_empty() { - list_state.select(Some(app.library.right_selected)); - } + let sel = if rows.is_empty() { + None + } else { + Some(app.library.right_selected) + }; + app.library.right_state.select(sel); let list = List::new(items) .block(Block::default().borders(Borders::ALL).title(title)) .highlight_style(highlight) .highlight_symbol("> "); - f.render_stateful_widget(list, area, &mut list_state); + f.render_stateful_widget(list, area, &mut app.library.right_state); } /// Цветной эквалайзер: 32 столбика с градиентом от синего к красному fn draw_equalizer(f: &mut Frame, app: &App, area: Rect) { let bars_data = app.player.spectrum.bars(); let num_bars = 32; - + let mut display: Vec = Vec::with_capacity(num_bars); for i in 0..num_bars { let a = bars_data[i * 2]; @@ -230,7 +249,7 @@ fn draw_progress(f: &mut Frame, app: &App, area: Rect) { let gauge = Gauge::default() .block(Block::default().borders(Borders::ALL).title(" Прогресс ")) - .gauge_style(Style::default().fg(Color::Green)) + .gauge_style(Style::default().fg(Color::Rgb(70, 130, 180))) .ratio(ratio) .label(format!( "{:02}:{:02} / {:02}:{:02}", @@ -253,10 +272,13 @@ fn draw_status(f: &mut Frame, app: &App, area: Rect) { ]) .split(area); + // Если поиск активен — показываем строку ввода. + // Иначе — статус с индикатором паузы. let (status_text, status_title) = if app.input_mode == InputMode::Search { (format!("> {}", app.search_buffer), " Поиск ") } else { - (app.status.clone(), " Статус ") + let prefix = if app.player.is_paused() { "⏸ " } else { "" }; + (format!("{}{}", prefix, app.status), " Статус ") }; let status = Paragraph::new(status_text) @@ -276,9 +298,9 @@ fn draw_status(f: &mut Frame, app: &App, area: Rect) { .block(Block::default().borders(Borders::ALL).title(" Mode ")); f.render_widget(mode, inner[1]); - let vol_text = format!("vol: {}%", (app.player.volume() * 100.0) as u32); + let vol_text = format!("Vol: {}%", (app.player.volume() * 100.0) as u32); let vol = Paragraph::new(vol_text) .alignment(Alignment::Center) - .block(Block::default().borders(Borders::ALL).title(" Звук ")); + .block(Block::default().borders(Borders::ALL).title(" ")); f.render_widget(vol, inner[2]); } \ No newline at end of file