Skip to content

Commit cb717ee

Browse files
Merge branch 'display-genres' into display-genres-master-update
2 parents bd38dd0 + c260fba commit cb717ee

File tree

8 files changed

+97
-3
lines changed

8 files changed

+97
-3
lines changed

docs/config.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ All configuration files should be placed inside the application's configuration
5252
| `liked_icon` | the icon to indicate the liked state of a song | `` |
5353
| `border_type` | the type of the application's borders | `Plain` |
5454
| `progress_bar_type` | the type of the playback progress bar | `Rectangle` |
55+
| `genre_num` | the amount of genres to display at `{genres}` | `2` |
5556
| `cover_img_width` | the width of the cover image (`image` feature only) | `5` |
5657
| `cover_img_length` | the length of the cover image (`image` feature only) | `9` |
5758
| `cover_img_scale` | the scale of the cover image (`image` feature only) | `1.0` |

examples/app.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ theme = "default"
22
login_redirect_uri = "http://127.0.0.1:8989/login"
33
client_port = 8080
44
tracks_playback_limit = 50
5-
playback_format = "{status} {track} • {artists}\n{album}\n{metadata}"
5+
playback_format = "{status} {track} • {artists}\n{album} • {genres}\n{metadata}"
66
playback_metadata_fields = ["repeat", "shuffle", "volume", "device"]
77
notify_format = { summary = "{track} • {artists}", body = "{album}" }
88
notify_timeout_in_secs = 0
@@ -18,6 +18,7 @@ default_device = "spotify-player"
1818
play_icon = ""
1919
pause_icon = "▌▌"
2020
liked_icon = ""
21+
genre_num = 2
2122
cover_img_length = 9
2223
cover_img_width = 5
2324
cover_img_pixels = 16

spotify_player/src/client/mod.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,38 @@ impl AppClient {
16351635
track_or_episode.clone()
16361636
};
16371637

1638+
// retrieve current artist for genres if not in cache
1639+
let curr_artist = match &curr_item {
1640+
rspotify::model::PlayableItem::Track(full_track) => {
1641+
let cached = state
1642+
.data
1643+
.read()
1644+
.caches
1645+
.genres
1646+
.contains_key(&full_track.artists[0].name);
1647+
1648+
if cached {
1649+
None
1650+
} else {
1651+
match &full_track.artists[0].id {
1652+
Some(id) => self.spotify.artist(id.clone()).await.ok(),
1653+
None => None,
1654+
}
1655+
}
1656+
}
1657+
rspotify::model::PlayableItem::Episode(_) => None,
1658+
};
1659+
1660+
if let Some(artist) = curr_artist {
1661+
if !artist.genres.is_empty() {
1662+
state.data.write().caches.genres.insert(
1663+
artist.name,
1664+
artist.genres,
1665+
*TTL_CACHE_DURATION,
1666+
);
1667+
}
1668+
}
1669+
16381670
let url = match curr_item {
16391671
rspotify::model::PlayableItem::Track(ref track) => {
16401672
crate::utils::get_track_album_image_url(track)

spotify_player/src/config/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ pub struct AppConfig {
8989

9090
pub layout: LayoutConfig,
9191

92+
pub genre_num: u8,
93+
9294
#[cfg(feature = "image")]
9395
pub cover_img_length: usize,
9496
#[cfg(feature = "image")]
@@ -204,6 +206,7 @@ pub struct LibraryLayoutConfig {
204206
pub album_percent: u16,
205207
}
206208

209+
#[allow(dead_code)]
207210
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
208211
#[serde(from = "StreamingTypeOrBool")]
209212
pub enum StreamingType {
@@ -221,6 +224,7 @@ enum RawStreamingType {
221224
Never,
222225
}
223226

227+
#[allow(dead_code)]
224228
#[derive(Deserialize)]
225229
#[serde(untagged)]
226230
enum StreamingTypeOrBool {
@@ -267,7 +271,7 @@ impl Default for AppConfig {
267271
tracks_playback_limit: 50,
268272

269273
playback_format: String::from(
270-
"{status} {track} • {artists} {liked}\n{album}\n{metadata}",
274+
"{status} {track} • {artists} {liked}\n{album} • {genres}\n{metadata}",
271275
),
272276
playback_metadata_fields: vec![
273277
"repeat".to_string(),
@@ -301,6 +305,8 @@ impl Default for AppConfig {
301305

302306
layout: LayoutConfig::default(),
303307

308+
genre_num: 2,
309+
304310
#[cfg(feature = "image")]
305311
cover_img_length: 9,
306312
#[cfg(feature = "image")]

spotify_player/src/config/theme.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ struct ComponentStyle {
6868
playback_track: Option<Style>,
6969
playback_artists: Option<Style>,
7070
playback_album: Option<Style>,
71+
playback_genres: Option<Style>,
7172
playback_metadata: Option<Style>,
7273
playback_progress_bar: Option<Style>,
7374
playback_progress_bar_unfilled: Option<Style>,
@@ -253,6 +254,18 @@ impl Theme {
253254
.style(&self.palette)
254255
}
255256

257+
pub fn playback_genres(&self) -> style::Style {
258+
self.component_style
259+
.playback_genres
260+
.as_ref()
261+
.unwrap_or(
262+
&Style::default()
263+
.fg(StyleColor::BrightBlack)
264+
.modifiers([StyleModifier::Italic]),
265+
)
266+
.style(&self.palette)
267+
}
268+
256269
pub fn playback_metadata(&self) -> style::Style {
257270
self.component_style
258271
.playback_metadata

spotify_player/src/state/data.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub struct MemoryCaches {
5050
pub context: ttl_cache::TtlCache<String, Context>,
5151
pub search: ttl_cache::TtlCache<String, SearchResults>,
5252
pub lyrics: ttl_cache::TtlCache<String, Option<Lyrics>>,
53+
pub genres: ttl_cache::TtlCache<String, Vec<String>>,
5354
#[cfg(feature = "image")]
5455
pub images: ttl_cache::TtlCache<String, image::DynamicImage>,
5556
}
@@ -67,6 +68,7 @@ impl MemoryCaches {
6768
context: ttl_cache::TtlCache::new(64),
6869
search: ttl_cache::TtlCache::new(64),
6970
lyrics: ttl_cache::TtlCache::new(64),
71+
genres: ttl_cache::TtlCache::new(64),
7072
#[cfg(feature = "image")]
7173
images: ttl_cache::TtlCache::new(64),
7274
}

spotify_player/src/state/ui/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ fn fuzzy_search_items<'a, T: std::fmt::Display>(items: &'a [T], query: &str) ->
128128
.iter()
129129
.filter_map(|t| {
130130
matcher
131-
.fuzzy(&t.to_string(), &query, false)
131+
.fuzzy(&t.to_string(), query, false)
132132
.map(|(score, _)| (t, score))
133133
})
134134
.collect::<Vec<_>>();

spotify_player/src/ui/playback.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,18 @@ fn construct_playback_text(
286286
ui.theme.playback_album(),
287287
),
288288
},
289+
"{genres}" => match playable {
290+
rspotify::model::PlayableItem::Track(full_track) => {
291+
let genre = match data.caches.genres.get(&full_track.artists[0].name) {
292+
Some(genres) => &format_genres(genres, configs.app_config.genre_num),
293+
None => "no genre",
294+
};
295+
(to_bidi_string(genre), ui.theme.playback_genres())
296+
}
297+
rspotify::model::PlayableItem::Episode(_) => {
298+
(to_bidi_string("no genre"), ui.theme.playback_genres())
299+
}
300+
},
289301
"{metadata}" => {
290302
let repeat_value = if playback.fake_track_repeat_state {
291303
"track (fake)".to_string()
@@ -457,3 +469,30 @@ fn split_rect_for_playback_window(rect: Rect) -> (Rect, Rect) {
457469
}
458470
}
459471
}
472+
473+
/// formats genres depending on the number of genres and `genre_num`
474+
///
475+
/// Examples for `genre_num = 2`
476+
/// - 1 genre: "genre1"
477+
/// - 2 genres: "genre1, genre2"
478+
/// - \>= 3 genres: "genre1, genre2, ..."
479+
fn format_genres(genres: &[String], genre_num: u8) -> String {
480+
let mut genre_str = String::with_capacity(64);
481+
482+
if genre_num > 0 {
483+
for i in 0..genres.len() {
484+
genre_str.push_str(&genres[i]);
485+
486+
if i + 1 != genres.len() {
487+
genre_str.push_str(", ");
488+
489+
if i + 1 >= genre_num as usize {
490+
genre_str.push_str("...");
491+
break;
492+
}
493+
}
494+
}
495+
}
496+
497+
genre_str
498+
}

0 commit comments

Comments
 (0)