Add ace editor light and dark theme support

This commit is contained in:
Spxg
2025-05-18 16:48:02 +08:00
parent be2832f518
commit 79cbe3b0e7
5 changed files with 84 additions and 42 deletions

View File

@@ -3,16 +3,20 @@ use reactive_stores::Store;
use wasm_bindgen::JsValue;
use web_sys::{Event, HtmlSelectElement};
use crate::{
SQLightError,
app::{
GlobalState, GlobalStateStoreFields, Orientation, Theme,
config_element::Select as SelectConfig, menu_group::MenuGroup,
},
use crate::app::{
GlobalState, GlobalStateStoreFields, Orientation, Theme,
config_element::Select as SelectConfig, menu_group::MenuGroup,
};
const ACE_KEYBOARDS: [&str; 5] = ["ace", "emacs", "sublime", "vim", "vscode"];
const ACE_THEMES: [&str; 3] = ["github", "github_dark", "gruvbox"];
const ACE_THEMES: [&str; 6] = [
"github",
"github_dark",
"github_light_default",
"gruvbox",
"gruvbox_light_hard",
"gruvbox_dark_hard",
];
fn selecet_view(s: &str, selected: &str) -> AnyView {
if s == selected {
@@ -35,32 +39,20 @@ pub fn ConfigMenu() -> impl IntoView {
if let Some(target) = event.target() {
let select = HtmlSelectElement::from(JsValue::from(target));
state.editor_config().write().keyboard = select.value();
if let Some(Err(err)) = state.editor().read().as_ref().map(|editor| {
let keyboard = select.value();
let handler = (keyboard != "ace").then_some(format!("ace/keyboard/{keyboard}"));
editor.set_keyboard_handler(handler.as_deref())
}) {
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
}
};
let ace_theme_change = move |event: Event| {
let light_ace_theme_change = move |event: Event| {
if let Some(target) = event.target() {
let select = HtmlSelectElement::from(JsValue::from(target));
state.editor_config().write().theme = select.value();
if let Some(Err(err)) = state
.editor()
.read()
.as_ref()
.map(|editor| editor.set_theme(&format!("ace/theme/{}", select.value())))
{
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
state.editor_config().write().light_theme = select.value();
}
};
let dark_ace_theme_change = move |event: Event| {
if let Some(target) = event.target() {
let select = HtmlSelectElement::from(JsValue::from(target));
state.editor_config().write().dark_theme = select.value();
}
};
@@ -90,11 +82,19 @@ pub fn ConfigMenu() -> impl IntoView {
.collect_view()
}}
</SelectConfig>
<SelectConfig name="Theme".into() on_change=ace_theme_change>
<SelectConfig name="Light Theme".into() on_change=light_ace_theme_change>
{move || {
ACE_THEMES
.into_iter()
.map(|s| selecet_view(s, &state.editor_config().read().theme))
.map(|s| selecet_view(s, &state.editor_config().read().light_theme))
.collect_view()
}}
</SelectConfig>
<SelectConfig name="Dark Theme".into() on_change=dark_ace_theme_change>
{move || {
ACE_THEMES
.into_iter()
.map(|s| selecet_view(s, &state.editor_config().read().dark_theme))
.collect_view()
}}
</SelectConfig>

View File

@@ -29,7 +29,7 @@ pub fn Editor() -> impl IntoView {
.mode("ace/mode/sql")
.theme(&format!(
"ace/theme/{}",
state.editor_config().read_untracked().theme
state.editor_config().read_untracked().light_theme
))
.keyboard(
{

View File

@@ -10,12 +10,15 @@ use wasm_bindgen::{JsCast, prelude::Closure};
use wasm_bindgen_futures::spawn_local;
use web_sys::wasm_bindgen::JsValue;
use crate::app::{
Focus,
editor::Editor,
header::Header,
output::{Output, change_focus},
state::{GlobalState, GlobalStateStoreFields, Orientation, Theme, Vfs},
use crate::{
SQLightError,
app::{
Focus,
editor::Editor,
header::Header,
output::{Output, change_focus},
state::{GlobalState, GlobalStateStoreFields, Orientation, Theme, Vfs},
},
};
use crate::{WorkerHandle, WorkerResponse, handle_state};
@@ -36,8 +39,9 @@ pub fn playground(
handle_system_theme(state);
handle_automic_orientation(state);
handle_connect_db(state);
hanlde_save_state(state);
handle_save_state(state);
handle_import_progress(state);
handle_ace_config(state);
spawn_local(handle_state(state, rx));
@@ -51,7 +55,39 @@ pub fn playground(
})
}
fn hanlde_save_state(state: Store<GlobalState>) {
fn handle_ace_config(state: Store<GlobalState>) {
Effect::new(move || {
let config = state.editor_config().read();
let keyboard = &config.keyboard;
let theme = match state.theme().read().value() {
Theme::SystemLight | Theme::Light => &config.light_theme,
Theme::SystemDark | Theme::Dark => &config.dark_theme,
Theme::System => unreachable!(),
};
if let Some(Err(err)) = state.editor().read().as_ref().map(|editor| {
let handler = (keyboard != "ace").then_some(format!("ace/keyboard/{keyboard}"));
editor.set_keyboard_handler(handler.as_deref())
}) {
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
if let Some(Err(err)) = state
.editor()
.read()
.as_ref()
.map(|editor| editor.set_theme(&format!("ace/theme/{theme}")))
{
state
.last_error()
.set(Some(SQLightError::new_ace_editor(err)));
}
});
}
fn handle_save_state(state: Store<GlobalState>) {
Effect::new(move || {
state.vfs().track();
state.editor_config().track();

View File

@@ -106,14 +106,16 @@ pub struct Exported {
#[derive(Serialize, Deserialize)]
pub struct EditorConfig {
pub keyboard: String,
pub theme: String,
pub light_theme: String,
pub dark_theme: String,
}
impl Default for EditorConfig {
fn default() -> Self {
EditorConfig {
keyboard: "ace".into(),
theme: "github".into(),
light_theme: "github".into(),
dark_theme: "github_dark".into(),
}
}
}
@@ -186,7 +188,7 @@ impl Theme {
Theme::SystemLight
}
})
.unwrap_or_else(|| Theme::SystemDark)
.unwrap_or_else(|| Theme::SystemLight)
} else {
*self
}