cool-spotify-blend/front/src/main.rs

145 lines
5.0 KiB
Rust

mod fetch;
mod spotify_types; // Symlinked from server because I do not want to separate this into another
// crate right now.
// This is a stupid way to do this.
use wasm_bindgen::prelude::*;
use wasm_bindgen_futures::spawn_local;
use web_sys::{Document, HtmlAnchorElement, HtmlImageElement};
use crate::spotify_types::*;
// Convenience alias
type TrackUserTuple = (TrackObject, UserProfile);
fn main() {
wasm_logger::init(wasm_logger::Config::default());
log::info!("wasm executing now :)");
spawn_local(app());
}
async fn app() {
let window = web_sys::window().expect("We have to have a window.");
let document = window.document().expect("Window should have a document.");
let body = document.body().expect("Document should have a body.");
let outer_div = generate_outer_div(&document).unwrap();
body.append_child(&outer_div).unwrap();
let data = fetch::fetch().await;
if data.is_err() {
log::error!("Could not fetch data, nothing to do.");
log::error!("{:?}", data.unwrap_err());
return (); // This is actually a graceful exit!
}
let data = data.unwrap(); // We know this is fine from above
let rows = data.iter()
.map(|row| generate_row(&document, &row))
.flatten(); // Intentionally not collecting--next step is to consume.
for row in rows {
outer_div.append_child(&row).unwrap();
}
}
fn generate_outer_div(document: &Document) -> Result<web_sys::Element, JsValue> {
let outer_div = document.create_element("div")?;
outer_div.set_class_name("outer-div");
Ok(outer_div)
}
fn generate_row(document: &Document, data: &TrackUserTuple) -> Result<web_sys::Element, JsValue> {
let container = document.create_element("div")?;
container.set_class_name("inner-div");
let track_info = generate_track_info(document, data)?;
let user_info = generate_user_info(document, data)?;
container.append_child(&track_info).unwrap();
container.append_child(&user_info).unwrap();
Ok(container)
}
fn generate_track_info(document: &Document, data: &TrackUserTuple) -> Result<web_sys::Element, JsValue> {
let track_info = document.create_element("div")?;
track_info.set_class_name("track-info");
// Scoping these to prevent accidentally referencing the wrong thing
// and to free memory sooner maybe
{
let track_name = document.create_element("p")?;
track_name.set_class_name("track_name");
let track_name_a: HtmlAnchorElement = document.create_element("a")?.dyn_into().unwrap();
track_name_a.set_text_content(Some(&data.0.name));
track_name_a.set_href(&create_track_link(&data.0.uri));
track_name.append_child(&track_name_a).unwrap();
track_info.append_child(&track_name).unwrap();
}
if let Some(album) = &data.0.album {
{
let track_album = document.create_element("p")?;
track_album.set_class_name("track_album");
let track_album_a: HtmlAnchorElement = document.create_element("a")?.dyn_into().unwrap();
track_album_a.set_text_content(Some(&album.name));
track_album_a.set_href(&create_album_link(&album.uri));
track_album.append_child(&track_album_a).unwrap();
track_info.append_child(&track_album).unwrap();
}
if let Some(image) = &album.images.get(0) {
let track_album_img: HtmlImageElement = document.create_element("img")?.dyn_into().unwrap();
track_album_img.set_alt("Album cover");
track_album_img.set_src(&image.url);
track_info.append_child(&track_album_img).unwrap();
}
}
Ok(track_info)
}
fn generate_user_info(document: &Document, data: &TrackUserTuple) -> Result<web_sys::Element, JsValue> {
let user_info = document.create_element("div")?;
user_info.set_class_name("user-info");
{
let user_name = document.create_element("p")?;
user_name.set_class_name("user_name");
let user_name_a: HtmlAnchorElement = document.create_element("a")?.dyn_into().unwrap();
if let Some(display_name) = &data.1.display_name {
user_name_a.set_text_content(Some(&display_name));
} else {
user_name_a.set_text_content(Some(&data.1.id));
}
user_name_a.set_href(&create_user_link(&data.1.id));
user_name.append_child(&user_name_a).unwrap();
user_info.append_child(&user_name).unwrap();
}
if let Some(Some(image)) = data.1.images.as_ref().map(|imgs| imgs.get(0)) {
let user_img: HtmlImageElement = document.create_element("img")?.dyn_into().unwrap();
user_img.set_alt("Profile picture");
user_img.set_src(&image.url);
user_info.append_child(&user_img).unwrap();
}
Ok(user_info)
}
fn create_track_link(uri: &Uri) -> String {
"https://open.spotify.com/track/".to_owned() + &uri.get_suffix()
}
fn create_album_link(uri: &Uri) -> String {
"https://open.spotify.com/album/".to_owned() + &uri.get_suffix()
}
fn create_user_link(id: &str) -> String {
"https://open.spotify.com/user/".to_owned() + id
}