Compare commits

...

3 Commits

Author SHA1 Message Date
f42985733f Add some varied default song covers 2023-09-24 01:33:55 +02:00
c6cc83018f Dockerfile from scratch 2023-09-24 01:32:46 +02:00
89cb0c475b 1.0.0 2023-09-23 23:51:07 +02:00
32 changed files with 53 additions and 7 deletions

4
Cargo.lock generated
View File

@ -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",

View File

@ -54,7 +54,7 @@ RUN trunk build --release
########################
### PRODUCTION STAGE ###
########################
FROM debian:stable-slim
FROM scratch
# Default logging level
ENV RUST_LOG="info"

View File

@ -1,6 +1,6 @@
[package]
name = "singit_srv"
version = "0.1.0"
version = "1.0.0"
authors = ["Joakim Hulthe <joakim@hulthe.net"]
edition = "2021"

View File

@ -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
View 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(())
}

View File

@ -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![

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB