feat(music): relocate playlist into a now-playing bar + slide-out drawer
The full music panel was rendered inline at all times (its own card in the 3-column layout, stuffed into the Controls panel otherwise), which crowded every layout. Move it behind two toggles: - A room-only ♪ button in the top bar shows/hides a slim 56px now-playing player bar (track + ⏮ ⏸/▶ ⏭ + position + expand). The preference persists (AppConfig.show_player_bar). - The bar's ⤢ button opens the full panel in a resizable right-edge drawer (DividerKind::PlaylistDrawer, mirrors the Chat drawer). When open, body_w shrinks so the layouts' fixed panels don't overflow. Removes all inline playlist placement (3-col card + ThreeColPlaylist divider, ctrl_music block) and the now-dead clamp/consts. Pure now_playing_label seam + drawer-width clamp test. 474 lib tests, clippy -D warnings clean, release build green. Implemented by Codex (gpt-5.5), reviewed + gates re-run by Claude. Co-Authored-By: Codex <codex@openai.com> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -138,6 +138,10 @@ fn default_chat_drawer_width() -> f32 {
|
||||
320.0
|
||||
}
|
||||
|
||||
fn default_playlist_drawer_width() -> f32 {
|
||||
320.0
|
||||
}
|
||||
|
||||
fn default_window_width() -> f32 {
|
||||
900.0
|
||||
}
|
||||
@@ -174,6 +178,9 @@ pub struct AppConfig {
|
||||
/// W22 music: opt-in shared listening broadcast toggle. Local preference.
|
||||
#[serde(default)]
|
||||
pub music_broadcast: bool,
|
||||
/// Show the slim now-playing player bar in the room screen.
|
||||
#[serde(default = "default_true")]
|
||||
pub show_player_bar: bool,
|
||||
/// When true, `clip_volume` governs every clip. When false, each clip keeps
|
||||
/// its own (in-memory) level and the universal slider is inactive.
|
||||
#[serde(default = "default_true")]
|
||||
@@ -207,6 +214,9 @@ pub struct AppConfig {
|
||||
/// Chat drawer width for the drawer layout (px).
|
||||
#[serde(default = "default_chat_drawer_width")]
|
||||
pub chat_drawer_width: f32,
|
||||
/// Playlist drawer width for the room-screen right-edge music panel (px).
|
||||
#[serde(default = "default_playlist_drawer_width")]
|
||||
pub playlist_drawer_width: f32,
|
||||
/// Chosen arrangement of the in-call room screen.
|
||||
#[serde(default)]
|
||||
pub room_layout: RoomLayout,
|
||||
@@ -348,6 +358,7 @@ impl Default for AppConfig {
|
||||
music_playlist: Vec::new(),
|
||||
music_volume: 1.0,
|
||||
music_broadcast: false,
|
||||
show_player_bar: true,
|
||||
clip_volume_universal: true,
|
||||
network_mode: NetworkMode::default(),
|
||||
presence_mode: crate::presence::PresenceMode::default(),
|
||||
@@ -358,6 +369,7 @@ impl Default for AppConfig {
|
||||
threecol_playlist_height: default_threecol_playlist_height(),
|
||||
controls_width: default_controls_width(),
|
||||
chat_drawer_width: default_chat_drawer_width(),
|
||||
playlist_drawer_width: default_playlist_drawer_width(),
|
||||
room_layout: RoomLayout::default(),
|
||||
theme: AppTheme::default(),
|
||||
avatar: crate::avatar::Avatar::default(),
|
||||
@@ -517,6 +529,8 @@ mod tests {
|
||||
assert_eq!(deserialized.room_layout, RoomLayout::BottomDock);
|
||||
assert_eq!(deserialized.controls_width, 280.0);
|
||||
assert_eq!(deserialized.chat_drawer_width, 320.0);
|
||||
assert_eq!(deserialized.playlist_drawer_width, 320.0);
|
||||
assert!(deserialized.show_player_bar);
|
||||
assert!(deserialized.custom_sound_self_join.is_none());
|
||||
assert!(deserialized.custom_sound_peer_join.is_none());
|
||||
assert!(deserialized.custom_sound_peer_leave.is_none());
|
||||
@@ -701,6 +715,7 @@ mod tests {
|
||||
assert!(def.music_playlist.is_empty());
|
||||
assert_eq!(def.music_volume, 1.0);
|
||||
assert!(!def.music_broadcast);
|
||||
assert!(def.show_player_bar);
|
||||
assert!(def.clip_volume_universal);
|
||||
|
||||
// Missing in JSON → unity (serde default).
|
||||
@@ -712,6 +727,7 @@ mod tests {
|
||||
assert!(cfg_missing.music_playlist.is_empty());
|
||||
assert_eq!(cfg_missing.music_volume, 1.0);
|
||||
assert!(!cfg_missing.music_broadcast);
|
||||
assert!(cfg_missing.show_player_bar);
|
||||
// Configs predating the toggle default to universal mode.
|
||||
assert!(cfg_missing.clip_volume_universal);
|
||||
|
||||
@@ -723,6 +739,7 @@ mod tests {
|
||||
music_playlist: vec!["/tmp/song.ogg".to_string()],
|
||||
music_volume: 0.6,
|
||||
music_broadcast: true,
|
||||
show_player_bar: false,
|
||||
clip_volume_universal: false,
|
||||
..AppConfig::default()
|
||||
};
|
||||
@@ -734,6 +751,7 @@ mod tests {
|
||||
assert_eq!(round_tripped.music_playlist, vec!["/tmp/song.ogg".to_string()]);
|
||||
assert_eq!(round_tripped.music_volume, 0.6);
|
||||
assert!(round_tripped.music_broadcast);
|
||||
assert!(!round_tripped.show_player_bar);
|
||||
assert!(!round_tripped.clip_volume_universal);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user