fix more whitespace issues in rsx autofmt nested rsx blocks (#5257)
* trim * works a bit better * almost... * it work? * yay! * codex tried a thing * move * reduce to 1 * remove search * simplify * adjust test case * clippy
This commit is contained in:
1 parent
ceb82612e0
commit
b6793dc2b4
4 files changed
+667
-58
No files matched your search
@@ -0,0 +1,250 @@
|
||||
pub fn MediaPlayerControls() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
// Control Panel Row
|
||||
nav { class: "h-12 border-b border-gray-200 dark:border-[#222] flex items-center justify-between px-6 shrink-0 bg-gray-50 dark:bg-[#000000]",
|
||||
// Right: Playback controls + Settings
|
||||
div { class: "flex items-center gap-2",
|
||||
// Playback buttons - shown only when track is loaded
|
||||
if let Some(track_id_str) = ¤t_track_id {
|
||||
// Get current track from the tracks hashmap
|
||||
{
|
||||
let current_track = tracks().get(track_id_str).cloned();
|
||||
let track_id_owned = track_id_str.clone();
|
||||
|
||||
rsx! {
|
||||
// Play and Download buttons
|
||||
if current_track.is_some() {
|
||||
{
|
||||
rsx! {
|
||||
// Play button - streams audio to device
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors flex items-center gap-1.5 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 cursor-pointer disabled:opacity-50",
|
||||
title: "Play track (streams audio)",
|
||||
disabled: is_buffering(),
|
||||
onclick: {
|
||||
let tid = track_id_owned.clone();
|
||||
// Capture output device for streaming
|
||||
let output_device = current_track
|
||||
.as_ref()
|
||||
.and_then(|t| t.preferred_output.clone());
|
||||
move |_| {
|
||||
let tid = tid.clone();
|
||||
let output_device = output_device.clone();
|
||||
async move {
|
||||
playback_result.set(None);
|
||||
playback_error.set(None);
|
||||
is_buffering.set(true);
|
||||
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
let request = StreamAudioRequest {};
|
||||
|
||||
match start_audio_stream(track_id, request).await {
|
||||
Ok(stream) => {
|
||||
// Use output device if available, otherwise fall back to default
|
||||
let device = output_device
|
||||
.map(|d| format!("{}/", d))
|
||||
.unwrap_or_else(|| "/dev/audio/default".to_string());
|
||||
|
||||
// Connect to the audio stream endpoint
|
||||
let stream_url = format!(
|
||||
"audio://stream/{}@{}{}",
|
||||
stream.session_token,
|
||||
stream.server_host,
|
||||
device,
|
||||
);
|
||||
// Open the audio stream
|
||||
#[cfg(feature = "web")]
|
||||
if let Some(window) = web_sys::window() {
|
||||
let _ = window.location().set_href(&stream_url);
|
||||
}
|
||||
#[cfg(not(feature = "web"))]
|
||||
let _ = stream_url;
|
||||
}
|
||||
Err(e) => {
|
||||
playback_error
|
||||
.set(Some(format!("Failed to start stream: {}", e)));
|
||||
show_error_modal.set(true);
|
||||
}
|
||||
}
|
||||
is_buffering.set(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "play_arrow",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#2563eb".to_string()),
|
||||
}
|
||||
if is_buffering() {
|
||||
"Buffering..."
|
||||
} else if SHOW_CONTROL_TEXT {
|
||||
"Play"
|
||||
}
|
||||
}
|
||||
|
||||
// Download button - downloads track locally
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer disabled:opacity-50",
|
||||
title: "Download track for offline playback",
|
||||
disabled: is_buffering(),
|
||||
onclick: {
|
||||
let tid = track_id_owned.clone();
|
||||
move |_| {
|
||||
let tid = tid.clone();
|
||||
async move {
|
||||
playback_result.set(None);
|
||||
playback_error.set(None);
|
||||
is_buffering.set(true);
|
||||
show_download_modal.set(true);
|
||||
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
let request = DownloadTrackRequest {};
|
||||
|
||||
match download_track(track_id, request).await {
|
||||
Ok(download) => {
|
||||
playback_result.set(Some(download));
|
||||
}
|
||||
Err(e) => {
|
||||
playback_error
|
||||
.set(Some(format!("Failed to download: {}", e)));
|
||||
}
|
||||
}
|
||||
is_buffering.set(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "download",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if is_buffering() {
|
||||
"Downloading..."
|
||||
} else if SHOW_CONTROL_TEXT {
|
||||
"Download"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fullscreen mode toggle
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white mr-2 pr-3 border-r border-gray-200 dark:border-[#333] cursor-pointer",
|
||||
title: if (ctx.fullscreen)() { "Exit fullscreen" } else { "Enter fullscreen" },
|
||||
onclick: move |_| ctx.fullscreen.set(!(ctx.fullscreen)()),
|
||||
Icon {
|
||||
name: if (ctx.fullscreen)() { "fullscreen_exit" } else { "fullscreen" },
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
if (ctx.fullscreen)() {
|
||||
"Exit Fullscreen"
|
||||
} else {
|
||||
"Fullscreen"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "flex items-center gap-1 mr-2 pr-3 border-r border-gray-200 dark:border-[#333]",
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer",
|
||||
title: "Add to playlist",
|
||||
onclick: move |_| show_playlist_modal.set(true),
|
||||
Icon {
|
||||
name: "playlist_add",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Add to Playlist"
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref track) = current_track {
|
||||
{
|
||||
let track_id_for_action = track_id_owned.clone();
|
||||
match track.status {
|
||||
TrackStatus::Playing { .. } => rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer",
|
||||
title: "Pause playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_action.clone();
|
||||
async move {
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
if let Err(e) = pause_track(track_id).await {
|
||||
error!("Failed to pause: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "pause",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Pause"
|
||||
}
|
||||
}
|
||||
},
|
||||
TrackStatus::Paused { .. } => rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 bg-green-600 hover:bg-green-500 text-white rounded transition-colors flex items-center gap-1.5 text-sm cursor-pointer",
|
||||
title: "Resume playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_action.clone();
|
||||
async move {
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
if let Err(e) = resume_track(track_id).await {
|
||||
error!("Failed to resume: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon { name: "play_arrow", size: 16, color: IconColor::Light }
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Resume"
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => rsx! {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let track_id_for_stop = track_id_owned.clone();
|
||||
rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-red-100 dark:hover:bg-red-900/30 rounded transition-colors flex items-center gap-1.5 text-sm text-red-600 dark:text-red-400 cursor-pointer",
|
||||
title: "Stop playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_stop.clone();
|
||||
async move {
|
||||
if let Err(e) = stop_track(tid).await {
|
||||
error!("Failed to stop: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "stop",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#dc2626".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Stop"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
pub fn MediaPlayerControls() -> Element {
|
||||
rsx! {
|
||||
div {
|
||||
// Control Panel Row
|
||||
nav { class: "h-12 border-b border-gray-200 dark:border-[#222] flex items-center justify-between px-6 shrink-0 bg-gray-50 dark:bg-[#000000]",
|
||||
// Right: Playback controls + Settings
|
||||
div { class: "flex items-center gap-2",
|
||||
// Playback buttons - shown only when track is loaded
|
||||
if let Some(track_id_str) = ¤t_track_id {
|
||||
// Get current track from the tracks hashmap
|
||||
{
|
||||
let current_track = tracks().get(track_id_str).cloned();
|
||||
let track_id_owned = track_id_str.clone();
|
||||
|
||||
rsx! {
|
||||
// Play and Download buttons
|
||||
if current_track.is_some() {
|
||||
{
|
||||
rsx! {
|
||||
// Play button - streams audio to device
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded transition-colors flex items-center gap-1.5 text-sm text-blue-600 dark:text-blue-400 hover:text-blue-700 dark:hover:text-blue-300 cursor-pointer disabled:opacity-50",
|
||||
title: "Play track (streams audio)",
|
||||
disabled: is_buffering(),
|
||||
onclick: {
|
||||
let tid = track_id_owned.clone();
|
||||
// Capture output device for streaming
|
||||
let output_device = current_track
|
||||
.as_ref()
|
||||
.and_then(|t| t.preferred_output.clone());
|
||||
move |_| {
|
||||
let tid = tid.clone();
|
||||
let output_device = output_device.clone();
|
||||
async move {
|
||||
playback_result.set(None);
|
||||
playback_error.set(None);
|
||||
is_buffering.set(true);
|
||||
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
let request = StreamAudioRequest {};
|
||||
|
||||
match start_audio_stream(track_id, request).await {
|
||||
Ok(stream) => {
|
||||
// Use output device if available, otherwise fall back to default
|
||||
let device = output_device
|
||||
.map(|d| format!("{}/", d))
|
||||
.unwrap_or_else(|| "/dev/audio/default".to_string());
|
||||
|
||||
// Connect to the audio stream endpoint
|
||||
let stream_url = format!(
|
||||
"audio://stream/{}@{}{}",
|
||||
stream.session_token,
|
||||
stream.server_host,
|
||||
device,
|
||||
);
|
||||
// Open the audio stream
|
||||
#[cfg(feature = "web")]
|
||||
if let Some(window) = web_sys::window() {
|
||||
let _ = window.location().set_href(&stream_url);
|
||||
}
|
||||
#[cfg(not(feature = "web"))]
|
||||
let _ = stream_url;
|
||||
}
|
||||
Err(e) => {
|
||||
playback_error
|
||||
.set(Some(format!("Failed to start stream: {}", e)));
|
||||
show_error_modal.set(true);
|
||||
}
|
||||
}
|
||||
is_buffering.set(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "play_arrow",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#2563eb".to_string()),
|
||||
}
|
||||
if is_buffering() {
|
||||
"Buffering..."
|
||||
} else if SHOW_CONTROL_TEXT {
|
||||
"Play"
|
||||
}
|
||||
}
|
||||
|
||||
// Download button - downloads track locally
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer disabled:opacity-50",
|
||||
title: "Download track for offline playback",
|
||||
disabled: is_buffering(),
|
||||
onclick: {
|
||||
let tid = track_id_owned.clone();
|
||||
move |_| {
|
||||
let tid = tid.clone();
|
||||
async move {
|
||||
playback_result.set(None);
|
||||
playback_error.set(None);
|
||||
is_buffering.set(true);
|
||||
show_download_modal.set(true);
|
||||
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
let request = DownloadTrackRequest {};
|
||||
|
||||
match download_track(track_id, request).await {
|
||||
Ok(download) => {
|
||||
playback_result.set(Some(download));
|
||||
}
|
||||
Err(e) => {
|
||||
playback_error
|
||||
.set(Some(format!("Failed to download: {}", e)));
|
||||
}
|
||||
}
|
||||
is_buffering.set(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "download",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if is_buffering() {
|
||||
"Downloading..."
|
||||
} else if SHOW_CONTROL_TEXT {
|
||||
"Download"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fullscreen mode toggle
|
||||
button {
|
||||
class: "px-2.5 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white mr-2 pr-3 border-r border-gray-200 dark:border-[#333] cursor-pointer",
|
||||
title: if (ctx.fullscreen)() { "Exit fullscreen" } else { "Enter fullscreen" },
|
||||
onclick: move |_| ctx.fullscreen.set(!(ctx.fullscreen)()),
|
||||
Icon {
|
||||
name: if (ctx.fullscreen)() { "fullscreen_exit" } else { "fullscreen" },
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
if (ctx.fullscreen)() {
|
||||
"Exit Fullscreen"
|
||||
} else {
|
||||
"Fullscreen"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
div { class: "flex items-center gap-1 mr-2 pr-3 border-r border-gray-200 dark:border-[#333]",
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer",
|
||||
title: "Add to playlist",
|
||||
onclick: move |_| show_playlist_modal.set(true),
|
||||
Icon {
|
||||
name: "playlist_add",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Add to Playlist"
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref track) = current_track {
|
||||
{
|
||||
let track_id_for_action = track_id_owned.clone();
|
||||
match track.status {
|
||||
TrackStatus::Playing { .. } => rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-gray-100 dark:hover:bg-[#252525] rounded transition-colors flex items-center gap-1.5 text-sm text-gray-600 dark:text-[#888] hover:text-gray-900 dark:hover:text-white cursor-pointer",
|
||||
title: "Pause playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_action.clone();
|
||||
async move {
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
if let Err(e) = pause_track(track_id).await {
|
||||
error!("Failed to pause: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "pause",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#666".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Pause"
|
||||
}
|
||||
}
|
||||
},
|
||||
TrackStatus::Paused { .. } => rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 bg-green-600 hover:bg-green-500 text-white rounded transition-colors flex items-center gap-1.5 text-sm cursor-pointer",
|
||||
title: "Resume playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_action.clone();
|
||||
async move {
|
||||
let track_id: uuid::Uuid = tid.parse().unwrap_or_default();
|
||||
if let Err(e) = resume_track(track_id).await {
|
||||
error!("Failed to resume: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon { name: "play_arrow", size: 16, color: IconColor::Light }
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Resume"
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => rsx! {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let track_id_for_stop = track_id_owned.clone();
|
||||
rsx! {
|
||||
button {
|
||||
class: "px-2 py-1 hover:bg-red-100 dark:hover:bg-red-900/30 rounded transition-colors flex items-center gap-1.5 text-sm text-red-600 dark:text-red-400 cursor-pointer",
|
||||
title: "Stop playback",
|
||||
onclick: move |_| {
|
||||
let tid = track_id_for_stop.clone();
|
||||
async move {
|
||||
if let Err(e) = stop_track(tid).await {
|
||||
error!("Failed to stop: {:?}", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
Icon {
|
||||
name: "stop",
|
||||
size: 16,
|
||||
color: IconColor::Custom("#dc2626".to_string()),
|
||||
}
|
||||
if SHOW_CONTROL_TEXT {
|
||||
"Stop"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user