Rockbox open source high quality audio player as a Music Player Daemon
mpris rockbox mpd libadwaita audio rust zig deno
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

gpui: update player screen background

+76 -17
+1 -1
README.md
··· 48 48 49 49 ### Clients 50 50 - [x] Web client (React) 51 - - [x] Desktop client (Electron / GTK4) 51 + - [x] Desktop client (Native MacOS / GPUI / GTK4) 52 52 - [x] Terminal client (TUI) 53 53 - [x] Rockbox REPL 54 54
+48 -15
gpui/src/ui/components/pages/library.rs
··· 418 418 let group_name: gpui::SharedString = 419 419 format!("track_group_{}_{}", row_id.0, row_id.1).into(); 420 420 let group_name2 = group_name.clone(); 421 - let _group_name3 = group_name.clone(); 421 + let group_name_for_num = group_name.clone(); 422 + let group_name_for_play = group_name.clone(); 422 423 let opts_id: gpui::SharedString = format!("{}_opts_{}", row_id.0, row_id.1).into(); 423 424 let heart_id: gpui::SharedString = format!("{}_heart_{}", row_id.0, row_id.1).into(); 425 + let play_id: gpui::SharedString = format!("{}_play_{}", row_id.0, row_id.1).into(); 426 + let path_for_play = path.clone(); 424 427 div() 425 428 .id(row_id) 426 429 .group(group_name) ··· 437 440 .border_b_2() 438 441 .border_color(theme.switcher_active) 439 442 }) 440 - .on_click(move |_, _, cx: &mut App| { 441 - let rt = cx.global::<Controller>().rt(); 442 - rt.spawn(crate::client::play_track(path.clone())); 443 - }) 444 443 .child( 445 444 div() 446 445 .w(px(28.0)) 446 + .h(px(20.0)) 447 447 .flex_shrink_0() 448 - .flex() 449 - .items_center() 450 - .when(!is_current, |this| { 451 - this.text_sm() 452 - .text_color(theme.library_header_text) 453 - .child(num) 454 - }) 455 - .when(is_current, |this| { 456 - this.child(equalizer_bars(row_id.1, is_playing)) 457 - }), 448 + .relative() 449 + // Track number / equalizer bars — hidden on row hover 450 + .child( 451 + div() 452 + .absolute() 453 + .top_0() 454 + .left_0() 455 + .w_full() 456 + .h_full() 457 + .flex() 458 + .items_center() 459 + .group_hover(group_name_for_num, |s| s.opacity(0.0)) 460 + .when(!is_current, |this| { 461 + this.text_sm() 462 + .text_color(theme.library_header_text) 463 + .child(num) 464 + }) 465 + .when(is_current, |this| { 466 + this.child(equalizer_bars(row_id.1, is_playing)) 467 + }), 468 + ) 469 + // Play icon — appears on row hover 470 + .child( 471 + div() 472 + .id(play_id) 473 + .absolute() 474 + .top_0() 475 + .left(px(-3.0)) 476 + .w_full() 477 + .h_full() 478 + .flex() 479 + .items_center() 480 + .opacity(0.0) 481 + .group_hover(group_name_for_play, |s| s.opacity(1.0)) 482 + .cursor_pointer() 483 + .text_color(theme.library_text) 484 + .on_click(move |_, _, cx: &mut App| { 485 + cx.stop_propagation(); 486 + let rt = cx.global::<Controller>().rt(); 487 + rt.spawn(crate::client::play_track(path_for_play.clone())); 488 + }) 489 + .child(Icon::new(Icons::Play).size_4()), 490 + ), 458 491 ) 459 492 .child( 460 493 div()
+27 -1
gpui/src/ui/components/pages/player.rs
··· 9 9 use gpui::prelude::FluentBuilder; 10 10 use gpui::px; 11 11 use gpui::{ 12 - div, img, App, Context, Entity, FontWeight, InteractiveElement, IntoElement, ObjectFit, 12 + div, img, rgba, App, Context, Entity, FontWeight, InteractiveElement, IntoElement, ObjectFit, 13 13 ParentElement, Render, StatefulInteractiveElement, Styled, StyledImage, Window, 14 14 }; 15 15 ··· 49 49 .and_then(|t| t.album_art.as_deref()) 50 50 .filter(|s| !s.is_empty()) 51 51 .map(|id| format!("http://localhost:6062/covers/{id}")); 52 + let bg_art_url = album_art_url.clone(); 52 53 let queue_total = state.queue.len(); 53 54 let queue_pos = state.current_idx.map(|i| i + 1); 54 55 let current_path = state.current_track().map(|t| t.path.clone()).unwrap_or_default(); ··· 64 65 .size_full() 65 66 .flex() 66 67 .flex_col() 68 + .relative() 67 69 .bg(theme.player_bg) 70 + // Full-screen album art background (low opacity) 71 + .when_some(bg_art_url, |this, url| { 72 + this.child( 73 + div() 74 + .absolute() 75 + .top_0() 76 + .left_0() 77 + .w_full() 78 + .h_full() 79 + .opacity(0.4) 80 + .overflow_hidden() 81 + .child(img(url).w_full().h_full().object_fit(ObjectFit::Cover)), 82 + ) 83 + // Dark scrim so text stays readable 84 + .child( 85 + div() 86 + .absolute() 87 + .top_0() 88 + .left_0() 89 + .w_full() 90 + .h_full() 91 + .bg(rgba(0x0F1117BF)), 92 + ) 93 + }) 68 94 .child( 69 95 div() 70 96 .flex_1()