diff --git a/src/components/menus/dashboard/shortcuts/buttons/SettingsButton.tsx b/src/components/menus/dashboard/shortcuts/buttons/SettingsButton.tsx
index ab1070b..c74d4e1 100644
--- a/src/components/menus/dashboard/shortcuts/buttons/SettingsButton.tsx
+++ b/src/components/menus/dashboard/shortcuts/buttons/SettingsButton.tsx
@@ -1,4 +1,5 @@
import { App, Gdk } from 'astal/gtk3';
+import { SettingsDialogLoader } from 'src/components/settings/lazyLoader';
export const SettingsButton = (): JSX.Element => {
return (
@@ -6,7 +7,7 @@ export const SettingsButton = (): JSX.Element => {
className={'dashboard-button'}
tooltipText={'HyprPanel Configuration'}
vexpand
- onButtonPressEvent={(_, event) => {
+ onButtonPressEvent={async (_, event) => {
const buttonClicked = event.get_button()[1];
if (buttonClicked !== Gdk.BUTTON_PRIMARY) {
@@ -14,7 +15,8 @@ export const SettingsButton = (): JSX.Element => {
}
App.get_window('dashboardmenu')?.set_visible(false);
- App.toggle_window('settings-dialog');
+ const loader = SettingsDialogLoader.getInstance();
+ await loader.toggle();
}}
>
diff --git a/src/components/settings/lazyLoader.ts b/src/components/settings/lazyLoader.ts
new file mode 100644
index 0000000..567bf72
--- /dev/null
+++ b/src/components/settings/lazyLoader.ts
@@ -0,0 +1,91 @@
+import { App } from 'astal/gtk3';
+import { Timer } from 'src/lib/performance/timer';
+
+/**
+ * Manages lazy loading of the settings dialog to improve startup performance.
+ * The dialog is only created when first accessed, not during app initialization.
+ */
+export class SettingsDialogLoader {
+ private static _instance: SettingsDialogLoader | null = null;
+ private _settingsDialog: JSX.Element | null = null;
+ private _loadPromise: Promise | null = null;
+
+ private constructor() {}
+
+ /**
+ * Gets the singleton instance of the settings dialog loader
+ */
+ public static getInstance(): SettingsDialogLoader {
+ if (!SettingsDialogLoader._instance) {
+ SettingsDialogLoader._instance = new SettingsDialogLoader();
+ }
+ return SettingsDialogLoader._instance;
+ }
+
+ /**
+ * Preloads the settings dialog
+ */
+ public static async preload(): Promise {
+ const instance = SettingsDialogLoader.getInstance();
+ await instance._getDialog();
+ }
+
+ /**
+ * Loads and returns the settings dialog, creating it if necessary.
+ * Multiple concurrent calls will share the same loading promise.
+ */
+ private async _getDialog(): Promise {
+ if (this._settingsDialog) {
+ return this._settingsDialog;
+ }
+
+ if (this._loadPromise) {
+ return this._loadPromise;
+ }
+
+ this._loadPromise = this._loadSettingsDialog();
+
+ try {
+ this._settingsDialog = await this._loadPromise;
+ return this._settingsDialog;
+ } finally {
+ this._loadPromise = null;
+ }
+ }
+
+ /**
+ * Performs the actual loading of the settings dialog module
+ */
+ private async _loadSettingsDialog(): Promise {
+ const { default: options } = await import('src/configuration');
+ const isLazyLoading = options.hyprpanel.useLazyLoading.get();
+ const timerLabel = isLazyLoading ? 'Lazy loading settings dialog' : 'Preloading settings dialog';
+ const timer = new Timer(timerLabel);
+
+ try {
+ const { default: SettingsDialog } = await import('./index');
+ const dialog = SettingsDialog();
+ timer.end();
+ return dialog;
+ } catch (error) {
+ timer.end();
+ throw new Error(`Failed to load settings dialog: ${error}`);
+ }
+ }
+
+ /**
+ * Toggles the settings dialog visibility, loading it if necessary
+ */
+ public async toggle(): Promise {
+ await this._getDialog();
+ App.toggle_window('settings-dialog');
+ }
+}
+
+/**
+ * Convenience function to toggle the settings dialog
+ */
+export async function toggleSettingsDialog(): Promise {
+ const loader = SettingsDialogLoader.getInstance();
+ await loader.toggle();
+}
diff --git a/src/components/settings/pages/config/general/index.tsx b/src/components/settings/pages/config/general/index.tsx
index 9e804d3..a123aa9 100644
--- a/src/components/settings/pages/config/general/index.tsx
+++ b/src/components/settings/pages/config/general/index.tsx
@@ -48,6 +48,15 @@ export const BarGeneral = (): JSX.Element => {
subtitle="Command executed when restarting. Use '-b busName' flag if needed."
type="string"
/>
+