v0.2.91
This commit is contained in:
1 parent
4da41a1404
commit
5cb6960b04
31 files changed
+1611
-2123
No files matched your search
+50
-3
@@ -48,6 +48,7 @@ const MODULES: &[&str] = &[
|
||||
"theme",
|
||||
"url-state",
|
||||
"vendor-libs",
|
||||
"virtual-editor-layers",
|
||||
"security",
|
||||
"select",
|
||||
];
|
||||
@@ -73,8 +74,18 @@ pub fn render_html(
|
||||
urls.stylesheet("styles"),
|
||||
urls.stylesheet_path("libs/rustpad-player/player.css"),
|
||||
);
|
||||
let show_note_loader = matches!(entrypoint, "pad" | "note");
|
||||
let html = template
|
||||
.replace("__APP_THEME_BOOTSTRAP__", &format!("{}{}", theme_bootstrap(), language_bootstrap()))
|
||||
.replace(
|
||||
"__APP_THEME_BOOTSTRAP__",
|
||||
&format!(
|
||||
"{}{}{}",
|
||||
theme_bootstrap(),
|
||||
language_bootstrap(),
|
||||
if show_note_loader { loading_bootstrap() } else { String::new() }
|
||||
),
|
||||
)
|
||||
.replace("__APP_LOADING_OVERLAY__", if show_note_loader { loading_overlay() } else { "" })
|
||||
.replace("__APP_STYLESHEET__", &app_stylesheets)
|
||||
.replace("__APP_IMPORT_MAP__", &urls.import_map())
|
||||
.replace("__APP_ENTRYPOINT__", &urls.entrypoint(entrypoint))
|
||||
@@ -101,6 +112,39 @@ pub fn render_html(
|
||||
response
|
||||
}
|
||||
|
||||
fn loading_bootstrap() -> String {
|
||||
// Embedded critical CSS and controller are available before the external assets.
|
||||
format!(
|
||||
"<style>{}</style><script>{}</script>",
|
||||
include_str!("../static/css/boot-loading.css"),
|
||||
include_str!("../static/js/boot-loading.js"),
|
||||
)
|
||||
}
|
||||
|
||||
fn loading_overlay() -> &'static str {
|
||||
r#"<div id="app-boot-overlay" role="status" aria-live="polite" aria-label="Loading RustPad">
|
||||
<div class="app-boot-card">
|
||||
<div class="app-boot-brand" aria-label="RustPad" role="img">
|
||||
<span class="app-boot-wordmark" aria-hidden="true">RustPad</span>
|
||||
</div>
|
||||
<h2 id="app-boot-heading">Loading…</h2>
|
||||
<p id="app-boot-stage">Preparing the interface</p>
|
||||
<div id="app-boot-progress" class="app-boot-track" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-label="Startup progress">
|
||||
<div id="app-boot-progress-fill"></div>
|
||||
</div>
|
||||
<p id="app-boot-count">0 of 5 stages completed</p>
|
||||
<ol class="app-boot-steps" aria-label="Loading stages">
|
||||
<li id="app-boot-step-assets"><span>Interface</span></li>
|
||||
<li id="app-boot-step-language"><span>Language</span></li>
|
||||
<li id="app-boot-step-libraries"><span>Editor</span></li>
|
||||
<li id="app-boot-step-access"><span>Access</span></li>
|
||||
<li id="app-boot-step-files"><span>Note</span></li>
|
||||
</ol>
|
||||
<button type="button" id="app-boot-retry" hidden>Reload page</button>
|
||||
</div>
|
||||
</div>"#
|
||||
}
|
||||
|
||||
pub fn theme_bootstrap() -> &'static str {
|
||||
r#"<script>(()=>{const key="rustpad:theme",guestKey="rustpad:guest-theme",authKey="rustpad:auth-state";let theme=matchMedia("(prefers-color-scheme: light)").matches?"light":"dark";try{const signedIn=localStorage.getItem(authKey)==="1";const saved=signedIn?localStorage.getItem(key):(localStorage.getItem(guestKey)||localStorage.getItem(key));if(saved==="light"||saved==="dark")theme=saved}catch{}const root=document.documentElement;root.dataset.theme=theme;root.style.colorScheme=theme;const meta=document.querySelector('meta[name="color-scheme"]');if(meta)meta.content=theme})();</script>"#
|
||||
}
|
||||
@@ -154,13 +198,16 @@ impl<'a> AssetUrls<'a> {
|
||||
}
|
||||
|
||||
fn stylesheet_path(&self, path: &str) -> String {
|
||||
format!(r#"<link rel="stylesheet" href="{}">"#, self.url(path))
|
||||
format!(
|
||||
r#"<link rel="stylesheet" data-rustpad-shell-css href="{}">"#,
|
||||
self.url(path)
|
||||
)
|
||||
}
|
||||
|
||||
fn entrypoint(&self, name: &str) -> String {
|
||||
let entrypoint = self.url(&format!("js/{name}.js"));
|
||||
format!(
|
||||
r#"<script type="module">import {{ initI18n }} from "@rustpad/i18n";import {{ initHeaderPreferences }} from "@rustpad/preferences";import {{ initSelectControls }} from "@rustpad/select";await initI18n();initHeaderPreferences();await import("{}");initSelectControls();</script>"#,
|
||||
r#"<script type="module">const boot=window.__RUSTPAD_LOADING__;try{{const [i18n,prefs,select]=await Promise.all([import("@rustpad/i18n"),import("@rustpad/preferences"),import("@rustpad/select")]);boot?.complete("js");await i18n.initI18n();boot?.complete("language");prefs.initHeaderPreferences();await import("{}");select.initSelectControls();boot?.complete("libraries");}}catch(error){{console.error("RustPad startup failed",error);boot?.fail(error);}}</script>"#,
|
||||
escape_js_string(&entrypoint)
|
||||
)
|
||||
}
|
||||
|
||||
+2
-5
@@ -174,7 +174,7 @@ impl Config {
|
||||
"GUEST_UPLOAD_MAX_SIZE_MB",
|
||||
guest_upload_max_size_mb,
|
||||
)?,
|
||||
asset_version: env!("CARGO_PKG_VERSION").to_owned(),
|
||||
asset_version: format!("{}-ui3", env!("CARGO_PKG_VERSION")),
|
||||
http_compression: values.bool("HTTP_COMPRESSION", false)?,
|
||||
asset_cache_max_age_seconds: values
|
||||
.nonnegative_u64("ASSET_CACHE_MAX_AGE_SECONDS", 600)?,
|
||||
@@ -241,10 +241,7 @@ fn multipart_body_limit_bytes(
|
||||
file_limit.saturating_add(1024 * 1024)
|
||||
}
|
||||
|
||||
fn megabytes_to_bytes(
|
||||
name: &str,
|
||||
megabytes: u64,
|
||||
) -> Result<usize, Box<dyn std::error::Error>> {
|
||||
fn megabytes_to_bytes(name: &str, megabytes: u64) -> Result<usize, Box<dyn std::error::Error>> {
|
||||
let bytes = megabytes
|
||||
.checked_mul(1024 * 1024)
|
||||
.ok_or_else(|| format!("{name} is too large"))?;
|
||||
|
||||
Reference in new issue
Block a user