mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-25 15:16:07 +00:00
Add abstraction for files to make iteration on UI easier
This commit is contained in:
@@ -12,6 +12,12 @@ exclude = [
|
|||||||
"/test-projects/**",
|
"/test-projects/**",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
|
||||||
|
# Enable this feature to live-reload assets from the web UI.
|
||||||
|
dev-live-assets = []
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"rojo-test",
|
"rojo-test",
|
||||||
|
|||||||
@@ -22,11 +22,10 @@ body {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main {
|
.root {
|
||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 1rem;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 50rem;
|
max-width: 50rem;
|
||||||
@@ -38,19 +37,25 @@ body {
|
|||||||
.header {
|
.header {
|
||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
flex-wrap: wrap;
|
||||||
|
/*justify-content: space-around;*/
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 1rem;
|
border-bottom: 1px solid #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main {
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-logo {
|
.main-logo {
|
||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
width: 20rem;
|
width: 10rem;
|
||||||
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stats {
|
.stats {
|
||||||
flex: 0 0 20rem;
|
flex: 0 0 20rem;
|
||||||
padding: 0 1rem;
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat {
|
.stat {
|
||||||
@@ -65,12 +70,13 @@ body {
|
|||||||
.button-list {
|
.button-list {
|
||||||
flex: 0 0;
|
flex: 0 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid #666;
|
border: 1px solid #666;
|
||||||
padding: 0.3em 1em;
|
padding: 0.3em 1em;
|
||||||
margin: 0 0.2rem;
|
margin: 1rem;
|
||||||
}
|
}
|
||||||
37
src/web/assets.rs
Normal file
37
src/web/assets.rs
Normal 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
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
mod api;
|
mod api;
|
||||||
|
mod assets;
|
||||||
pub mod interface;
|
pub mod interface;
|
||||||
mod ui;
|
mod ui;
|
||||||
mod util;
|
mod util;
|
||||||
|
|||||||
@@ -10,15 +10,12 @@ use crate::{
|
|||||||
imfs::ImfsFetcher,
|
imfs::ImfsFetcher,
|
||||||
serve_session::ServeSession,
|
serve_session::ServeSession,
|
||||||
web::{
|
web::{
|
||||||
|
assets,
|
||||||
interface::{ErrorResponse, SERVER_VERSION},
|
interface::{ErrorResponse, SERVER_VERSION},
|
||||||
util::json,
|
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> {
|
pub struct UiService<F> {
|
||||||
serve_session: Arc<ServeSession<F>>,
|
serve_session: Arc<ServeSession<F>>,
|
||||||
}
|
}
|
||||||
@@ -56,46 +53,24 @@ impl<F: ImfsFetcher> UiService<F> {
|
|||||||
fn handle_logo(&self) -> Response<Body> {
|
fn handle_logo(&self) -> Response<Body> {
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.header(header::CONTENT_TYPE, "image/png")
|
.header(header::CONTENT_TYPE, "image/png")
|
||||||
.body(Body::from(LOGO))
|
.body(Body::from(assets::logo()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_icon(&self) -> Response<Body> {
|
fn handle_icon(&self) -> Response<Body> {
|
||||||
Response::builder()
|
Response::builder()
|
||||||
.header(header::CONTENT_TYPE, "image/png")
|
.header(header::CONTENT_TYPE, "image/png")
|
||||||
.body(Body::from(ICON))
|
.body(Body::from(assets::icon()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_home(&self) -> Response<Body> {
|
fn handle_home(&self) -> Response<Body> {
|
||||||
let project_name = self.serve_session.project_name().unwrap_or("<unnamed>");
|
let page = self.normal_page(html! {
|
||||||
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">
|
<div class="button-list">
|
||||||
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
|
{ Self::button("Rojo Documentation", "https://rojo.space/docs") }
|
||||||
{ Self::button("View in-memory filesystem state", "/show-imfs") }
|
{ Self::button("View in-memory filesystem state", "/show-imfs") }
|
||||||
{ Self::button("View instance tree state", "/show-instances") }
|
{ Self::button("View instance tree state", "/show-instances") }
|
||||||
</div>
|
</div>
|
||||||
</main>
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Response::builder()
|
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<'_> {
|
fn page(body: HtmlContent<'_>) -> HtmlContent<'_> {
|
||||||
html! {
|
html! {
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>"Rojo Live Server"</title>
|
<title>"Rojo Live Server"</title>
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/icon.png" />
|
<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>
|
<style>
|
||||||
{ ritz::UnescapedText::new(HOME_CSS) }
|
{ ritz::UnescapedText::new(assets::css()) }
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user