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

@@ -14,8 +14,12 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.40.1/mode-sql.min.js" integrity="sha512-dABa+YCy/MOELLU5BKnJeR/pcORL8icJNR1TBZWrRmlFoWXZEFketX6Qx/DVBkewMZC8mUOGJMJ70fwxcpIDCw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.40.1/theme-gruvbox.min.js" integrity="sha512-csAdQ+MAmg252+rlVpEgxnAzlzPBBEDzi8QSoaMyV1lJqMZuzASQUDyTpT1W2gGqrRLioKPaX0ylDwkMXxzDsw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/theme-gruvbox_dark_hard.min.js" integrity="sha512-vtJVpEfWpayOCztM++zcJm9pVjyjRKsw4Uc33y3H26ckYKPZthtxhrs4wWCuTDM1uzYbPfS8Llj41Q/71porvg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/theme-gruvbox_light_hard.min.js" integrity="sha512-qhIXgTDFC22ff43cO+ufdivWukgjh1pAZRsaqNhwHxiDMk6U8v80MkSmi5zqr+eUdDyLQ83V2xDF1qHO3rueNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.40.1/theme-github.min.js" integrity="sha512-6PQOyKN8ulKmC/NQlWnhk2Upjza1Lj9pbYD/6+gNuNG+U28jW/x9iJQJuiQkfQAFggY1sToW9va3vY4xfpsJaA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/theme-github_dark.min.js" integrity="sha512-9KPSgJ+mukvk+UY25jG7bM1hOR43Sw9jmJxc5q5aa7RAMoQeyY12PNfwwUAPhe9AtOpUA1jKsDRgxeDCXe/uMg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/theme-github_light_default.min.js" integrity="sha512-VrddWqOESYVik5j3t1Do96tsvOAP1OqhRAK5wKHD6pE6BMBbtb1VnVr2MJT4/qtk25DMMcU8kcfLqJWt5YBY+g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-emacs.min.js" integrity="sha512-1we+ZK71T6DaWp6q4BJy19k434OD9bA5Og0UfzbTYJSH/uudpJGyutzmySWFpaa9t4D6mQV+EqZSzZjuSMcWRA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.41.0/keybinding-sublime.min.js" integrity="sha512-w/39STWW/Z1LblB2XwmGduzCcCPEL1HUi220daoSjYw4d/XsSzSQm+2no518nufpy5mKKTChZ50oQ9YQE/zDNg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

View File

@@ -3,16 +3,20 @@ use reactive_stores::Store;
use wasm_bindgen::JsValue;
use web_sys::{Event, HtmlSelectElement};
use crate::{
SQLightError,
app::{
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::{
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
}