perf: eliminate theme switch lag by suppressing CSS transitions
Disable all CSS transitions/animations during theme toggle so color changes apply instantly instead of animating over 150ms. Also cache Tauri window module import and set color-scheme for native UI elements.
This commit is contained in:
parent
70becfd74f
commit
b4d1f4b04e
|
|
@ -123,11 +123,17 @@ impl AgentManager {
|
|||
|
||||
pub fn jre_java_path(&self, jre_key: &str) -> PathBuf {
|
||||
let dir = self.jre_dir(jre_key);
|
||||
if cfg!(windows) {
|
||||
dir.join("bin").join("java.exe")
|
||||
} else {
|
||||
dir.join("bin").join("java")
|
||||
let java_name = if cfg!(windows) { "java.exe" } else { "java" };
|
||||
let flat = dir.join("bin").join(java_name);
|
||||
if flat.exists() {
|
||||
return flat;
|
||||
}
|
||||
// macOS Adoptium JRE 8 uses Contents/Home/ layout
|
||||
let macos = dir.join("Contents").join("Home").join("bin").join(java_name);
|
||||
if macos.exists() {
|
||||
return macos;
|
||||
}
|
||||
flat
|
||||
}
|
||||
|
||||
pub fn driver_jar_path(&self, db_type: &str) -> PathBuf {
|
||||
|
|
@ -159,13 +165,16 @@ impl AgentManager {
|
|||
self.driver_jar_path(db_type).exists()
|
||||
}
|
||||
|
||||
pub fn db_type_to_agent_key(db_type: &DatabaseType) -> Option<&'static str> {
|
||||
pub fn db_type_to_agent_key(db_type: &DatabaseType, driver_profile: Option<&str>) -> Option<&'static str> {
|
||||
match db_type {
|
||||
DatabaseType::Dameng => Some("dameng"),
|
||||
DatabaseType::Kingbase => Some("kingbase"),
|
||||
DatabaseType::Vastbase => Some("vastbase"),
|
||||
DatabaseType::Goldendb => Some("goldendb"),
|
||||
DatabaseType::Oracle => Some("oracle"),
|
||||
DatabaseType::Oracle => match driver_profile {
|
||||
Some("oracle-10g") => Some("oracle-10g"),
|
||||
_ => Some("oracle"),
|
||||
},
|
||||
DatabaseType::H2 => Some("h2"),
|
||||
DatabaseType::Snowflake => Some("snowflake"),
|
||||
DatabaseType::Trino => Some("trino"),
|
||||
|
|
@ -183,11 +192,15 @@ impl AgentManager {
|
|||
}
|
||||
|
||||
pub fn is_agent_type(db_type: &DatabaseType) -> bool {
|
||||
Self::db_type_to_agent_key(db_type).is_some()
|
||||
Self::db_type_to_agent_key(db_type, None).is_some()
|
||||
}
|
||||
|
||||
pub async fn spawn(&self, db_type: &DatabaseType) -> Result<AgentDriverClient, String> {
|
||||
let key = Self::db_type_to_agent_key(db_type)
|
||||
pub async fn spawn(
|
||||
&self,
|
||||
db_type: &DatabaseType,
|
||||
driver_profile: Option<&str>,
|
||||
) -> Result<AgentDriverClient, String> {
|
||||
let key = Self::db_type_to_agent_key(db_type, driver_profile)
|
||||
.ok_or_else(|| format!("{:?} is not an agent-driven database type", db_type))?;
|
||||
|
||||
let state = self.load_state();
|
||||
|
|
@ -208,10 +221,11 @@ impl AgentManager {
|
|||
pub async fn call_daemon<T: serde::de::DeserializeOwned + Send + 'static>(
|
||||
&self,
|
||||
db_type: &DatabaseType,
|
||||
driver_profile: Option<&str>,
|
||||
method: &str,
|
||||
params: serde_json::Value,
|
||||
) -> Result<T, String> {
|
||||
let key = Self::db_type_to_agent_key(db_type)
|
||||
let key = Self::db_type_to_agent_key(db_type, driver_profile)
|
||||
.ok_or_else(|| format!("{:?} is not an agent-driven database type", db_type))?
|
||||
.to_string();
|
||||
|
||||
|
|
|
|||
|
|
@ -231,7 +231,8 @@ impl AppState {
|
|||
| DatabaseType::Kylin
|
||||
| DatabaseType::Sundb
|
||||
| DatabaseType::Gaussdb => {
|
||||
let mut client = self.agent_manager.spawn(&db_config.db_type).await?;
|
||||
let mut client =
|
||||
self.agent_manager.spawn(&db_config.db_type, db_config.driver_profile.as_deref()).await?;
|
||||
client
|
||||
.call::<serde_json::Value>(
|
||||
"connect",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ const AGENT_TYPES: &[(&str, &str)] = &[
|
|||
("vastbase", "Vastbase"),
|
||||
("goldendb", "GoldenDB"),
|
||||
("oracle", "Oracle"),
|
||||
("oracle-10g", "Oracle 10g"),
|
||||
("h2", "H2"),
|
||||
("snowflake", "Snowflake"),
|
||||
("trino", "Trino (Presto)"),
|
||||
|
|
|
|||
|
|
@ -127,6 +127,7 @@ pub async fn test_connection(state: State<'_, Arc<AppState>>, config: Connection
|
|||
.agent_manager
|
||||
.call_daemon::<serde_json::Value>(
|
||||
&config.db_type,
|
||||
config.driver_profile.as_deref(),
|
||||
"test_connection",
|
||||
serde_json::json!({
|
||||
"host": host,
|
||||
|
|
@ -238,7 +239,7 @@ pub async fn connect_db(state: State<'_, Arc<AppState>>, config: ConnectionConfi
|
|||
| DatabaseType::Kylin
|
||||
| DatabaseType::Sundb
|
||||
| DatabaseType::Gaussdb => {
|
||||
let mut client = state.agent_manager.spawn(&db_config.db_type).await?;
|
||||
let mut client = state.agent_manager.spawn(&db_config.db_type, db_config.driver_profile.as_deref()).await?;
|
||||
client
|
||||
.call::<serde_json::Value>(
|
||||
"connect",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ const isDark = computed(() => resolveAppThemeAppearance(themeMode.value, systemP
|
|||
|
||||
let mediaQuery: MediaQueryList | null = null;
|
||||
let isListeningForSystemTheme = false;
|
||||
let cachedTauriWindow: typeof import("@tauri-apps/api/window") | null = null;
|
||||
|
||||
function readSystemPrefersDark() {
|
||||
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
||||
|
|
@ -35,15 +36,34 @@ function setupSystemThemeListener() {
|
|||
}
|
||||
|
||||
function applyTheme() {
|
||||
if (typeof document !== "undefined") {
|
||||
document.documentElement.classList.toggle("dark", isDark.value);
|
||||
}
|
||||
if (typeof document === "undefined") return;
|
||||
|
||||
const doc = document.documentElement;
|
||||
const dark = isDark.value;
|
||||
|
||||
doc.classList.add("disable-transitions");
|
||||
doc.classList.toggle("dark", dark);
|
||||
doc.style.colorScheme = dark ? "dark" : "light";
|
||||
|
||||
// force reflow so the class toggle takes effect before re-enabling transitions
|
||||
doc.offsetHeight; // eslint-disable-line @typescript-eslint/no-unused-expressions
|
||||
requestAnimationFrame(() => doc.classList.remove("disable-transitions"));
|
||||
|
||||
if (!isTauriRuntime()) return;
|
||||
import("@tauri-apps/api/window").then(({ getCurrentWindow }) => {
|
||||
getCurrentWindow()
|
||||
if (cachedTauriWindow) {
|
||||
cachedTauriWindow
|
||||
.getCurrentWindow()
|
||||
.setTheme(getTauriThemeForMode(themeMode.value))
|
||||
.catch(() => {});
|
||||
});
|
||||
} else {
|
||||
import("@tauri-apps/api/window").then((mod) => {
|
||||
cachedTauriWindow = mod;
|
||||
mod
|
||||
.getCurrentWindow()
|
||||
.setTheme(getTauriThemeForMode(themeMode.value))
|
||||
.catch(() => {});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setThemeMode(mode: AppThemeMode) {
|
||||
|
|
|
|||
|
|
@ -119,6 +119,14 @@
|
|||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
html.disable-transitions,
|
||||
html.disable-transitions *,
|
||||
html.disable-transitions *::before,
|
||||
html.disable-transitions *::after {
|
||||
transition-duration: 0s !important;
|
||||
animation-duration: 0s !important;
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
|
|
|
|||
Loading…
Reference in New Issue