Allow clicking on queue items to change songs
Some checks reported errors
continuous-integration/drone/push Build was killed

This commit is contained in:
Sijmen 2024-01-05 17:43:11 +01:00
parent 69a1ca0a6c
commit 20bc6352b6
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
5 changed files with 32 additions and 12 deletions

View file

@ -15,6 +15,7 @@ pub fn host() -> String {
pub struct QueueItem { pub struct QueueItem {
pub id: u32, pub id: u32,
pub position: i32,
pub file: String, pub file: String,
pub title: String, pub title: String,
pub artist: Option<String>, pub artist: Option<String>,
@ -249,15 +250,20 @@ impl Mpd {
Ok(()) Ok(())
} }
pub async fn add_pos(&mut self, path: &str, pos: &str) -> anyhow::Result<()> { pub async fn add_position(&mut self, path: &str, position: &str) -> anyhow::Result<()> {
let path = Self::escape_str(path); let path = Self::escape_str(path);
let pos = Self::escape_str(pos); let position = Self::escape_str(position);
self.command(&format!(r#"add "{path}" "{pos}""#)).await?; self.command(&format!(r#"add "{path}" "{position}""#))
.await?;
Ok(()) Ok(())
} }
pub async fn play(&mut self) -> anyhow::Result<()> { pub async fn play(&mut self, position: Option<&str>) -> anyhow::Result<()> {
self.command("play").await?; let command = match position {
Some(position) => format!(r#"play "{position}""#),
None => "play".into(),
};
self.command(&command).await?;
Ok(()) Ok(())
} }
@ -352,6 +358,7 @@ impl Mpd {
.iter() .iter()
.map(|song| QueueItem { .map(|song| QueueItem {
id: song["Id"].parse().unwrap(), id: song["Id"].parse().unwrap(),
position: song["Pos"].parse().unwrap(),
file: song["file"].clone(), file: song["file"].clone(),
title: song.get("Title").unwrap_or(&song["file"]).clone(), title: song.get("Title").unwrap_or(&song["file"]).clone(),
artist: song.get("Artist").cloned(), artist: song.get("Artist").cloned(),

View file

@ -1,4 +1,5 @@
use actix_web::{post, HttpResponse, Responder}; use actix_web::{post, web, HttpResponse, Responder};
use serde::Deserialize;
use crate::mpd; use crate::mpd;
@ -13,9 +14,16 @@ async fn toggle_setting(setting: &str) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
#[derive(Deserialize)]
struct PostPlayQuery {
#[serde(default)]
position: Option<String>,
}
#[post("/play")] #[post("/play")]
pub async fn post_play() -> impl Responder { pub async fn post_play(query: web::Query<PostPlayQuery>) -> impl Responder {
mpd::command("play").await.unwrap(); let mut mpd = mpd::get_instance().await;
mpd.play(query.position.as_deref()).await.unwrap();
HttpResponse::NoContent() HttpResponse::NoContent()
} }

View file

@ -38,13 +38,13 @@ pub async fn post_queue(query: web::Query<PostQueueQuery>) -> impl Responder {
} }
if query.next { if query.next {
mpd.add_pos(&path, "+0").await.unwrap(); mpd.add_position(&path, "+0").await.unwrap();
} else { } else {
mpd.add(&path).await.unwrap(); mpd.add(&path).await.unwrap();
} }
if query.play { if query.play {
mpd.play().await.unwrap(); mpd.play(None).await.unwrap();
} }
HttpResponse::NoContent() HttpResponse::NoContent()

View file

@ -105,7 +105,7 @@ ul {
border-radius: .25rem; border-radius: .25rem;
display: flex; display: flex;
align-items: center; align-items: center;
cursor: move; cursor: grab;
} }
.queue ul li:hover { .queue ul li:hover {
background-color: #223; background-color: #223;

View file

@ -3,7 +3,12 @@
<ul> <ul>
{% for item in queue %} {% for item in queue %}
<li {% if item.playing %}class="playing"{% endif %}> <li
{% if item.playing %}class="playing"{% endif %}
hx-post="/play?position={{ item.position|urlencode }}"
hx-trigger="click,keyup[key='Enter']"
hx-swap="none"
>
<div class="albumart"> <div class="albumart">
<img <img
src="/art?path={{ item.file|urlencode }}" src="/art?path={{ item.file|urlencode }}"