Add abstraction for files to make iteration on UI easier

This commit is contained in:
Lucien Greathouse
2019-09-24 14:00:48 -07:00
parent 486319407a
commit e8a5e44319
5 changed files with 99 additions and 43 deletions

View File

@@ -12,6 +12,12 @@ exclude = [
"/test-projects/**",
]
[features]
default = []
# Enable this feature to live-reload assets from the web UI.
dev-live-assets = []
[workspace]
members = [
"rojo-test",

View File

@@ -22,11 +22,10 @@ body {
justify-content: center;
}
.main {
.root {
flex: 0 0;
display: flex;
flex-direction: column;
padding: 1rem;
margin: 0 auto;
width: 100%;
max-width: 50rem;
@@ -38,19 +37,25 @@ body {
.header {
flex: 0 0;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
/*justify-content: space-around;*/
align-items: center;
margin-bottom: 1rem;
border-bottom: 1px solid #666;
}
.main {
padding: 1rem;
}
.main-logo {
flex: 0 0;
width: 20rem;
width: 10rem;
margin: 1rem;
}
.stats {
flex: 0 0 20rem;
padding: 0 1rem;
margin: 1rem;
}
.stat {
@@ -65,12 +70,13 @@ body {
.button-list {
flex: 0 0;
display: flex;
justify-content: space-around;
flex-wrap: wrap;
justify-content: center;
}
.button {
display: inline-block;
border: 1px solid #666;
padding: 0.3em 1em;
margin: 0 0.2rem;
margin: 1rem;
}

37
src/web/assets.rs Normal file
View File

@@ -0,0 +1,37 @@
use std::{fs, path::Path};
static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png");
static ICON: &[u8] = include_bytes!("../../assets/icon-32.png");
static HOME_CSS: &str = include_str!("../../assets/index.css");
macro_rules! declare_asset {
($name: ident, $path: expr) => {
pub fn $name() -> &'static str {
if cfg!(feature = "dev-live-assets") {
let file_path = Path::new(file!());
let asset_path = file_path.parent().unwrap().join($path);
println!("Reloading {}", asset_path.display());
let content = fs::read_to_string(asset_path)
.expect("Couldn't read dev live asset")
.into_boxed_str();
Box::leak(content)
} else {
static CONTENT: &str = include_str!($path);
CONTENT
}
}
};
}
declare_asset!(css, "../../assets/index.css");
pub fn logo() -> &'static [u8] {
LOGO
}
pub fn icon() -> &'static [u8] {
ICON
}

View File

@@ -1,4 +1,5 @@
mod api;
mod assets;
pub mod interface;
mod ui;
mod util;

View File

@@ -10,15 +10,12 @@ use crate::{
imfs::ImfsFetcher,
serve_session::ServeSession,
web::{
assets,
interface::{ErrorResponse, SERVER_VERSION},
util::json,
},
};
static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png");
static ICON: &[u8] = include_bytes!("../../assets/icon-32.png");
static HOME_CSS: &str = include_str!("../../assets/index.css");
pub struct UiService<F> {
serve_session: Arc<ServeSession<F>>,
}
@@ -56,46 +53,24 @@ impl<F: ImfsFetcher> UiService<F> {
fn handle_logo(&self) -> Response<Body> {
Response::builder()
.header(header::CONTENT_TYPE, "image/png")
.body(Body::from(LOGO))
.body(Body::from(assets::logo()))
.unwrap()
}
fn handle_icon(&self) -> Response<Body> {
Response::builder()
.header(header::CONTENT_TYPE, "image/png")
.body(Body::from(ICON))
.body(Body::from(assets::icon()))
.unwrap()
}
fn handle_home(&self) -> Response<Body> {
let project_name = self.serve_session.project_name().unwrap_or("<unnamed>");
let uptime = {
let elapsed = self.serve_session.start_time().elapsed();
// Round off all of our sub-second precision to make timestamps
// nicer.
let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64);
let elapsed = elapsed - just_nanos;
humantime::format_duration(elapsed).to_string()
};
let page = Self::page(html! {
<main class="main">
<header class="header">
<img class="main-logo" src="/logo.png" />
<div class="stats">
{ Self::stat_item("Server Version", SERVER_VERSION) }
{ Self::stat_item("Project", project_name) }
{ Self::stat_item("Server Uptime", uptime) }
</div>
</header>
<div class="button-list">
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
{ Self::button("View in-memory filesystem state", "/show-imfs") }
{ Self::button("View instance tree state", "/show-instances") }
</div>
</main>
let page = self.normal_page(html! {
<div class="button-list">
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
{ Self::button("View in-memory filesystem state", "/show-imfs") }
{ Self::button("View instance tree state", "/show-instances") }
</div>
});
Response::builder()
@@ -133,14 +108,45 @@ impl<F: ImfsFetcher> UiService<F> {
}
}
fn normal_page<'a>(&'a self, body: HtmlContent<'a>) -> HtmlContent<'a> {
let project_name = self.serve_session.project_name().unwrap_or("<unnamed>");
let uptime = {
let elapsed = self.serve_session.start_time().elapsed();
// Round off all of our sub-second precision to make timestamps
// nicer.
let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64);
let elapsed = elapsed - just_nanos;
humantime::format_duration(elapsed).to_string()
};
Self::page(html! {
<div class="root">
<header class="header">
<img class="main-logo" src="/logo.png" />
<div class="stats">
{ Self::stat_item("Server Version", SERVER_VERSION) }
{ Self::stat_item("Project", project_name) }
{ Self::stat_item("Server Uptime", uptime) }
</div>
</header>
<main class="main">
{ body }
</main>
</div>
})
}
fn page(body: HtmlContent<'_>) -> HtmlContent<'_> {
html! {
<html>
<head>
<title>"Rojo Live Server"</title>
<link rel="icon" type="image/png" sizes="32x32" href="/icon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1" />
<style>
{ ritz::UnescapedText::new(HOME_CSS) }
{ ritz::UnescapedText::new(assets::css()) }
</style>
</head>