myx 0.4.0

A lean, beautiful terminal Spotify player
//! Search.

use super::*;
use crate::*;

pub(crate) fn spawn_search(
    webapi: Arc<Mutex<WebApi>>,
    query: String,
    tx: flume::Sender<Vec<LibItem>>,
) {
    tokio::task::spawn_blocking(move || {
        let results = match token_of(&webapi) {
            Some(token) => search_blocking(&token, &query),
            None => Vec::new(),
        };
        let _ = tx.send(results);
    });
}

pub(crate) fn search_blocking(token: &str, query: &str) -> Vec<LibItem> {
    let client = http_client();
    let url = format!(
        "{API}/search?q={}&type=track,artist,album,playlist&limit=6",
        urlencode(query)
    );
    let Some(v) = get_json(&client, &url, token) else {
        return Vec::new();
    };

    let mut out = Vec::new();

    let songs: Vec<LibItem> = v["tracks"]["items"]
        .as_array()
        .into_iter()
        .flatten()
        .filter_map(|t| {
            Some(LibItem::track(
                t["name"].as_str()?.to_string(),
                t["artists"][0]["name"].as_str().unwrap_or("").to_string(),
                t["uri"].as_str()?.to_string(),
            ))
        })
        .collect();
    let artists: Vec<LibItem> = v["artists"]["items"]
        .as_array()
        .into_iter()
        .flatten()
        .filter_map(|a| {
            Some(LibItem::ctx(
                a["name"].as_str()?.to_string(),
                String::new(),
                a["uri"].as_str()?.to_string(),
            ))
        })
        .collect();
    let albums: Vec<LibItem> = v["albums"]["items"]
        .as_array()
        .into_iter()
        .flatten()
        .filter_map(|al| {
            Some(LibItem::ctx(
                al["name"].as_str()?.to_string(),
                al["artists"][0]["name"].as_str().unwrap_or("").to_string(),
                al["uri"].as_str()?.to_string(),
            ))
        })
        .collect();
    let playlists: Vec<LibItem> = v["playlists"]["items"]
        .as_array()
        .into_iter()
        .flatten()
        .filter_map(|p| {
            Some(LibItem::ctx(
                p["name"].as_str()?.to_string(),
                playlist_subtitle(
                    p["owner"]["display_name"].as_str().unwrap_or(""),
                    playlist_total(p),
                ),
                p["uri"].as_str()?.to_string(),
            ))
        })
        .collect();

    for (title, group) in [
        ("Songs", songs),
        ("Artists", artists),
        ("Albums", albums),
        ("Playlists", playlists),
    ] {
        if !group.is_empty() {
            out.push(LibItem::header(title));
            out.extend(group);
        }
    }
    out
}