Add UI performance-related settings (#6747)

This commit is contained in:
Elian Doran 2025-08-23 15:16:22 +03:00 committed by GitHub
commit 980077f559
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 107 additions and 4 deletions

View File

@ -28,6 +28,28 @@
--ck-mention-list-max-height: 500px; --ck-mention-list-max-height: 500px;
} }
body#trilium-app.motion-disabled *,
body#trilium-app.motion-disabled *::before,
body#trilium-app.motion-disabled *::after {
/* Disable transitions and animations */
transition: none !important;
animation: none !important;
}
body#trilium-app.shadows-disabled *,
body#trilium-app.shadows-disabled *::before,
body#trilium-app.shadows-disabled *::after {
/* Disable shadows */
box-shadow: none !important;
}
body#trilium-app.backdrop-effects-disabled *,
body#trilium-app.backdrop-effects-disabled *::before,
body#trilium-app.backdrop-effects-disabled *::after {
/* Disable backdrop effects */
backdrop-filter: none !important;
}
.table { .table {
--bs-table-bg: transparent !important; --bs-table-bg: transparent !important;
} }
@ -355,7 +377,7 @@ body.desktop .tabulator-popup-container {
@supports (animation-fill-mode: forwards) { @supports (animation-fill-mode: forwards) {
/* Delay the opening of submenus */ /* Delay the opening of submenus */
body.desktop .dropdown-submenu .dropdown-menu { body.desktop:not(.motion-disabled) .dropdown-submenu .dropdown-menu {
opacity: 0; opacity: 0;
animation-fill-mode: forwards; animation-fill-mode: forwards;
animation-delay: var(--submenu-opening-delay); animation-delay: var(--submenu-opening-delay);

View File

@ -89,6 +89,7 @@
--menu-text-color: #e3e3e3; --menu-text-color: #e3e3e3;
--menu-background-color: #222222d9; --menu-background-color: #222222d9;
--menu-background-color-no-backdrop: #1b1b1b;
--menu-item-icon-color: #8c8c8c; --menu-item-icon-color: #8c8c8c;
--menu-item-disabled-opacity: 0.5; --menu-item-disabled-opacity: 0.5;
--menu-item-keyboard-shortcut-color: #ffffff8f; --menu-item-keyboard-shortcut-color: #ffffff8f;

View File

@ -83,6 +83,7 @@
--menu-text-color: #272727; --menu-text-color: #272727;
--menu-background-color: #ffffffd9; --menu-background-color: #ffffffd9;
--menu-background-color-no-backdrop: #fdfdfd;
--menu-item-icon-color: #727272; --menu-item-icon-color: #727272;
--menu-item-disabled-opacity: 0.6; --menu-item-disabled-opacity: 0.6;
--menu-item-keyboard-shortcut-color: #666666a8; --menu-item-keyboard-shortcut-color: #666666a8;

View File

@ -83,6 +83,12 @@
--tab-note-icons: true; --tab-note-icons: true;
} }
body.backdrop-effects-disabled {
/* Backdrop effects are disabled, replace the menu background color with the
* no-backdrop fallback color */
--menu-background-color: var(--menu-background-color-no-backdrop);
}
/* /*
* MENUS * MENUS
* *

View File

@ -1113,6 +1113,12 @@
"layout-vertical-description": "launcher bar is on the left (default)", "layout-vertical-description": "launcher bar is on the left (default)",
"layout-horizontal-description": "launcher bar is underneath the tab bar, the tab bar is now full width." "layout-horizontal-description": "launcher bar is underneath the tab bar, the tab bar is now full width."
}, },
"ui-performance": {
"title": "Performance",
"enable-motion": "Enable transitions and animations",
"enable-shadows": "Enable shadows",
"enable-backdrop-effects": "Enable background effects for menus, popups and panels"
},
"ai_llm": { "ai_llm": {
"not_started": "Not started", "not_started": "Not started",
"title": "AI Settings", "title": "AI Settings",

View File

@ -1,6 +1,8 @@
import utils from "../../services/utils.js"; import { EventData } from "../../components/app_context.js";
import type BasicWidget from "../basic_widget.js";
import FlexContainer from "./flex_container.js"; import FlexContainer from "./flex_container.js";
import options from "../../services/options.js";
import type BasicWidget from "../basic_widget.js";
import utils from "../../services/utils.js";
/** /**
* The root container is the top-most widget/container, from which the entire layout derives. * The root container is the top-most widget/container, from which the entire layout derives.
@ -27,15 +29,45 @@ export default class RootContainer extends FlexContainer<BasicWidget> {
window.visualViewport?.addEventListener("resize", () => this.#onMobileResize()); window.visualViewport?.addEventListener("resize", () => this.#onMobileResize());
} }
this.#setMotion(options.is("motionEnabled"));
this.#setShadows(options.is("shadowsEnabled"));
this.#setBackdropEffects(options.is("backdropEffectsEnabled"));
return super.render(); return super.render();
} }
entitiesReloadedEvent({ loadResults }: EventData<"entitiesReloaded">) {
if (loadResults.isOptionReloaded("motionEnabled")) {
this.#setMotion(options.is("motionEnabled"));
}
if (loadResults.isOptionReloaded("shadowsEnabled")) {
this.#setShadows(options.is("shadowsEnabled"));
}
if (loadResults.isOptionReloaded("backdropEffectsEnabled")) {
this.#setBackdropEffects(options.is("backdropEffectsEnabled"));
}
}
#onMobileResize() { #onMobileResize() {
const currentViewportHeight = getViewportHeight(); const currentViewportHeight = getViewportHeight();
const isKeyboardOpened = (currentViewportHeight < this.originalViewportHeight); const isKeyboardOpened = (currentViewportHeight < this.originalViewportHeight);
this.$widget.toggleClass("virtual-keyboard-opened", isKeyboardOpened); this.$widget.toggleClass("virtual-keyboard-opened", isKeyboardOpened);
} }
#setMotion(enabled: boolean) {
document.body.classList.toggle("motion-disabled", !enabled);
jQuery.fx.off = !enabled;
}
#setShadows(enabled: boolean) {
document.body.classList.toggle("shadows-disabled", !enabled);
}
#setBackdropEffects(enabled: boolean) {
document.body.classList.toggle("backdrop-effects-disabled", !enabled);
}
} }
function getViewportHeight() { function getViewportHeight() {

View File

@ -88,6 +88,7 @@ export default function AppearanceSettings() {
<ApplicationTheme /> <ApplicationTheme />
{overrideThemeFonts === "true" && <Fonts />} {overrideThemeFonts === "true" && <Fonts />}
{isElectron() && <ElectronIntegration /> } {isElectron() && <ElectronIntegration /> }
<Performance />
<MaxContentWidth /> <MaxContentWidth />
<RelatedSettings items={[ <RelatedSettings items={[
{ {
@ -245,6 +246,30 @@ function ElectronIntegration() {
) )
} }
function Performance() {
const [ motionEnabled, setMotionEnabled ] = useTriliumOptionBool("motionEnabled");
const [ shadowsEnabled, setShadowsEnabled ] = useTriliumOptionBool("shadowsEnabled");
const [ backdropEffectsEnabled, setBackdropEffectsEnabled ] = useTriliumOptionBool("backdropEffectsEnabled");
return <OptionsSection title={t("ui-performance.title")}>
<FormCheckbox
label={t("ui-performance.enable-motion")}
currentValue={motionEnabled} onChange={setMotionEnabled}
/>
<FormCheckbox
label={t("ui-performance.enable-shadows")}
currentValue={shadowsEnabled} onChange={setShadowsEnabled}
/>
<FormCheckbox
label={t("ui-performance.enable-backdrop-effects")}
currentValue={backdropEffectsEnabled} onChange={setBackdropEffectsEnabled}
/>
</OptionsSection>
}
function MaxContentWidth() { function MaxContentWidth() {
const [ maxContentWidth, setMaxContentWidth ] = useTriliumOption("maxContentWidth"); const [ maxContentWidth, setMaxContentWidth ] = useTriliumOption("maxContentWidth");

View File

@ -9,7 +9,7 @@
<link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest"> <link rel="manifest" crossorigin="use-credentials" href="manifest.webmanifest">
<title>Trilium Notes</title> <title>Trilium Notes</title>
</head> </head>
<body class="desktop heading-style-<%= headingStyle %> layout-<%= layoutOrientation %> platform-<%= platform %> <%= isElectron ? 'electron' : '' %> <%= hasNativeTitleBar ? 'native-titlebar' : '' %> <%= hasBackgroundEffects ? 'background-effects' : '' %>"> <body id="trilium-app" class="desktop heading-style-<%= headingStyle %> layout-<%= layoutOrientation %> platform-<%= platform %> <%= isElectron ? 'electron' : '' %> <%= hasNativeTitleBar ? 'native-titlebar' : '' %> <%= hasBackgroundEffects ? 'background-effects' : '' %>">
<noscript><%= t("javascript-required") %></noscript> <noscript><%= t("javascript-required") %></noscript>
<script> <script>

View File

@ -63,6 +63,9 @@ const ALLOWED_OPTIONS = new Set<OptionNames>([
"dailyBackupEnabled", "dailyBackupEnabled",
"weeklyBackupEnabled", "weeklyBackupEnabled",
"monthlyBackupEnabled", "monthlyBackupEnabled",
"motionEnabled",
"shadowsEnabled",
"backdropEffectsEnabled",
"maxContentWidth", "maxContentWidth",
"compressImages", "compressImages",
"downloadImagesAutomatically", "downloadImagesAutomatically",

View File

@ -152,6 +152,10 @@ const defaultOptions: DefaultOption[] = [
}, },
isSynced: false isSynced: false
}, },
{ name: "motionEnabled", value: "true", isSynced: false },
{ name: "shadowsEnabled", value: "true", isSynced: false },
{ name: "backdropEffectsEnabled", value: "true", isSynced: false },
// Internationalization // Internationalization
{ name: "locale", value: "en", isSynced: true }, { name: "locale", value: "en", isSynced: true },

View File

@ -93,6 +93,9 @@ export interface OptionDefinitions extends KeyboardShortcutsOptions<KeyboardActi
// Appearance // Appearance
splitEditorOrientation: "horziontal" | "vertical"; splitEditorOrientation: "horziontal" | "vertical";
motionEnabled: boolean;
shadowsEnabled: boolean;
backdropEffectsEnabled: boolean;
codeNoteTheme: string; codeNoteTheme: string;
initialized: boolean; initialized: boolean;