feat(runner): enable Vim mode toggle for CodeRunner sandbox
This commit is contained in:
parent
3bb67f6673
commit
cda5a92230
@ -204,6 +204,13 @@ export class CodeMirrorInstance {
|
||||
});
|
||||
}
|
||||
|
||||
/** 热切换 Vim 模式,不重建实例(Compartment.reconfigure)。 */
|
||||
setVim(v: boolean): void {
|
||||
this.view.dispatch({
|
||||
effects: this.vimCompartment.reconfigure(v ? [vim()] : []),
|
||||
});
|
||||
}
|
||||
|
||||
/** 热切换语言(python/node/javascript/sql),不重建实例(Compartment.reconfigure)。 */
|
||||
setLanguage(lang: string): void {
|
||||
this.language = lang;
|
||||
|
||||
@ -89,6 +89,10 @@ pub mod wasm {
|
||||
#[wasm_bindgen(method, js_name = setTheme)]
|
||||
pub fn set_theme(this: &EditorInstance, theme: &str);
|
||||
|
||||
/// 热切换 Vim 模式(Compartment.reconfigure,不重建实例)。
|
||||
#[wasm_bindgen(method, js_name = setVim)]
|
||||
pub fn set_vim(this: &EditorInstance, v: bool);
|
||||
|
||||
/// 热切换语言(python/node/javascript/sql,Compartment.reconfigure)。
|
||||
/// 由 CodeRunner 组件在挂载时按 data-lang 调用。
|
||||
#[wasm_bindgen(method, js_name = setLanguage)]
|
||||
|
||||
@ -66,6 +66,34 @@ pub fn CodeRunner(
|
||||
// → 骨架屏从 DOM 移除,露出真实编辑器。
|
||||
let mut editor_ready = use_signal(|| false);
|
||||
|
||||
// Vim 模式状态(通过 localStorage 持久化偏好)
|
||||
let mut vim_enabled = use_signal(|| {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
if let Some(window) = web_sys::window() {
|
||||
if let Ok(Some(storage)) = window.local_storage() {
|
||||
if let Ok(Some(val)) = storage.get_item("yggdrasil-code-runner-vim") {
|
||||
return val == "true";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
let toggle_vim = move |_| {
|
||||
let next = !vim_enabled();
|
||||
vim_enabled.set(next);
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
if let Some(window) = web_sys::window() {
|
||||
if let Ok(Some(storage)) = window.local_storage() {
|
||||
let _ = storage.set_item("yggdrasil-code-runner-vim", &next.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// —— CodeMirror 挂载(仅 WASM)——
|
||||
// 范式镜像 src/pages/admin/system.rs 的 SQL 控制台与 src/pages/admin/write.rs 的 Tiptap。
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@ -106,6 +134,7 @@ pub fn CodeRunner(
|
||||
let opts = codemirror_bridge::EditorOptions::new();
|
||||
opts.set_language(&mount_language);
|
||||
opts.set_theme(theme_name);
|
||||
opts.set_vim(*vim_enabled.read());
|
||||
opts.set_value(&source_signal.read());
|
||||
opts.set_on_change(&on_change);
|
||||
opts.set_on_ready(&on_ready);
|
||||
@ -138,6 +167,14 @@ pub fn CodeRunner(
|
||||
}
|
||||
});
|
||||
|
||||
// 监听 vim 模式切换并同步。
|
||||
use_effect(move || {
|
||||
let enabled = vim_enabled();
|
||||
if let Some(h) = editor_handle.read().as_ref() {
|
||||
h.instance().set_vim(enabled);
|
||||
}
|
||||
});
|
||||
|
||||
// source prop 外部变更(如 admin 页面切换语言重置示例代码)同步到
|
||||
// signal + 编辑器。通过 source_prop_signal 订阅其变化。
|
||||
// 此 effect 仅读取 source_prop_signal,不读取 source_signal,避免用户编辑时误触重置回环。
|
||||
@ -241,9 +278,21 @@ pub fn CodeRunner(
|
||||
div { class: "rounded-2xl overflow-hidden border border-[var(--color-paper-border)] bg-[var(--color-paper-entry)]",
|
||||
// 顶栏:语言标签 + 运行按钮
|
||||
div { class: "flex justify-between items-center px-4 py-2.5 border-b border-[var(--color-paper-border)] bg-[var(--color-paper-theme)]",
|
||||
div { class: "flex items-center gap-2",
|
||||
div { class: "flex items-center gap-3",
|
||||
span { class: "w-2 h-2 rounded-full bg-[var(--color-paper-accent)]" }
|
||||
span { class: "font-mono text-sm font-semibold text-[var(--color-paper-primary)]", "{language}" }
|
||||
button {
|
||||
class: format!(
|
||||
"text-[10px] px-1.5 py-0.5 rounded border transition cursor-pointer {}",
|
||||
if vim_enabled() {
|
||||
"bg-[var(--color-paper-accent)]/15 text-[var(--color-paper-accent)] border-[var(--color-paper-accent)]/30 font-semibold"
|
||||
} else {
|
||||
"bg-transparent text-[var(--color-paper-tertiary)] border-[var(--color-paper-border)] hover:text-[var(--color-paper-primary)]"
|
||||
}
|
||||
),
|
||||
onclick: toggle_vim,
|
||||
"Vim"
|
||||
}
|
||||
}
|
||||
button {
|
||||
class: "inline-flex items-center gap-1.5 px-4 py-1.5 text-sm font-medium rounded-full text-[var(--color-paper-theme)] bg-[var(--color-paper-accent)] hover:brightness-110 active:scale-[0.98] transition disabled:opacity-50 disabled:cursor-not-allowed cursor-pointer",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user