Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions src/core/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ pub enum ActiveBlock {
TrackTable,
Discover,
Artists,
BasicView,
LyricsView,
CoverArtView,
Dialog(DialogContext),

AnnouncementPrompt,
Expand All @@ -248,7 +249,8 @@ pub enum RouteId {
AlbumTracks,
AlbumList,
Artist,
BasicView,
LyricsView,
CoverArtView,
Error,
Home,
RecentlyPlayed,
Expand Down Expand Up @@ -3081,10 +3083,17 @@ impl App {
value: SettingValue::Key(key_to_string(&self.user_config.keys.audio_analysis)),
},
SettingItem {
id: "keys.basic_view".to_string(),
name: "Basic View".to_string(),
description: "Open lyrics/basic view".to_string(),
value: SettingValue::Key(key_to_string(&self.user_config.keys.basic_view)),
id: "keys.lyrics_view".to_string(),
name: "Lyrics View".to_string(),
description: "Open lyrics view".to_string(),
value: SettingValue::Key(key_to_string(&self.user_config.keys.lyrics_view)),
},
#[cfg(feature = "cover-art")]
SettingItem {
id: "keys.cover_art_view".to_string(),
name: "Cover Art View".to_string(),
description: "Open full-screen cover art view".to_string(),
value: SettingValue::Key(key_to_string(&self.user_config.keys.cover_art_view)),
},
],
SettingsCategory::Theme => {
Expand Down Expand Up @@ -3490,10 +3499,18 @@ impl App {
}
}
}
"keys.basic_view" => {
"keys.lyrics_view" => {
if let SettingValue::Key(v) = &setting.value {
if let Ok(key) = crate::core::user_config::parse_key_public(v.clone()) {
self.user_config.keys.lyrics_view = key;
}
}
}
#[cfg(feature = "cover-art")]
"keys.cover_art_view" => {
if let SettingValue::Key(v) = &setting.value {
if let Ok(key) = crate::core::user_config::parse_key_public(v.clone()) {
self.user_config.keys.basic_view = key;
self.user_config.keys.cover_art_view = key;
}
}
}
Expand Down
16 changes: 11 additions & 5 deletions src/core/user_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,9 @@ pub struct KeyBindingsString {
copy_song_url: Option<String>,
copy_album_url: Option<String>,
audio_analysis: Option<String>,
basic_view: Option<String>,
#[serde(alias = "basic_view")]
lyrics_view: Option<String>,
cover_art_view: Option<String>,
add_item_to_queue: Option<String>,
show_queue: Option<String>,
open_settings: Option<String>,
Expand Down Expand Up @@ -617,7 +619,8 @@ pub struct KeyBindings {
pub copy_song_url: Key,
pub copy_album_url: Key,
pub audio_analysis: Key,
pub basic_view: Key,
pub lyrics_view: Key,
pub cover_art_view: Key,
pub add_item_to_queue: Key,
pub show_queue: Key,
pub open_settings: Key,
Expand Down Expand Up @@ -760,7 +763,8 @@ impl UserConfig {
copy_song_url: Key::Char('c'),
copy_album_url: Key::Char('C'),
audio_analysis: Key::Char('v'),
basic_view: Key::Char('B'),
lyrics_view: Key::Char('B'),
cover_art_view: Key::Char('G'),
add_item_to_queue: Key::Char('z'),
show_queue: Key::Char('Q'),
// On macOS, use Ctrl+, for settings since Alt+, produces ≤ on most keyboard layouts
Expand Down Expand Up @@ -875,7 +879,8 @@ impl UserConfig {
to_keys!(copy_song_url);
to_keys!(copy_album_url);
to_keys!(audio_analysis);
to_keys!(basic_view);
to_keys!(lyrics_view);
to_keys!(cover_art_view);
to_keys!(add_item_to_queue);
to_keys!(show_queue);
to_keys!(open_settings);
Expand Down Expand Up @@ -1222,7 +1227,8 @@ impl UserConfig {
copy_song_url: Some(key_to_config_string(self.keys.copy_song_url)),
copy_album_url: Some(key_to_config_string(self.keys.copy_album_url)),
audio_analysis: Some(key_to_config_string(self.keys.audio_analysis)),
basic_view: Some(key_to_config_string(self.keys.basic_view)),
lyrics_view: Some(key_to_config_string(self.keys.lyrics_view)),
cover_art_view: Some(key_to_config_string(self.keys.cover_art_view)),
add_item_to_queue: Some(key_to_config_string(self.keys.add_item_to_queue)),
show_queue: Some(key_to_config_string(self.keys.show_queue)),
open_settings: Some(key_to_config_string(self.keys.open_settings)),
Expand Down
12 changes: 9 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2522,8 +2522,12 @@ async fn start_ui(
ActiveBlock::Analysis => {
ui::audio_analysis::draw(f, &app);
}
ActiveBlock::BasicView => {
ui::draw_basic_view(f, &app);
ActiveBlock::LyricsView => {
ui::draw_lyrics_view(f, &app);
}
#[cfg(feature = "cover-art")]
ActiveBlock::CoverArtView => {
ui::draw_cover_art_view(f, &app);
}

ActiveBlock::AnnouncementPrompt => {
Expand Down Expand Up @@ -2837,7 +2841,9 @@ async fn start_ui(
ActiveBlock::Error => ui::draw_error_screen(f, &app),
ActiveBlock::SelectDevice => ui::draw_device_list(f, &app),
ActiveBlock::Analysis => ui::audio_analysis::draw(f, &app),
ActiveBlock::BasicView => ui::draw_basic_view(f, &app),
ActiveBlock::LyricsView => ui::draw_lyrics_view(f, &app),
#[cfg(feature = "cover-art")]
ActiveBlock::CoverArtView => ui::draw_cover_art_view(f, &app),

ActiveBlock::AnnouncementPrompt => ui::draw_announcement_prompt(f, &app),
ActiveBlock::ExitPrompt => ui::draw_exit_prompt(f, &app),
Expand Down
27 changes: 23 additions & 4 deletions src/tui/cover_art.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ use std::sync::Mutex;

pub struct CoverArt {
pub state: Mutex<Option<CoverArtState>>,
/// Separate protocol state for fullscreen cover art view, avoiding conflicts
/// when the same image is rendered in both the playbar and fullscreen in one frame.
pub fullscreen_state: Mutex<Option<CoverArtState>>,
picker: Picker,
}

Expand All @@ -36,6 +39,7 @@ impl CoverArt {
Self {
picker,
state: Mutex::new(None),
fullscreen_state: Mutex::new(None),
}
}

Expand Down Expand Up @@ -81,11 +85,18 @@ impl CoverArt {
Err(e) => return Err(anyhow!(e)),
};

let image_protocol = self
.picker
.new_resize_protocol(image::load_from_memory(&file).map_err(|e| anyhow!(e))?);
let img = image::load_from_memory(&file).map_err(|e| anyhow!(e))?;

// Create two separate protocol instances so the playbar and fullscreen
// views can render independently without conflicting.
let image_protocol = self.picker.new_resize_protocol(img.clone());
let fullscreen_protocol = self.picker.new_resize_protocol(img);

self.set_state(CoverArtState::new(image.url.clone(), image_protocol));
{
let mut lock = self.fullscreen_state.lock().unwrap();
*lock = Some(CoverArtState::new(image.url.clone(), fullscreen_protocol));
}
info!("got new cover art: {}", image.url);
} else {
debug!("skipping image refresh: cover art already downloaded");
Expand All @@ -99,7 +110,15 @@ impl CoverArt {
}

pub fn render(&self, f: &mut Frame, area: Rect) {
let mut lock = self.state.lock().unwrap();
Self::render_state(&self.state, f, area);
}

pub fn render_fullscreen(&self, f: &mut Frame, area: Rect) {
Self::render_state(&self.fullscreen_state, f, area);
}

fn render_state(state: &Mutex<Option<CoverArtState>>, f: &mut Frame, area: Rect) {
let mut lock = state.lock().unwrap();
if let Some(sp) = lock.as_mut() {
f.render_stateful_widget(
StatefulImage::new().resize(Resize::Fit(None)),
Expand Down
8 changes: 0 additions & 8 deletions src/tui/handlers/basic_view.rs

This file was deleted.

3 changes: 2 additions & 1 deletion src/tui/handlers/common_key_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,8 @@ pub fn handle_right_event(app: &mut App) {
RouteId::SelectedDevice => {}
RouteId::Error => {}
RouteId::Analysis => {}
RouteId::BasicView => {}
RouteId::LyricsView => {}
RouteId::CoverArtView => {}
RouteId::Dialog => {}
RouteId::AnnouncementPrompt => {}
RouteId::ExitPrompt => {}
Expand Down
14 changes: 14 additions & 0 deletions src/tui/handlers/cover_art_view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::core::app::App;
use crate::tui::event::Key;

pub fn handler(key: Key, app: &mut App) {
match key {
Key::Char('s') => {
super::playbar::toggle_like_currently_playing_item(app);
}
k if k == app.user_config.keys.back => {
app.pop_navigation_stack();
}
_ => {}
}
}
14 changes: 14 additions & 0 deletions src/tui/handlers/lyrics_view.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use crate::core::app::App;
use crate::tui::event::Key;

pub fn handler(key: Key, app: &mut App) {
match key {
Key::Char('s') => {
super::playbar::toggle_like_currently_playing_item(app);
}
k if k == app.user_config.keys.back => {
app.pop_navigation_stack();
}
_ => {}
}
}
23 changes: 18 additions & 5 deletions src/tui/handlers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ mod analysis;
mod announcement_prompt;
mod artist;
mod artists;
mod basic_view;
mod common_key_events;
#[cfg(feature = "cover-art")]
mod cover_art_view;
mod dialog;
mod discover;
mod empty;
Expand All @@ -15,6 +16,7 @@ mod help_menu;
mod home;
mod input;
mod library;
mod lyrics_view;
mod mouse;
mod party;
mod playbar;
Expand Down Expand Up @@ -164,8 +166,12 @@ pub fn handle_app(key: Key, app: &mut App) {
_ if key == app.user_config.keys.audio_analysis => {
app.get_audio_analysis();
}
_ if key == app.user_config.keys.basic_view => {
app.push_navigation_stack(RouteId::BasicView, ActiveBlock::BasicView);
_ if key == app.user_config.keys.lyrics_view => {
app.push_navigation_stack(RouteId::LyricsView, ActiveBlock::LyricsView);
}
#[cfg(feature = "cover-art")]
_ if key == app.user_config.keys.cover_art_view => {
app.push_navigation_stack(RouteId::CoverArtView, ActiveBlock::CoverArtView);
}
_ if key == app.user_config.keys.listening_party => {
app.push_navigation_stack(RouteId::Party, ActiveBlock::Party);
Expand Down Expand Up @@ -300,8 +306,12 @@ fn handle_block_events(key: Key, app: &mut App) {
ActiveBlock::PlayBar => {
playbar::handler(key, app);
}
ActiveBlock::BasicView => {
basic_view::handler(key, app);
ActiveBlock::LyricsView => {
lyrics_view::handler(key, app);
}
ActiveBlock::CoverArtView => {
#[cfg(feature = "cover-art")]
cover_art_view::handler(key, app);
}
ActiveBlock::Dialog(_) => {
dialog::handler(key, app);
Expand Down Expand Up @@ -355,6 +365,9 @@ fn handle_escape(app: &mut App) {
ActiveBlock::Party => {
app.pop_navigation_stack();
}
ActiveBlock::LyricsView | ActiveBlock::CoverArtView => {
app.pop_navigation_stack();
}
// These are global views that have no active/inactive distinction so do nothing
ActiveBlock::SelectDevice | ActiveBlock::Analysis => {}

Expand Down
Loading
Loading