feat(terminal): add runtime renderer switch
This commit is contained in:
@@ -1,22 +1,91 @@
|
||||
use leptos::prelude::*;
|
||||
|
||||
use crate::components::layout::{AdminShell, Breadcrumb};
|
||||
use crate::terminal::{TerminalPanel, TerminalRenderEvent};
|
||||
use crate::terminal::{Renderer, TerminalOptions, TerminalPanel, TerminalRenderEvent};
|
||||
|
||||
#[component]
|
||||
pub fn TerminalPage() -> impl IntoView {
|
||||
let renderer = RwSignal::new(initial_terminal_renderer());
|
||||
let terminal_options = Signal::derive(move || TerminalOptions {
|
||||
renderer: renderer.get(),
|
||||
..TerminalOptions::default()
|
||||
});
|
||||
let on_render = Callback::new(update_terminal_bench_probe);
|
||||
|
||||
view! {
|
||||
<AdminShell>
|
||||
<Breadcrumb current="浏览器终端" />
|
||||
<section class="cowa-work-surface terminal-page-shell">
|
||||
<TerminalPanel on_render=on_render />
|
||||
<TerminalRendererSwitch renderer=renderer />
|
||||
<TerminalPanel options=terminal_options on_render=on_render />
|
||||
</section>
|
||||
</AdminShell>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn TerminalRendererSwitch(renderer: RwSignal<Renderer>) -> impl IntoView {
|
||||
view! {
|
||||
<div class="terminal-page-toolbar" role="toolbar" aria-label="终端渲染器">
|
||||
<span class="terminal-renderer-label">"Renderer"</span>
|
||||
<RendererButton renderer=renderer value=Renderer::WebGl label="WebGL" />
|
||||
<RendererButton renderer=renderer value=Renderer::Canvas label="Canvas" />
|
||||
<RendererButton renderer=renderer value=Renderer::Dom label="DOM" />
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
#[component]
|
||||
fn RendererButton(
|
||||
renderer: RwSignal<Renderer>,
|
||||
value: Renderer,
|
||||
label: &'static str,
|
||||
) -> impl IntoView {
|
||||
view! {
|
||||
<button
|
||||
type="button"
|
||||
class="terminal-renderer-option"
|
||||
class=("is-active", move || renderer.get() == value)
|
||||
aria-pressed=move || (renderer.get() == value).to_string()
|
||||
on:click=move |_| renderer.set(value)
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn initial_terminal_renderer() -> Renderer {
|
||||
web_sys::window()
|
||||
.and_then(|window| window.location().search().ok())
|
||||
.and_then(|query| renderer_from_query(&query))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn initial_terminal_renderer() -> Renderer {
|
||||
Renderer::default()
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "wasm32", test))]
|
||||
fn renderer_from_query(query: &str) -> Option<Renderer> {
|
||||
query
|
||||
.trim_start_matches('?')
|
||||
.split('&')
|
||||
.filter_map(|part| part.split_once('='))
|
||||
.find_map(|(key, value)| (key == "renderer").then(|| parse_renderer(value)).flatten())
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "wasm32", test))]
|
||||
fn parse_renderer(value: &str) -> Option<Renderer> {
|
||||
match value.to_ascii_lowercase().as_str() {
|
||||
"webgl" | "web-gl" => Some(Renderer::WebGl),
|
||||
"canvas" | "canvas2d" | "canvas-2d" => Some(Renderer::Canvas),
|
||||
"dom" => Some(Renderer::Dom),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn update_terminal_bench_probe(event: TerminalRenderEvent) {
|
||||
use wasm_bindgen::JsValue;
|
||||
@@ -87,3 +156,28 @@ fn update_terminal_bench_probe(event: TerminalRenderEvent) {
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn update_terminal_bench_probe(_event: TerminalRenderEvent) {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn renderer_query_parses_supported_values() {
|
||||
assert_eq!(
|
||||
renderer_from_query("?renderer=webgl"),
|
||||
Some(Renderer::WebGl)
|
||||
);
|
||||
assert_eq!(
|
||||
renderer_from_query("?foo=1&renderer=canvas2d"),
|
||||
Some(Renderer::Canvas)
|
||||
);
|
||||
assert_eq!(renderer_from_query("?renderer=dom"), Some(Renderer::Dom));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renderer_query_ignores_unknown_values() {
|
||||
assert_eq!(renderer_from_query("?renderer=auto"), None);
|
||||
assert_eq!(renderer_from_query("?other=webgl"), None);
|
||||
assert_eq!(renderer_from_query(""), None);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user