Skip to content

Instantly share code, notes, and snippets.

@kralo
Last active August 15, 2021 18:16
Show Gist options
  • Save kralo/7846138f35f6ca689d1c182fa4daa3ce to your computer and use it in GitHub Desktop.
Save kralo/7846138f35f6ca689d1c182fa4daa3ce to your computer and use it in GitHub Desktop.
electron_auto-resize_window_to_content

resize the electron app to match the content. Might be used for web-based Asterisk BLI-Pages or other unobstrusive notifications.

Window is always on top on Ubuntu/Windows

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Electron Window expand/shrink Demo!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using Node.js <span id="node-version"></span>,
Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
<p>This Window will expand/shrink in height only. It will keep the width the user sets</p>
<p id="content"> Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
<input type="button" id="addContent" value="Add Content" />
<input type="button" id="resetter" value="Reset" />
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>
</html>
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')
let mainWindow;
function createWindow() {
mainWindow = new BrowserWindow({
width: 400,
height: 600,
alwaysOnTop: true,
autoHideMenuBar: true,
useContentSize: true,
backgroundColor: '#f9f9fa',
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
moveNotification = function (event) {
cancelMoveNotification()
}
const { ipcMain } = require('electron')
let suspected_y = -1, previous_y = -1;
cancelMoveNotification = function () { // workaround to register potentially moved windows
mainWindow.removeListener('move', moveNotification)
const after = mainWindow.getBounds();
if (after.y < previous_y) {
// suspect that window moved upwards
if (suspected_y < 0)
suspected_y = previous_y;
}
}
ipcMain.on('resize-window-content-height', (event, arg) => {
const before = mainWindow.getContentBounds();
const width = mainWindow.getContentSize()[0]
mainWindow.on('move', moveNotification)
mainWindow.setContentBounds({x:before.x, y:before.y, width:before.width,height:arg + 30}, true); // +30 because not everything is shown -.-
const after = mainWindow.getContentBounds(); // this does not reflect potentially moved window
if (before.height < after.height) {
// it expanded
previous_y = after.y
} else {
//it shrank
if (suspected_y > 0) {
//mainWindow.setContentBounds({y: suspected_y}) // does not work
mainWindow.setContentBounds({x:after.x, y: suspected_y, width:after.width, height:after.height })
}
suspected_y = -1;
}
setTimeout(cancelMoveNotification, 200)
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
{
"name": "lonely-floor-use-n68x5",
"productName": "lonely-floor-use-n68x5",
"description": "My Electron application description",
"keywords": [],
"main": "./main.js",
"version": "1.0.0",
"author": "max",
"scripts": {
"start": "electron ."
},
"dependencies": {},
"devDependencies": {
"electron": "13.1.9"
}
}
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
resizerContent: (height) => ipcRenderer.send('resize-window-content-height', height)
}
)
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// No Node.js APIs are available in this process because
// `nodeIntegration` is turned off. Use `preload.js` to
// selectively enable features needed in the rendering
// process.
document.getElementById('addContent').addEventListener('click', (e) => {
document.getElementById('content').innerHTML = document.getElementById('content').innerHTML + document.getElementById('content').innerHTML;
});
document.getElementById('resetter').addEventListener('click', (e) => {
document.getElementById('content').innerText = 'this is text.';
});
// automatically resize on content change
var observer = new MutationObserver(function (mutations) {
window.electron.resizerContent(document.body.scrollHeight)
});
var container = document.documentElement || document.body;
var config = { subtree: true, attributes: false, childList: true, characterData: false };
observer.observe(container, config);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment