configurable native menu

This commit is contained in:
Jan Prochazka 2022-02-12 10:01:40 +01:00
parent f11d3e134b
commit a1f5d1f230
8 changed files with 57 additions and 29 deletions

View File

@ -15,7 +15,8 @@ const path = require('path');
const url = require('url'); const url = require('url');
const mainMenuDefinition = require('./mainMenuDefinition'); const mainMenuDefinition = require('./mainMenuDefinition');
let isNativeMenu = true; let useNativeMenu = true;
let useNativeMenuSpecified = null;
// require('@electron/remote/main').initialize(); // require('@electron/remote/main').initialize();
@ -184,6 +185,9 @@ ipcMain.on('set-title', async (event, arg) => {
ipcMain.on('open-link', async (event, arg) => { ipcMain.on('open-link', async (event, arg) => {
electron.shell.openExternal(arg); electron.shell.openExternal(arg);
}); });
ipcMain.on('set-use-native-menu', async (event, arg) => {
useNativeMenuSpecified = arg;
});
ipcMain.on('window-action', async (event, arg) => { ipcMain.on('window-action', async (event, arg) => {
switch (arg) { switch (arg) {
case 'minimize': case 'minimize':
@ -226,23 +230,28 @@ ipcMain.handle('showItemInFolder', async (event, path) => {
ipcMain.handle('openExternal', async (event, url) => { ipcMain.handle('openExternal', async (event, url) => {
electron.shell.openExternal(url); electron.shell.openExternal(url);
}); });
ipcMain.handle('isNativeMenu', async () => { ipcMain.handle('useNativeMenu', async () => {
return isNativeMenu; return useNativeMenu;
}); });
function createWindow() { function createWindow() {
const bounds = initialConfig['winBounds']; const bounds = initialConfig['winBounds'];
isNativeMenu = os.platform() == 'darwin' ? true : false; useNativeMenu = os.platform() == 'darwin' ? true : false;
if (initialConfig['menuStyle'] == 'native') isNativeMenu = true; if (initialConfig['useNativeMenu'] === true) {
if (initialConfig['menuStyle'] == 'client') isNativeMenu = false; useNativeMenu = true;
// isNativeMenu = true; useNativeMenuSpecified = true;
}
if (initialConfig['useNativeMenu'] === false) {
useNativeMenu = false;
useNativeMenuSpecified = false;
}
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 1200, width: 1200,
height: 800, height: 800,
title: 'DbGate', title: 'DbGate',
frame: isNativeMenu, frame: useNativeMenu,
titleBarStyle: isNativeMenu ? undefined : 'hidden', titleBarStyle: useNativeMenu ? undefined : 'hidden',
...bounds, ...bounds,
icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'), icon: os.platform() == 'win32' ? 'icon.ico' : path.resolve(__dirname, '../icon.png'),
webPreferences: { webPreferences: {
@ -274,6 +283,7 @@ function createWindow() {
JSON.stringify({ JSON.stringify({
winBounds: mainWindow.getBounds(), winBounds: mainWindow.getBounds(),
winIsMaximized: mainWindow.isMaximized(), winIsMaximized: mainWindow.isMaximized(),
useNativeMenu: useNativeMenuSpecified,
}), }),
'utf-8' 'utf-8'
); );

View File

@ -45,7 +45,9 @@ module.exports = [
{ command: 'app.toggleDevTools', hideDisabled: true }, { command: 'app.toggleDevTools', hideDisabled: true },
{ command: 'app.toggleFullScreen', hideDisabled: true }, { command: 'app.toggleFullScreen', hideDisabled: true },
{ command: 'app.minimize', hideDisabled: true }, { command: 'app.minimize', hideDisabled: true },
{ divider: true },
{ command: 'theme.changeTheme', hideDisabled: true }, { command: 'theme.changeTheme', hideDisabled: true },
{ command: 'settings.show' },
], ],
}, },
{ {

View File

@ -16,7 +16,8 @@
import { subscribePermissionCompiler } from './utility/hasPermission'; import { subscribePermissionCompiler } from './utility/hasPermission';
import { apiCall } from './utility/api'; import { apiCall } from './utility/api';
import { getUsedApps } from './utility/metadataLoaders'; import { getUsedApps } from './utility/metadataLoaders';
import AppTitleProvider from './utility/AppTitleProvider.svelte'; import AppTitleProvider from './utility/AppTitleProvider.svelte';
import { initTitleBarVisibility } from './utility/common';
let loadedApi = false; let loadedApi = false;
@ -26,6 +27,8 @@ import AppTitleProvider from './utility/AppTitleProvider.svelte';
// return; // return;
// } // }
await initTitleBarVisibility();
try { try {
// console.log('************** LOADING API'); // console.log('************** LOADING API');

View File

@ -24,18 +24,12 @@
import dragDropFileTarget from './utility/dragDropFileTarget'; import dragDropFileTarget from './utility/dragDropFileTarget';
import TitleBar from './widgets/TitleBar.svelte'; import TitleBar from './widgets/TitleBar.svelte';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { shouldDrawTitleBar } from './utility/common'; import { getTitleBarVisibility } from './utility/common';
$: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light'; $: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light';
let domTabs; let domTabs;
let drawTitleBar = false;
onMount(async () => {
drawTitleBar = await shouldDrawTitleBar();
document.documentElement.style.setProperty('--dim-visible-titlebar', drawTitleBar ? 1 : 0);
});
function handleTabsWheel(e) { function handleTabsWheel(e) {
if (!e.shiftKey) { if (!e.shiftKey) {
e.preventDefault(); e.preventDefault();
@ -57,7 +51,7 @@
use:dragDropFileTarget use:dragDropFileTarget
on:contextmenu={e => e.preventDefault()} on:contextmenu={e => e.preventDefault()}
> >
{#if drawTitleBar} {#if getTitleBarVisibility()}
<div class="titlebar"> <div class="titlebar">
<TitleBar /> <TitleBar />
</div> </div>

View File

@ -3,6 +3,7 @@
import FormButton from '../forms/FormButton.svelte'; import FormButton from '../forms/FormButton.svelte';
import FormCheckboxField from '../forms/FormCheckboxField.svelte'; import FormCheckboxField from '../forms/FormCheckboxField.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import FormProvider from '../forms/FormProvider.svelte'; import FormProvider from '../forms/FormProvider.svelte';
import FormSelectField from '../forms/FormSelectField.svelte'; import FormSelectField from '../forms/FormSelectField.svelte';
@ -14,6 +15,9 @@
import { closeCurrentModal } from '../modals/modalTools'; import { closeCurrentModal } from '../modals/modalTools';
import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores'; import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores';
import { apiCall } from '../utility/api'; import { apiCall } from '../utility/api';
import { getTitleBarVisibility } from '../utility/common';
import getElectron from '../utility/getElectron';
import { showSnackbarInfo } from '../utility/snackbar';
function handleOk(e) { function handleOk(e) {
apiCall( apiCall(
@ -22,8 +26,14 @@
); );
visibleToolbar.set(!!e.detail[':visibleToolbar']); visibleToolbar.set(!!e.detail[':visibleToolbar']);
zoomKoef.set(e.detail[':zoomKoef']); zoomKoef.set(e.detail[':zoomKoef']);
if (electron && !getTitleBarVisibility() != !!e.detail[':useNativeMenu']) {
electron.send('set-use-native-menu', !!e.detail[':useNativeMenu']);
showSnackbarInfo('Native menu settings will be applied after app restart');
}
closeCurrentModal(); closeCurrentModal();
} }
const electron = getElectron();
</script> </script>
<FormProvider <FormProvider
@ -31,6 +41,7 @@
...getCurrentSettings(), ...getCurrentSettings(),
':visibleToolbar': getVisibleToolbar(), ':visibleToolbar': getVisibleToolbar(),
':zoomKoef': getZoomKoef(), ':zoomKoef': getZoomKoef(),
':useNativeMenu': !getTitleBarVisibility(),
}} }}
> >
<ModalBase {...$$restProps}> <ModalBase {...$$restProps}>
@ -39,6 +50,9 @@
<FormValues let:values> <FormValues let:values>
<div class="heading">Appearance</div> <div class="heading">Appearance</div>
<FormCheckboxField name=":visibleToolbar" label="Show toolbar" defaultValue={true} /> <FormCheckboxField name=":visibleToolbar" label="Show toolbar" defaultValue={true} />
{#if electron}
<FormCheckboxField name=":useNativeMenu" label="Use system native menu" />
{/if}
<FormSelectField <FormSelectField
name=":zoomKoef" name=":zoomKoef"
label="Zoom" label="Zoom"

View File

@ -40,13 +40,23 @@ export async function asyncFilter(arr, predicate) {
return arr.filter((_v, index) => results[index]); return arr.filter((_v, index) => results[index]);
} }
export async function shouldDrawTitleBar() { async function computeTitleBarVisibility() {
const electron = getElectron(); const electron = getElectron();
if (!electron) { if (!electron) {
return false; return false;
} }
if (await electron.isNativeMenu()) { if (await electron.useNativeMenu()) {
return false; return false;
} }
return true; return true;
} }
let titleBarVisibility = false;
export async function initTitleBarVisibility() {
titleBarVisibility = await computeTitleBarVisibility();
document.documentElement.style.setProperty('--dim-visible-titlebar', titleBarVisibility ? '1' : '0');
}
export function getTitleBarVisibility() {
return titleBarVisibility;
}

View File

@ -26,8 +26,8 @@ class ElectronApi {
await this.ipcRenderer.invoke('openExternal', url); await this.ipcRenderer.invoke('openExternal', url);
} }
async isNativeMenu() { async useNativeMenu() {
const res = await this.ipcRenderer.invoke('isNativeMenu'); const res = await this.ipcRenderer.invoke('useNativeMenu');
return res; return res;
} }

View File

@ -2,7 +2,7 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import FontIcon from '../icons/FontIcon.svelte'; import FontIcon from '../icons/FontIcon.svelte';
import { currentDropDownMenu, selectedWidget, visibleCommandPalette } from '../stores'; import { currentDropDownMenu, selectedWidget, visibleCommandPalette } from '../stores';
import { shouldDrawTitleBar } from '../utility/common'; import { getTitleBarVisibility } from '../utility/common';
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition'; import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
let domSettings; let domSettings;
@ -78,15 +78,10 @@
const items = mainMenuDefinition; const items = mainMenuDefinition;
currentDropDownMenu.set({ left, top, items }); currentDropDownMenu.set({ left, top, items });
} }
let showMainMenu = false;
onMount(async () => {
showMainMenu = !(await shouldDrawTitleBar());
});
</script> </script>
<div class="main"> <div class="main">
{#if showMainMenu} {#if !getTitleBarVisibility()}
<div class="wrapper mb-3" on:click={handleMainMenu} bind:this={domMainMenu}> <div class="wrapper mb-3" on:click={handleMainMenu} bind:this={domMainMenu}>
<FontIcon icon="icon menu" /> <FontIcon icon="icon menu" />
</div> </div>