native menu, fullscreen refactor

This commit is contained in:
Jan Prochazka 2022-02-26 14:04:18 +01:00
parent 9267ca326f
commit 7b8c0be044
14 changed files with 77 additions and 165 deletions

View File

@ -14,9 +14,7 @@ const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
const mainMenuDefinition = require('./mainMenuDefinition');
let useNativeMenu = true;
let useNativeMenuSpecified = null;
const { settings } = require('cluster');
// require('@electron/remote/main').initialize();
@ -104,9 +102,6 @@ ipcMain.on('set-title', async (event, arg) => {
ipcMain.on('open-link', async (event, arg) => {
electron.shell.openExternal(arg);
});
ipcMain.on('set-use-native-menu', async (event, arg) => {
useNativeMenuSpecified = arg;
});
ipcMain.on('window-action', async (event, arg) => {
switch (arg) {
case 'minimize':
@ -122,8 +117,11 @@ ipcMain.on('window-action', async (event, arg) => {
case 'close':
mainWindow.close();
break;
case 'fullscreen':
mainWindow.setFullScreen(!mainWindow.isFullScreen());
case 'fullscreen-on':
mainWindow.setFullScreen(true);
break;
case 'fullscreen-off':
mainWindow.setFullScreen(false);
break;
case 'devtools':
mainWindow.webContents.toggleDevTools();
@ -157,21 +155,31 @@ ipcMain.handle('showItemInFolder', async (event, path) => {
ipcMain.handle('openExternal', async (event, url) => {
electron.shell.openExternal(url);
});
ipcMain.handle('useNativeMenu', async () => {
return useNativeMenu;
});
function fillMissingSettings(value) {
const res = {
...value,
};
if (value['app.useNativeMenu'] !== true && value['app.useNativeMenu'] !== false) {
res['app.useNativeMenu'] = os.platform() == 'darwin' ? true : false;
}
return res;
}
function createWindow() {
let settingsJson = {};
try {
const datadir = path.join(os.homedir(), 'dbgate-data');
settingsJson = fillMissingSettings(
JSON.parse(fs.readFileSync(path.join(datadir, 'settings.json'), { encoding: 'utf-8' }))
);
} catch (err) {
console.log('Error loading settings.json:', err.message);
settingsJson = fillMissingSettings({});
}
const bounds = initialConfig['winBounds'];
useNativeMenu = os.platform() == 'darwin' ? true : false;
if (initialConfig['useNativeMenu'] === true) {
useNativeMenu = true;
useNativeMenuSpecified = true;
}
if (initialConfig['useNativeMenu'] === false) {
useNativeMenu = false;
useNativeMenuSpecified = false;
}
useNativeMenu = settingsJson['app.useNativeMenu'];
mainWindow = new BrowserWindow({
width: 1200,
@ -192,17 +200,14 @@ function createWindow() {
if (initialConfig['winIsMaximized']) {
mainWindow.maximize();
}
if (initialConfig['winIsFullscreen']) {
if (settingsJson['app.fullscreen']) {
mainWindow.setFullScreen(true);
}
mainMenu = buildMenu();
mainWindow.setMenu(mainMenu);
async function loadMainWindow() {
const settings = await main.configController.getSettings();
console.log(settings);
function loadMainWindow() {
const startUrl =
process.env.ELECTRON_START_URL ||
url.format({
@ -217,8 +222,6 @@ function createWindow() {
JSON.stringify({
winBounds: mainWindow.getBounds(),
winIsMaximized: mainWindow.isMaximized(),
useNativeMenu: useNativeMenuSpecified,
winIsFullscreen: mainWindow.isFullScreen(),
}),
'utf-8'
);
@ -230,6 +233,7 @@ function createWindow() {
if (os.platform() == 'linux') {
mainWindow.setIcon(path.resolve(__dirname, '../icon.png'));
}
// mainWindow.webContents.toggleDevTools();
}
const apiPackage = path.join(

View File

@ -1,4 +1,5 @@
const fs = require('fs-extra');
const os = require('os');
const path = require('path');
const axios = require('axios');
const { datadir } = require('../utility/directories');
@ -44,12 +45,24 @@ module.exports = {
getSettings_meta: true,
async getSettings() {
try {
return JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }));
return this.fillMissingSettings(
JSON.parse(await fs.readFile(path.join(datadir(), 'settings.json'), { encoding: 'utf-8' }))
);
} catch (err) {
return {};
return this.fillMissingSettings({});
}
},
fillMissingSettings(value) {
const res = {
...value,
};
if (value['app.useNativeMenu'] !== true && value['app.useNativeMenu'] !== false) {
res['app.useNativeMenu'] = os.platform() == 'darwin' ? true : false;
}
return res;
},
updateSettings_meta: true,
async updateSettings(values) {
if (!hasPermission(`settings/change`)) return false;

View File

@ -15,9 +15,8 @@
import { subscribeConnectionPingers } from './utility/connectionsPinger';
import { subscribePermissionCompiler } from './utility/hasPermission';
import { apiCall } from './utility/api';
import { getConfig, getUsedApps } from './utility/metadataLoaders';
import { getConfig, getSettings, getUsedApps } from './utility/metadataLoaders';
import AppTitleProvider from './utility/AppTitleProvider.svelte';
import { initTitleBarVisibility } from './utility/common';
let loadedApi = false;
@ -27,13 +26,11 @@
// return;
// }
await initTitleBarVisibility();
try {
// console.log('************** LOADING API');
const settings = await apiCall('config/get-settings');
const connections = await apiCall('connections/list');
const settings = await getSettings();
const config = await getConfig();
const apps = await getUsedApps();
loadedApi = settings && connections && config && apps;

View File

@ -9,6 +9,7 @@
openedSnackbars,
selectedWidget,
visibleCommandPalette,
visibleTitleBar,
visibleToolbar,
} from './stores';
import TabsPanel from './widgets/TabsPanel.svelte';
@ -23,8 +24,6 @@
import DragAndDropFileTarget from './DragAndDropFileTarget.svelte';
import dragDropFileTarget from './utility/dragDropFileTarget';
import TitleBar from './widgets/TitleBar.svelte';
import { onMount } from 'svelte';
import { getTitleBarVisibility } from './utility/common';
$: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light';
@ -42,7 +41,7 @@
use:dragDropFileTarget
on:contextmenu={e => e.preventDefault()}
>
{#if getTitleBarVisibility()}
{#if $visibleTitleBar}
<div class="titlebar">
<TitleBar />
</div>

View File

@ -27,6 +27,7 @@ import { showSnackbarSuccess } from '../utility/snackbar';
import { apiCall } from '../utility/api';
import runCommand from './runCommand';
import { openWebLink } from '../utility/exportElectronFile';
import { getSettings } from '../utility/metadataLoaders';
function themeCommand(theme: ThemeDefinition) {
return {
@ -596,7 +597,13 @@ registerCommand({
name: 'Toggle full screen',
keyText: 'F11',
testEnabled: () => getElectron() != null,
onClick: () => getElectron().send('window-action', 'fullscreen'),
onClick: async () => {
const settings = await getSettings();
const value = !settings['app.fullscreen'];
apiCall('config/update-settings', { 'app.fullscreen': value });
if (value) getElectron().send('window-action', 'fullscreen-on');
else getElectron().send('window-action', 'fullscreen-off');
},
});
registerCommand({

View File

@ -1,23 +0,0 @@
<script lang="ts">
import { getFormContext } from './FormProviderCore.svelte';
import SettingsCheckboxFieldRaw from './SettingsCheckboxFieldRaw.svelte';
export let label;
export let name;
export let disabled = false;
export let templateProps = {};
const { template, setFieldValue, values } = getFormContext();
</script>
<svelte:component
this={template}
on:change
type="checkbox"
{label}
{disabled}
{...templateProps}
labelProps={disabled ? { disabled: true } : { onClick: () => setFieldValue(name, !$values[name]) }}
>
<SettingsCheckboxFieldRaw {name} {...$$restProps} {disabled} />
</svelte:component>

View File

@ -1,17 +0,0 @@
<script lang="ts">
import CheckboxField from './CheckboxField.svelte';
import { apiCall } from '../utility/api';
import _ from 'lodash';
import { useSettings } from '../utility/metadataLoaders';
export let name;
export let defaultValue;
const settings = useSettings();
function handleChange(e) {
apiCall('config/update-settings', { [name]: e.target['checked'] });
}
</script>
<CheckboxField {...$$restProps} checked={($settings || {})[name] ?? defaultValue} on:change={handleChange} on:change />

View File

@ -1,15 +0,0 @@
<script lang="ts">
import { getFormContext } from './FormProviderCore.svelte';
import SettingsTextFieldRaw from './SettingsTextFieldRaw.svelte';
export let label;
export let name;
export let templateProps = {};
export let focused = false;
const { template } = getFormContext();
</script>
<svelte:component this={template} type="text" {label} {...templateProps}>
<SettingsTextFieldRaw {name} {...$$restProps} {focused} />
</svelte:component>

View File

@ -1,18 +0,0 @@
<script lang="ts">
import { apiCall } from '../utility/api';
import { useSettings } from '../utility/metadataLoaders';
import TextField from './TextField.svelte';
export let name;
export let defaultValue;
const settings = useSettings();
function handleChange(e) {
apiCall('config/update-settings', { [name]: e.target['value'] });
}
</script>
<TextField {...$$restProps} value={($settings || {})[name] ?? defaultValue} on:input={handleChange} />

View File

@ -2,40 +2,16 @@
import _ from 'lodash';
import FormStyledButton from '../buttons/FormStyledButton.svelte';
import FormButton from '../forms/FormButton.svelte';
import FormCheckboxField from '../forms/FormCheckboxField.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import FormSelectField from '../forms/FormSelectField.svelte';
import FormSubmit from '../forms/FormSubmit.svelte';
import FormTextField from '../forms/FormTextField.svelte';
import FormValues from '../forms/FormValues.svelte';
import SettingsCheckboxField from '../forms/SettingsCheckboxField.svelte';
import SettingsFormProvider from '../forms/SettingsFormProvider.svelte';
import SettingsTextField from '../forms/SettingsTextField.svelte';
import ModalBase from '../modals/ModalBase.svelte';
import { closeCurrentModal } from '../modals/modalTools';
import { getCurrentSettings, getVisibleToolbar, getZoomKoef, visibleToolbar, zoomKoef } from '../stores';
import { apiCall } from '../utility/api';
import { getTitleBarVisibility } from '../utility/common';
import getElectron from '../utility/getElectron';
import { showSnackbarInfo } from '../utility/snackbar';
// function handleOk(e) {
// apiCall(
// 'config/update-settings',
// _.omitBy(e.detail, (v, k) => k.startsWith(':'))
// );
// visibleToolbar.set(!!e.detail[':visibleToolbar']);
// 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();
// }
const electron = getElectron();
</script>

View File

@ -76,9 +76,25 @@ export const currentThemeDefinition = derived([currentTheme, extensions], ([$cur
$extensions.themes.find(x => x.themeClassName == $currentTheme)
);
export const visibleTitleBar = derived(useSettings(), $settings => {
const electron = getElectron();
if (!electron) return false;
// console.log('visibleTitleBar:settings', $settings);
if (!$settings) return false;
return !$settings['app.fullscreen'] && !$settings['app.useNativeMenu'];
});
export const visibleHamburgerMenuWidget = derived(useSettings(), $settings => {
const electron = getElectron();
if (!electron) return true;
if (!$settings) return false;
return !!$settings['app.fullscreen'];
});
subscribeCssVariable(selectedWidget, x => (x ? 1 : 0), '--dim-visible-left-panel');
// subscribeCssVariable(visibleToolbar, x => (x ? 1 : 0), '--dim-visible-toolbar');
subscribeCssVariable(leftPanelWidth, x => `${x}px`, '--dim-left-panel-width');
subscribeCssVariable(visibleTitleBar, x => (x ? 1 : 0), '--dim-visible-titlebar');
let activeTabIdValue = null;
activeTabId.subscribe(value => {

View File

@ -39,24 +39,3 @@ export async function asyncFilter(arr, predicate) {
return arr.filter((_v, index) => results[index]);
}
async function computeTitleBarVisibility() {
const electron = getElectron();
if (!electron) {
return false;
}
if (await electron.useNativeMenu()) {
return false;
}
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,11 +26,6 @@ class ElectronApi {
await this.ipcRenderer.invoke('openExternal', url);
}
async useNativeMenu() {
const res = await this.ipcRenderer.invoke('useNativeMenu');
return res;
}
async invoke(route, args) {
const res = await this.ipcRenderer.invoke(route, args);
return res;

View File

@ -1,8 +1,7 @@
<script lang="ts">
import { onMount } from 'svelte';
import FontIcon from '../icons/FontIcon.svelte';
import { currentDropDownMenu, selectedWidget, visibleCommandPalette } from '../stores';
import { getTitleBarVisibility } from '../utility/common';
import { currentDropDownMenu, selectedWidget, visibleCommandPalette, visibleHamburgerMenuWidget } from '../stores';
import mainMenuDefinition from '../../../../app/src/mainMenuDefinition';
let domSettings;
@ -81,7 +80,7 @@
</script>
<div class="main">
{#if !getTitleBarVisibility()}
{#if $visibleHamburgerMenuWidget}
<div class="wrapper mb-3" on:click={handleMainMenu} bind:this={domMainMenu}>
<FontIcon icon="icon menu" />
</div>