Compare commits
No commits in common. "main" and "v0.1.1" have entirely different histories.
|
@ -1,3 +1,2 @@
|
||||||
/target
|
/target
|
||||||
.env
|
.env
|
||||||
dist/
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cool_spotify_server"
|
name = "cool_spotify_server"
|
||||||
version = "0.1.1"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
|
@ -620,17 +620,6 @@ dependencies = [
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "front"
|
name = "front"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
|
||||||
"gloo-net",
|
|
||||||
"js-sys",
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"wasm-logger",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
|
@ -705,40 +694,6 @@ dependencies = [
|
||||||
"wasi",
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gloo-net"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3000ef231a67d5bfee6b35f2c0f6f5c8d45b3381ef5bbbea603690ec4e539762"
|
|
||||||
dependencies = [
|
|
||||||
"futures-channel",
|
|
||||||
"futures-core",
|
|
||||||
"futures-sink",
|
|
||||||
"gloo-utils",
|
|
||||||
"http",
|
|
||||||
"js-sys",
|
|
||||||
"pin-project",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"thiserror",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"wasm-bindgen-futures",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gloo-utils"
|
|
||||||
version = "0.1.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e"
|
|
||||||
dependencies = [
|
|
||||||
"js-sys",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.20"
|
version = "0.3.20"
|
||||||
|
@ -1313,26 +1268,6 @@ version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842"
|
|
||||||
dependencies = [
|
|
||||||
"pin-project-internal",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-internal"
|
|
||||||
version = "1.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.22",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.9"
|
version = "0.2.9"
|
||||||
|
@ -2158,17 +2093,6 @@ version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasm-logger"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "074649a66bb306c8f2068c9016395fa65d8e08d2affcbf95acf3c24c3ab19718"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"wasm-bindgen",
|
|
||||||
"web-sys",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.64"
|
version = "0.3.64"
|
||||||
|
|
|
@ -6,27 +6,3 @@ edition = "2021"
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
wasm-bindgen = "0.2.74"
|
|
||||||
js-sys = "0.3.51"
|
|
||||||
wasm-bindgen-futures = "0.4.24"
|
|
||||||
|
|
||||||
gloo-net = { version = "0.3", features = ["http"] }
|
|
||||||
|
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
|
||||||
serde_json = "1.0"
|
|
||||||
|
|
||||||
log = "0.4"
|
|
||||||
wasm-logger = "0.2"
|
|
||||||
|
|
||||||
[dependencies.web-sys]
|
|
||||||
version = "0.3.4"
|
|
||||||
features = [
|
|
||||||
'Window',
|
|
||||||
'Document',
|
|
||||||
'Element',
|
|
||||||
'HtmlElement',
|
|
||||||
'Node',
|
|
||||||
'HtmlAnchorElement',
|
|
||||||
'HtmlImageElement',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[build]
|
|
||||||
release = true
|
|
||||||
public_url = "/cool-stuff/cool-spotify-blend/"
|
|
|
@ -1,86 +0,0 @@
|
||||||
@use "sass:math";
|
|
||||||
|
|
||||||
$card-height: 8vh;
|
|
||||||
$card-gap: 1.5vh;
|
|
||||||
|
|
||||||
body {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
font-family: sans-serif;
|
|
||||||
color: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
}
|
|
||||||
|
|
||||||
.outer-div {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner-div {
|
|
||||||
height: $card-height;
|
|
||||||
margin-top: ($card-gap * 0.5);
|
|
||||||
margin-bottom: ($card-gap * 0.5);
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
|
|
||||||
|
|
||||||
&:nth-child(odd) {
|
|
||||||
background: #e0e0e0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.track-info {
|
|
||||||
height: 100%;
|
|
||||||
width: 70%;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: ($card-height * 1.1) 1fr;
|
|
||||||
grid-template-rows: 1fr 1fr;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: $card-height;
|
|
||||||
grid-column: 1 / 2;
|
|
||||||
grid-row: 1 / span 2;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.track_name {
|
|
||||||
grid-column: 2 / span 1;
|
|
||||||
grid-row: 1 / span 1;
|
|
||||||
}
|
|
||||||
.track_album {
|
|
||||||
grid-column: 2 / span 1;
|
|
||||||
grid-row: 2 / span 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-info {
|
|
||||||
height: 100%;
|
|
||||||
width: 30%;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: $card-height;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
margin: 0;
|
|
||||||
margin-right: ($card-height * 0.1);
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<link data-trunk rel="scss" href="assets/scss/index.scss">
|
|
||||||
<title>Cool Spotify Blend</title>
|
|
||||||
</head>
|
|
||||||
</html>
|
|
|
@ -1,11 +0,0 @@
|
||||||
use gloo_net::http::Request;
|
|
||||||
|
|
||||||
use crate::spotify_types::*;
|
|
||||||
|
|
||||||
pub async fn fetch() -> Result<Vec<(TrackObject, UserProfile)>, gloo_net::Error> {
|
|
||||||
Ok(Request::get("https://spotify.api.ilia.moe/status")
|
|
||||||
.send()
|
|
||||||
.await?
|
|
||||||
.json()
|
|
||||||
.await?)
|
|
||||||
}
|
|
|
@ -1,144 +1,3 @@
|
||||||
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() {
|
fn main() {
|
||||||
wasm_logger::init(wasm_logger::Config::default());
|
println!("Hello, world!");
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
../../server/src/spotify_types.rs
|
|
|
@ -22,7 +22,6 @@ pub struct AlbumObject {
|
||||||
pub release_date: String,
|
pub release_date: String,
|
||||||
pub uri: Uri,
|
pub uri: Uri,
|
||||||
pub genres: Option<String>,
|
pub genres: Option<String>,
|
||||||
pub images: Vec<ImageObject>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
@ -52,9 +51,9 @@ pub struct SpotifyId(pub String);
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub struct UserProfile {
|
pub struct UserProfile {
|
||||||
pub id: String,
|
id: String,
|
||||||
pub display_name: Option<String>,
|
display_name: Option<String>,
|
||||||
pub images: Option<Vec<ImageObject>>,
|
images: Option<Vec<ImageObject>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||||
|
|
Loading…
Reference in New Issue