Compare commits
3 Commits
95dbb74b47
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
f42985733f
|
|||
|
c6cc83018f
|
|||
|
89cb0c475b
|
4
Cargo.lock
generated
@ -1504,7 +1504,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "singit_srv"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"actix-files",
|
||||
"actix-web",
|
||||
@ -1520,7 +1520,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "singit_web"
|
||||
version = "0.2.2"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"css_typegen",
|
||||
"csv",
|
||||
|
||||
@ -54,7 +54,7 @@ RUN trunk build --release
|
||||
########################
|
||||
### PRODUCTION STAGE ###
|
||||
########################
|
||||
FROM debian:stable-slim
|
||||
FROM scratch
|
||||
|
||||
# Default logging level
|
||||
ENV RUST_LOG="info"
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "singit_srv"
|
||||
version = "0.1.0"
|
||||
version = "1.0.0"
|
||||
authors = ["Joakim Hulthe <joakim@hulthe.net"]
|
||||
edition = "2021"
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
[package]
|
||||
name = "singit_web"
|
||||
version = "0.2.2"
|
||||
version = "1.0.0"
|
||||
authors = ["Joakim Hulthe <joakim@hulthe.net"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
seed = "0.10.0"
|
||||
serde = { version = "1.0.0", features = ['derive'] }
|
||||
serde = { version = "1.0.0", features = ["derive"] }
|
||||
serde_json = "1.0.0"
|
||||
rand = "0.8.5"
|
||||
gloo-console = "0.3.0"
|
||||
|
||||
26
frontend/build.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::io;
|
||||
|
||||
fn main() {
|
||||
index_default_covers().expect("index default covers");
|
||||
}
|
||||
|
||||
/// Index all pngs in static/images/default_covers and expose the list in the build as an
|
||||
/// environment variable DEFAULT_SONG_COVERS. This list includes the path to the images so the
|
||||
/// frontend can fetch them.
|
||||
fn index_default_covers() -> io::Result<()> {
|
||||
let mut files = vec![];
|
||||
for dir in fs::read_dir("static/images/default_covers")? {
|
||||
let path = dir?.path();
|
||||
if path.extension().and_then(|s| s.to_str()) == Some("png") {
|
||||
let path = Path::new("/").join(path.strip_prefix("static").unwrap());
|
||||
files.push(path.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
let list = files.join(",");
|
||||
println!("cargo:rustc-env=DEFAULT_SONG_COVERS={list}");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -13,6 +13,8 @@ use seed::prelude::*;
|
||||
use seed::{attrs, button, div, empty, img, input, p, span, C, IF};
|
||||
use std::cmp::Reverse;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use web_sys::Element;
|
||||
|
||||
pub struct Model {
|
||||
@ -40,6 +42,9 @@ pub struct Model {
|
||||
query_placeholder_len: usize,
|
||||
|
||||
autotyper: Option<CmdHandle>,
|
||||
|
||||
/// URLs of some defaults for songs with missing cover art.
|
||||
default_song_covers: Vec<&'static str>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
@ -94,6 +99,10 @@ pub fn init(_url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
||||
orders.perform_cmd(fetch_songs());
|
||||
orders.perform_cmd(fetch_custom_song_list_index());
|
||||
|
||||
// get list of default song covers. see build.rs
|
||||
const DEFAULT_SONG_COVERS: &str = env!("DEFAULT_SONG_COVERS");
|
||||
let default_song_covers = DEFAULT_SONG_COVERS.split(',').collect();
|
||||
|
||||
Model {
|
||||
songs: vec![],
|
||||
custom_lists: Default::default(),
|
||||
@ -105,6 +114,7 @@ pub fn init(_url: Url, orders: &mut impl Orders<Msg>) -> Model {
|
||||
query_placeholder: String::from("Sök"),
|
||||
query_placeholder_len: 0,
|
||||
autotyper: Some(orders.perform_cmd_with_handle(timeout(500, || Msg::Autotyper))),
|
||||
default_song_covers,
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,6 +238,7 @@ pub fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders<Msg>) {
|
||||
}
|
||||
|
||||
pub fn view(model: &Model) -> Vec<Node<Msg>> {
|
||||
|
||||
let song_card = |song: &Song| -> Node<Msg> {
|
||||
div![
|
||||
C![C.song_item],
|
||||
@ -235,7 +246,16 @@ pub fn view(model: &Model) -> Vec<Node<Msg>> {
|
||||
C![C.song_item_cover],
|
||||
match song.cover {
|
||||
Some(_) => attrs! {At::Src => format!("/images/songs/{}.png", song.song_hash)},
|
||||
None => attrs! {At::Src => "/images/default_cover.png"},
|
||||
None => {
|
||||
// use a DefaultHasher to turn the song_hash string into a number we can
|
||||
// use to give the song a psuedo-random default cover.
|
||||
let mut hasher = DefaultHasher::new();
|
||||
song.song_hash.hash(&mut hasher);
|
||||
let hash = hasher.finish() as usize;
|
||||
let cover_i = hash % model.default_song_covers.len();
|
||||
let cover = model.default_song_covers[cover_i];
|
||||
attrs! { At::Src => cover }
|
||||
}
|
||||
},
|
||||
],
|
||||
div![
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB |
BIN
frontend/static/images/default_covers/00.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/01.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/02.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/03.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/04.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/05.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/06.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/07.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/08.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/09.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/10.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/11.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/12.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/13.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/14.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/15.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/16.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
frontend/static/images/default_covers/17.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/18.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/19.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/20.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/21.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/22.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/23.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
frontend/static/images/default_covers/24.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |