diff --git a/Cargo.lock b/Cargo.lock index 770e06e..5fdc20d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1897,6 +1897,7 @@ dependencies = [ "rocket 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "scheduled-thread-pool 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tantivy 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/plume-models/Cargo.toml b/plume-models/Cargo.toml index d79a098..ba899cc 100644 --- a/plume-models/Cargo.toml +++ b/plume-models/Cargo.toml @@ -18,6 +18,7 @@ rocket = "0.4.0" reqwest = "0.9" scheduled-thread-pool = "0.2.0" serde = "1.0" +serde_derive = "1.0" serde_json = "1.0" tantivy = "0.8.2" url = "1.7" diff --git a/plume-models/src/config.rs b/plume-models/src/config.rs index 97344b4..602ae88 100644 --- a/plume-models/src/config.rs +++ b/plume-models/src/config.rs @@ -1,4 +1,4 @@ -use std::env::var; +use std::env::{self, var}; use rocket::Config as RocketConfig; use rocket::config::Limits; @@ -9,10 +9,11 @@ const DB_NAME: &str = "plume_tests"; pub struct Config { pub base_url: String, - pub db_name: &'static str, pub database_url: String, + pub db_name: &'static str, pub search_index: String, pub rocket: Result, + pub logo: LogoConfig, } #[derive(Debug,Clone)] @@ -42,6 +43,128 @@ fn get_rocket_config() -> Result { Ok(c) } +pub struct LogoConfig { + pub main: String, + pub favicon: String, + pub other: Vec //url, size, type +} + +#[derive(Serialize)] +pub struct Icon { + pub src: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub sizes: Option, + #[serde(skip_serializing_if = "Option::is_none")] + #[serde(rename = "type")] + pub image_type: Option, +} + +impl Icon { + pub fn with_prefix(&self, prefix: &str) -> Icon { + Icon { + src: format!("{}/{}", prefix, self.src), + sizes: self.sizes.clone(), + image_type: self.image_type.clone(), + } + } +} + + + +impl Default for LogoConfig { + fn default() -> Self { + let to_icon = |(src, sizes, image_type): &(&str, Option<&str>, Option<&str>)| Icon { + src: str::to_owned(src), + sizes: sizes.map(str::to_owned), + image_type: image_type.map(str::to_owned) + }; + let icons = [ + ( + "icons/trwnh/feather/plumeFeather48.png", + Some("48x48"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather72.png", + Some("72x72"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather96.png", + Some("96x96"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather144.png", + Some("144x144"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather160.png", + Some("160x160"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather192.png", + Some("192x192"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather256.png", + Some("256x256"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather512.png", + Some("512x512"), + Some("image/png"), + ), + ( + "icons/trwnh/feather/plumeFeather.svg", + None, + None, + ) + ].iter().map(to_icon).collect(); + + let custom_main = var("PLUME_LOGO").ok(); + let custom_favicon = var("PLUME_LOGO_FAVICON").ok().or_else(|| custom_main.clone()); + let other = if let Some(main) = custom_main.clone() { + let ext = |path: &str| match path.rsplitn(2, '.').next() { + Some("png") => Some("image/png".to_owned()), + Some("jpg")| Some("jpeg") => Some("image/jpeg".to_owned()), + Some("svg") => Some("image/svg+xml".to_owned()), + Some("webp") => Some("image/webp".to_owned()), + _ => None, + }; + let mut custom_icons = env::vars() + .filter_map(|(var, val)| if var.starts_with("PLUME_LOGO_") { + Some((var[11..].to_owned(), val)) + } else { None }) + .filter_map(|(var, val)| var.parse::().ok().map(|var| (var,val))) + .map(|(dim,src)| Icon { + image_type: ext(&src), + src, + sizes: Some(format!("{}x{}", dim, dim)), + }) + .collect::>(); + custom_icons.push(Icon { + image_type: ext(&main), + src: main, + sizes: None, + }); + custom_icons + } else { + icons + }; + + LogoConfig { + main: custom_main.unwrap_or_else(|| "icons/trwnh/feather/plumeFeather256.png".to_owned()), + favicon: custom_favicon.unwrap_or_else(|| "icons/trwnh/feather-filled/plumeFeatherFilled64.png".to_owned()), + other, + } + } +} + lazy_static! { pub static ref CONFIG: Config = Config { base_url: var("BASE_URL").unwrap_or_else(|_| format!( @@ -60,6 +183,7 @@ lazy_static! { DB_NAME )), search_index: var("SEARCH_INDEX").unwrap_or_else(|_| "search_index".to_owned()), - rocket: get_rocket_config() + rocket: get_rocket_config(), + logo: LogoConfig::default(), }; } diff --git a/plume-models/src/lib.rs b/plume-models/src/lib.rs index 18f3996..654afd3 100644 --- a/plume-models/src/lib.rs +++ b/plume-models/src/lib.rs @@ -1,5 +1,6 @@ #![feature(try_trait)] #![feature(never_type)] +#![feature(custom_attribute)] extern crate activitypub; extern crate ammonia; @@ -22,6 +23,8 @@ extern crate rocket; extern crate scheduled_thread_pool; extern crate serde; #[macro_use] +extern crate serde_derive; +#[macro_use] extern crate serde_json; #[macro_use] extern crate tantivy; diff --git a/src/routes/instance.rs b/src/routes/instance.rs index b4e3a47..8fb97ad 100644 --- a/src/routes/instance.rs +++ b/src/routes/instance.rs @@ -11,9 +11,9 @@ use inbox::{Inbox, SignedJson}; use plume_common::activity_pub::sign::{verify_http_headers, Signable}; use plume_models::{ admin::Admin, comments::Comment, db_conn::DbConn, headers::Headers, instance::*, posts::Post, - safe_string::SafeString, users::User, Error, + safe_string::SafeString, users::User, Error, CONFIG }; -use routes::{errors::ErrorPage, Page}; +use routes::{errors::ErrorPage, Page, rocket_uri_macro_static_files}; use template_utils::Ructe; use Searcher; @@ -326,50 +326,8 @@ pub fn web_manifest(conn: DbConn) -> Result, ErrorPage> "background_color": String::from("#f4f4f4"), "theme_color": String::from("#7765e3"), "categories": [String::from("social")], - "icons": [ - { - "src": "/static/icons/trwnh/feather/plumeFeather48.png", - "sizes": "48x48", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather72.png", - "sizes": "72x72", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather96.png", - "sizes": "96x96", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather144.png", - "sizes": "144x144", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather160.png", - "sizes": "160x160", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather256.png", - "sizes": "256x256", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "/static/icons/trwnh/feather/plumeFeather.svg" - } - ] + "icons": CONFIG.logo.other.iter() + .map(|i| i.with_prefix(&uri!(static_files: file = "").to_string())) + .collect::>() }))) } diff --git a/templates/base.rs.html b/templates/base.rs.html index 4eeeced..b0840e8 100644 --- a/templates/base.rs.html +++ b/templates/base.rs.html @@ -1,3 +1,4 @@ +@use plume_models::CONFIG; @use template_utils::*; @use routes::*; @(ctx: BaseContext, title: String, head: Content, header: Content, content: Content) @@ -11,7 +12,7 @@ - + @:head() @@ -22,7 +23,7 @@