Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jacksongoode committed Jan 29, 2025
1 parent e9367ba commit 005e15f
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 89 deletions.
1 change: 1 addition & 0 deletions psst-gui/src/cmd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::sync::Arc;
use std::time::Duration;

use crate::{
data::Alert,
data::{Nav, PlaybackPayload, QueueBehavior, QueueEntry},
ui::find::Find,
};
Expand Down
2 changes: 1 addition & 1 deletion psst-gui/src/controller/playback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ impl PlaybackController {
album: album.as_deref(),
artist: artist.as_deref(),
duration,
cover_url,
cover_url: cover_url.as_deref(),
})
.unwrap();
}
Expand Down
13 changes: 1 addition & 12 deletions psst-gui/src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ impl AppState {
impl AppState {
pub fn add_alert(&mut self, message: impl Display, style: AlertStyle) {
let alert = Alert {
message: message.to_string().into(),
message: Arc::from(message.to_string()),
style,
id: Alert::fresh_id(),
created_at: Instant::now(),
Expand Down Expand Up @@ -485,11 +485,6 @@ impl Library {
}
}
}

pub fn get_album(&self, id: &str) -> Option<&Arc<Album>> {
self.saved_albums.resolved()
.and_then(|albums| albums.albums.iter().find(|a| a.id.as_ref() == id))
}
}

#[derive(Clone, Default, Data, Lens)]
Expand Down Expand Up @@ -580,12 +575,6 @@ pub struct Alert {
pub created_at: Instant,
}

impl Alert {
fn fresh_id() -> usize {
ALERT_ID.fetch_add(1, Ordering::SeqCst)
}
}

#[derive(Clone, Data, Eq, PartialEq)]
pub enum AlertStyle {
Error,
Expand Down
46 changes: 26 additions & 20 deletions psst-gui/src/data/playback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,32 +91,38 @@ pub struct NowPlaying {
}

impl NowPlaying {
pub fn cover_image_url(&self, width: f64, height: f64) -> Option<&str> {
pub fn cover_image_url(&self, _width: f64, _height: f64) -> Option<String> {
match &self.item {
Playable::Track(track) => {
let album = track.album.as_ref().or(match &self.origin {
PlaybackOrigin::Album(album) => Some(album),
_ => None,
})?;
Some(&album.image(width, height)?.url)
}
Playable::Episode(episode) => Some(&episode.image(width, height)?.url),
Playable::Track(track) => track
.album
.as_ref()
.and_then(|album| album.images.get(0).map(|img| img.url.to_string())),
Playable::Episode(episode) => episode.images.get(0).map(|img| img.url.to_string()),
}
}

pub fn cover_image_metadata(&self) -> Option<(&str, (u32, u32))> {
match &self.item {
Playable::Track(track) => {
track.album.as_ref().map(|album_link| {
// Use floating point values for image dimensions
album_link.image(0.0, 0.0) // Use any size since we just need the URL
.map(|img| (&*img.url, (img.width.unwrap_or(0) as u32, img.height.unwrap_or(0) as u32)))
}).flatten()
}
Playable::Episode(episode) =>
// Use get(0) instead of first() for Vector type
episode.images.get(0)
.map(|img| (&*img.url, (img.width.unwrap_or(0) as u32, img.height.unwrap_or(0) as u32)))
Playable::Track(track) => track.album.as_ref().and_then(|album| {
album.images.get(0).map(|img| {
(
&*img.url,
(
img.width.unwrap_or(0) as u32,
img.height.unwrap_or(0) as u32,
),
)
})
}),
Playable::Episode(episode) => episode.images.get(0).map(|img| {
(
&*img.url,
(
img.width.unwrap_or(0) as u32,
img.height.unwrap_or(0) as u32,
),
)
}),
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions psst-gui/src/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ use std::fs;
use std::io::Read;
use threadpool::ThreadPool;

use crate::ui::album::DOWNLOAD_ARTWORK;
use crate::ui::playlist::{
RENAME_PLAYLIST, RENAME_PLAYLIST_CONFIRM, UNFOLLOW_PLAYLIST, UNFOLLOW_PLAYLIST_CONFIRM,
};
use crate::ui::theme;
use crate::ui::DOWNLOAD_ARTWORK;
use crate::{
cmd,
data::{AppState, Config},
Expand Down Expand Up @@ -214,14 +214,13 @@ impl AppDelegate<AppState> for Delegate {
} else if cmd.is(crate::cmd::SHOW_ARTWORK) {
self.show_artwork(ctx);
Handled::Yes
} else if let Some((url, album_name)) = cmd.get::<(String, String)>(DOWNLOAD_ARTWORK) {
} else if let Some((url, title)) = cmd.get(DOWNLOAD_ARTWORK) {
// Sanitize title
let safe_title = title.replace(['/', '\\', ':', '*', '?', '"', '<', '>', '|'], "_");
let file_name = format!("{} cover.jpg", safe_title);
// Get user's download directory
if let Some(user_dirs) = UserDirs::new() {
if let Some(download_dir) = user_dirs.download_dir() {
// Sanitize album name for filename
let safe_name =
album_name.replace(['/', '\\', ':', '*', '?', '"', '<', '>', '|'], "_");
let file_name = format!("{}_cover.jpg", safe_name);
let path = download_dir.join(file_name);

// Download the image
Expand All @@ -233,6 +232,7 @@ impl AppDelegate<AppState> for Delegate {
{
if fs::write(&path, bytes).is_ok() {
log::info!("Downloaded album artwork to {:?}", path);
data.info_alert("Cover saved to Downloads folder.");
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions psst-gui/src/ui/album.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ use crate::{
use super::{artist, library, playable, theme, track, utils};

pub const LOAD_DETAIL: Selector<AlbumLink> = Selector::new("app.album.load-detail");
pub const DOWNLOAD_ARTWORK: Selector<(String, String)> =
Selector::new("app.album.download-artwork");

pub fn detail_widget() -> impl Widget<AppState> {
Async::new(
Expand Down
72 changes: 47 additions & 25 deletions psst-gui/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ use crate::{
},
};
use credits::TrackCredits;
use druid::LocalizedString;
use druid::widget::Controller;
use druid::KbKey;
use druid::{
im::Vector,
widget::{CrossAxisAlignment, Either, Flex, Label, List, Scroll, Slider, Split, ViewSwitcher},
Expand Down Expand Up @@ -48,6 +49,8 @@ pub mod track;
pub mod user;
pub mod utils;

pub const DOWNLOAD_ARTWORK: Selector<(String, String)> = Selector::new("app.artwork.download");

pub fn main_window(config: &Config) -> WindowDesc<AppState> {
let win = WindowDesc::new(root_widget())
.title(compute_main_window_title)
Expand Down Expand Up @@ -152,7 +155,48 @@ fn account_setup_widget() -> impl Widget<AppState> {
)
}

fn artwork_widget() -> impl Widget<AppState> {
struct ArtworkController;

impl<W: Widget<AppState>> Controller<AppState, W> for ArtworkController {
fn event(
&mut self,
child: &mut W,
ctx: &mut druid::EventCtx,
event: &druid::Event,
data: &mut AppState,
env: &druid::Env,
) {
if let druid::Event::WindowConnected = event {
ctx.request_focus();
ctx.set_handled();
}

if let druid::Event::KeyDown(key_event) = event {
// Handle D key for download
if key_event.key == KbKey::Character('d'.into()) {
if let Some(np) = &data.playback.now_playing {
if let Some((url, _)) = np.cover_image_metadata() {
let title = match &np.item {
Playable::Track(track) => track
.album
.as_ref()
.map(|a| a.name.as_ref())
.unwrap_or("Unknown Album"),
Playable::Episode(episode) => episode.show.name.as_ref(),
};
ctx.submit_command(
DOWNLOAD_ARTWORK.with((url.to_string(), title.to_string())),
);
ctx.set_handled();
}
}
}
}
child.event(ctx, event, data, env);
}
}

pub fn artwork_widget() -> impl Widget<AppState> {
RemoteImage::new(utils::placeholder_widget(), move |data: &AppState, _| {
data.playback
.now_playing
Expand All @@ -162,29 +206,7 @@ fn artwork_widget() -> impl Widget<AppState> {
})
.expand()
.background(theme::BACKGROUND_DARK)
.context_menu(|data: &AppState| {
let mut menu = Menu::empty();
if let Some(np) = &data.playback.now_playing {
if let Playable::Track(track) = &np.item {
if let Some(album) = track.album.as_ref() {
// Get largest available image
if let Some((image_url, _)) = np.cover_image_metadata() {
menu = menu.entry(
MenuItem::new(
LocalizedString::new("menu-item-download-artwork")
.with_placeholder("Download Cover"),
)
.command(
album::DOWNLOAD_ARTWORK
.with((image_url.to_string(), album.name.to_string())),
),
);
}
}
}
}
menu
})
.controller(ArtworkController)
}

fn root_widget() -> impl Widget<AppState> {
Expand Down
2 changes: 1 addition & 1 deletion psst-gui/src/ui/playable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use druid::{
use crate::{
cmd,
data::{
Album, ArtistTracks, CommonCtx, FindQuery, MatchFindQuery, Playable, PlaybackOrigin,
ArtistTracks, CommonCtx, FindQuery, MatchFindQuery, Playable, PlaybackOrigin,
PlaybackPayload, PlaylistTracks, Recommendations, SavedTracks, SearchResults, ShowEpisodes,
Track, WithCtx,
},
Expand Down
24 changes: 2 additions & 22 deletions psst-gui/src/ui/playback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use druid::{
kurbo::{Affine, BezPath},
widget::{CrossAxisAlignment, Either, Flex, Label, LineBreaking, Spinner, ViewSwitcher},
BoxConstraints, Cursor, Data, Env, Event, EventCtx, LayoutCtx, LensExt, LifeCycle,
LifeCycleCtx, LocalizedString, Menu, MenuItem, MouseButton, PaintCtx, Point, Rect,
RenderContext, Size, UpdateCtx, Widget, WidgetExt, WidgetPod,
LifeCycleCtx, MouseButton, PaintCtx, Point, Rect, RenderContext, Size, UpdateCtx, Widget,
WidgetExt, WidgetPod,
};
use itertools::Itertools;

Expand Down Expand Up @@ -172,26 +172,6 @@ fn cover_widget(size: f64) -> impl Widget<NowPlaying> {
.on_left_click(|ctx, _, _, _| {
ctx.submit_command(SHOW_ARTWORK);
})
.context_menu(|np: &NowPlaying| {
let mut menu = Menu::empty();
if let Playable::Track(track) = &np.item {
if let Some(album) = track.album.as_ref() {
if let Some((image_url, _)) = np.cover_image_metadata() {
menu = menu.entry(
MenuItem::new(
LocalizedString::new("menu-item-download-artwork")
.with_placeholder("Download Cover"),
)
.command(
super::album::DOWNLOAD_ARTWORK
.with((image_url.to_string(), album.name.to_string())),
),
);
}
}
}
menu
})
}

fn playback_origin_icon(origin: &PlaybackOrigin) -> &'static SvgIcon {
Expand Down

0 comments on commit 005e15f

Please sign in to comment.