Added native menu support in desktop mode. #5503

This commit is contained in:
Nikhil Mohite
2022-12-06 18:16:36 +05:30
committed by GitHub
parent cddb24bc50
commit 2480d08e0f
78 changed files with 1126 additions and 523 deletions

View File

@@ -6,7 +6,6 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
const axios = require('axios');
const fs = require('fs');
const path = require('path');
@@ -16,6 +15,8 @@ const spawn = require('child_process').spawn;
let pgadminServerProcess = null;
let startPageUrl = null;
let serverCheckUrl = null;
let addMenuCompleted = false;
let pgAdminMainScreen = null;
let serverPort = 5050;
let appStartTime = (new Date()).getTime();
@@ -69,7 +70,7 @@ function startDesktopMode() {
misc.writeServerLog('Webapp Path: "' + path.resolve(pgadminFile) + '"');
misc.writeServerLog('pgAdmin Command: "' + command + '"');
misc.writeServerLog('Environment: ');
Object.keys(process.env).forEach(function(key) {
Object.keys(process.env).forEach(function (key) {
// Below code is included only for Mac OS as default path for azure CLI
// installation path is not included in PATH variable while spawning
// runtime environment.
@@ -84,13 +85,13 @@ function startDesktopMode() {
// Spawn the process to start pgAdmin4 server.
let spawnStartTime = (new Date).getTime();
pgadminServerProcess = spawn(path.resolve(pythonPath), ['-s', path.resolve(pgadminFile)]);
pgadminServerProcess.on('error', function(err) {
pgadminServerProcess.on('error', function (err) {
// Log the error into the log file if process failed to launch
misc.writeServerLog('Failed to launch pgAdmin4. Error:');
misc.writeServerLog(err);
});
let spawnEndTime = (new Date).getTime();
misc.writeServerLog('Total spawn time to start the pgAdmin4 server: ' + (spawnEndTime - spawnStartTime)/1000 + ' Sec');
misc.writeServerLog('Total spawn time to start the pgAdmin4 server: ' + (spawnEndTime - spawnStartTime) / 1000 + ' Sec');
pgadminServerProcess.stdout.setEncoding('utf8');
pgadminServerProcess.stdout.on('data', (chunk) => {
@@ -125,7 +126,7 @@ function startDesktopMode() {
misc.zoomIn();
} else if (chunk.indexOf('Runtime Zoom Out') >= 0) {
misc.zoomOut();
} else if (chunk.indexOf('Runtime Actual Size') >= 0) {
} else if (chunk.indexOf('Runtime Actual Size') >= 0) {
misc.actualSize();
} else if (chunk.indexOf('Runtime Toggle Full Screen') >= 0) {
misc.toggleFullScreen();
@@ -144,14 +145,14 @@ function startDesktopMode() {
let connectionTimeout = misc.ConfigureStore.get('connectionTimeout', 90) * 1000;
let currentTime = (new Date).getTime();
let endTime = currentTime + connectionTimeout;
let midTime1 = currentTime + (connectionTimeout/2);
let midTime2 = currentTime + (connectionTimeout*2/3);
let endTime = currentTime + connectionTimeout;
let midTime1 = currentTime + (connectionTimeout / 2);
let midTime2 = currentTime + (connectionTimeout * 2 / 3);
let pingInProgress = false;
// ping pgAdmin server every 1 second.
let pingStartTime = (new Date).getTime();
let intervalID = setInterval(function() {
let intervalID = setInterval(function () {
// If ping request is already send and response is not
// received no need to send another request.
if (pingInProgress)
@@ -166,9 +167,9 @@ function startDesktopMode() {
clearInterval(intervalID);
let appEndTime = (new Date).getTime();
misc.writeServerLog('------------------------------------------');
misc.writeServerLog('Total time taken to ping pgAdmin4 server: ' + (appEndTime - pingStartTime)/1000 + ' Sec');
misc.writeServerLog('Total time taken to ping pgAdmin4 server: ' + (appEndTime - pingStartTime) / 1000 + ' Sec');
misc.writeServerLog('------------------------------------------');
misc.writeServerLog('Total launch time of pgAdmin4: ' + (appEndTime - appStartTime)/1000 + ' Sec');
misc.writeServerLog('Total launch time of pgAdmin4: ' + (appEndTime - appStartTime) / 1000 + ' Sec');
misc.writeServerLog('------------------------------------------');
launchPgAdminWindow();
}).catch(() => {
@@ -192,7 +193,7 @@ function startDesktopMode() {
}
if (curTime > midTime1) {
if(curTime < midTime2) {
if (curTime < midTime2) {
document.getElementById('loader-text-status').innerHTML = 'Taking longer than usual...';
} else {
document.getElementById('loader-text-status').innerHTML = 'Almost there...';
@@ -223,7 +224,8 @@ function launchPgAdminWindow() {
'height': 768,
'focus': true,
'show': false,
}, (pgadminWindow)=> {
}, (pgadminWindow) => {
pgAdminMainScreen = pgadminWindow;
// Set pgAdmin4 Windows Object
misc.setPgAdminWindowObject(pgadminWindow);
@@ -233,18 +235,18 @@ function launchPgAdminWindow() {
// Set zoom in and out events.
misc.setZoomEvents();
pgadminWindow.on('closed', function() {
pgadminWindow.on('closed', function () {
misc.cleanupAndQuitApp();
});
// set up handler for new-win-policy event.
// Set the width and height for the new window.
pgadminWindow.on('new-win-policy', function(frame, url, policy) {
if(!frame) {
pgadminWindow.on('new-win-policy', function (frame, url, policy) {
if (!frame) {
let openDocsInBrowser = misc.ConfigureStore.get('openDocsInBrowser', true);
let isDocURL = false;
docsURLSubStrings.forEach(function(key) {
if(url.indexOf(key) >= 0) {
docsURLSubStrings.forEach(function (key) {
if (url.indexOf(key) >= 0) {
isDocURL = true;
}
});
@@ -268,7 +270,7 @@ function launchPgAdminWindow() {
}
});
pgadminWindow.on('loaded', function() {
pgadminWindow.on('loaded', function () {
/* Make the new window opener to null as it is
* nothing but a splash screen. We will have to make it null,
* so that open in new browser tab will work.
@@ -279,15 +281,39 @@ function launchPgAdminWindow() {
pgadminWindow.show();
pgadminWindow.focus();
nativeMenu = new gui.Menu({ type: 'menubar' });
// Create Mac Builtin Menu
if (platform() === 'darwin') {
nativeMenu.createMacBuiltin('pgAdmin 4');
pgAdminMainScreen.menu = nativeMenu;
}
try {
pgAdminMainScreen.isCustomMenusAdded = false;
let addMenuInterval = setInterval(() => {
if (pgadminWindow?.window?.pgAdmin?.Browser?.Events && pgadminWindow?.window?.pgAdmin?.Browser?.MainMenus?.length > 0) {
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-enable-disable-menu-items', enableDisableMenuItem);
pgadminWindow.window.pgAdmin.Browser.Events.on('pgadmin:nw-refresh-menu-item', refreshMenuItems);
// Add Main Menus to native menu.
pgadminWindow.window.pgAdmin.Browser.MainMenus.forEach((menu)=> {
addMenu(pgadminWindow.window.pgAdmin.Browser, menu)
})
clearInterval(addMenuInterval);
}
}, 250)
} catch (e) {
console.error('Error in add native menus');
}
// Hide the splash screen
splashWindow.hide();
});
pgadminWindow.on('blur', function() {
pgadminWindow.on('blur', function () {
misc.unregisterZoomEvents();
});
pgadminWindow.on('focus', function() {
pgadminWindow.on('focus', function () {
misc.registerZoomEvents();
});
});
@@ -299,17 +325,17 @@ let splashWindow = gui.Window.get();
// Enable dragging on the splash screen.
let isDragging = false;
let dragOrigin = {x:0, y:0};
document.mouseleave = ()=> isDragging = false;
document.onmouseup = ()=> isDragging = false;
let dragOrigin = { x: 0, y: 0 };
document.mouseleave = () => isDragging = false;
document.onmouseup = () => isDragging = false;
document.onmousedown = (e)=> {
document.onmousedown = (e) => {
isDragging = true;
dragOrigin.x = e.x;
dragOrigin.y = e.y;
};
document.onmousemove = (e)=> {
document.onmousemove = (e) => {
if (isDragging) {
splashWindow.moveTo(e.screenX - dragOrigin.x, e.screenY - dragOrigin.y);
}
@@ -318,14 +344,9 @@ document.onmousemove = (e)=> {
// Always clear the cache before starting the application.
nw.App.clearCache();
// Create Mac Builtin Menu
if (platform() === 'darwin') {
let macMenu = new gui.Menu({type: 'menubar'});
macMenu.createMacBuiltin('pgAdmin 4');
splashWindow.menu = macMenu;
}
let nativeMenu;
splashWindow.on('loaded', function() {
splashWindow.on('loaded', function () {
// Initialize the ConfigureStore
misc.ConfigureStore.init();
@@ -352,6 +373,200 @@ splashWindow.on('loaded', function() {
}
});
splashWindow.on('close', function() {
splashWindow.on('close', function () {
misc.cleanupAndQuitApp();
});
function addCommonMenus(pgBrowser, menu) {
let _menu = new gui.Menu();
menu.menuItems.forEach((menuItem) => {
var submenu = getSubMenu(pgBrowser, menuItem);
let _menuItem = new gui.MenuItem({
label: menuItem.label,
enabled: !menuItem.is_disabled,
type: menuItem.type || 'normal',
priority: menuItem.priority,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
menuItem.callback();
},
});
_menu.append(_menuItem);
});
if (menu.menuItems.length == 0) {
let _menuItem = new gui.MenuItem({
label: 'No object selected',
enabled: false,
priority: 0,
});
_menu.append(_menuItem);
}
if (platform() == 'darwin') {
pgAdminMainScreen.menu.insert(new gui.MenuItem({
label: menu.label,
name: menu.name,
submenu: _menu,
}), menu.index);
} else {
nativeMenu.append(new gui.MenuItem({
label: menu.label,
name: menu.name,
submenu: _menu,
}));
pgAdminMainScreen.menu = nativeMenu;
}
}
function getSubMenu(pgBrowser, menuItem) {
var submenu = new gui.Menu();
if (menuItem.menu_items) {
menuItem.menu_items.forEach((item) => {
let menuType = typeof item.checked == 'boolean' ? 'checkbox' : item.type || 'normal';
submenu.append(new gui.MenuItem({
label: item.label,
enabled: !item.is_disabled,
priority: item.priority,
type: menuType,
checked: item.checked,
click: function () {
if (menuType == 'checkbox') {
pgAdminMainScreen.menu.items.forEach(el => {
el.submenu.items.forEach((sub) => {
if (sub.submenu?.items?.length) {
sub.submenu.items.forEach((m) => {
if (m.type == 'checkbox') {
m.label == item.label ? m.checked = true : m.checked = false;
}
});
}
});
});
}
item.callback();
},
}));
});
}
return submenu;
}
function addMacMenu(pgBrowser, menu) {
if (menu.name == 'file' && platform() === 'darwin') {
var rootMenu = nativeMenu.items[0].submenu;
let indx = 0;
menu.menuItems.forEach((menuItem) => {
let submenu = getSubMenu(pgBrowser, menuItem);
rootMenu.insert(
new gui.MenuItem({
label: menuItem.label,
type: menuItem.type || 'normal',
enabled: !menuItem.is_disabled,
priority: menuItem.priority,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
// Callback functions for actions
menuItem.callback();
},
}), indx);
indx++;
});
let separator_menu = new nw.MenuItem({ type: 'separator' });
rootMenu.insert(separator_menu, indx);
indx++;
pgAdminMainScreen.menu = nativeMenu;
} else {
addCommonMenus(pgBrowser, menu)
}
}
function addOtherOsMenu(pgBrowser, menu) {
addCommonMenus(pgBrowser, menu)
}
function addMenu(pgBrowser, menu) {
pgAdminMainScreen.isCustomMenusAdded = true;
if (platform() === 'darwin') {
addMacMenu(pgBrowser, menu);
} else {
addOtherOsMenu(pgBrowser, menu);
}
addMenuCompleted = true;
}
function enableDisableMenuItem(menu, menuItem) {
if (addMenuCompleted) {
// Enable or Disabled specific menu item
pgAdminMainScreen.menu.items.forEach(el => {
if (el?.label == menu?.label) {
el.submenu.items.forEach((sub) => {
if (sub.label == menuItem.label) {
sub.enabled = !menuItem.is_disabled;
}
});
}
});
}
}
function refreshMenuItems(menu) {
// Add menu item/option in specific menu.
pgAdminMainScreen.menu.items.forEach(el => {
if (el.label == menu.label) {
let totalSubItems = el.submenu.items.length;
// Remove exisitng menu options to add new options.
for (let i = 0; i < totalSubItems; i++) {
el.submenu.removeAt(0);
}
menu.menuItems.forEach((item) => {
var submenu = new gui.Menu();
if (item.menu_items) {
item.menu_items.forEach((subItem) => {
submenu.append(new gui.MenuItem({
label: subItem.label,
enabled: !subItem.is_disabled,
priority: subItem.priority,
type: [true, false].includes(subItem.checked) ? 'checkbox' : 'normal',
checked: subItem.checked,
click: function () {
subItem.callback();
},
}));
});
}
let _menuItem = new gui.MenuItem({
label: item.label,
enabled: !item.is_disabled,
priority: item.priority,
...(submenu.items.length > 0) && {
submenu: submenu,
},
click: function () {
item.callback();
},
});
el.submenu.append(_menuItem);
if (['create', 'register'].includes(item.category)) {
let separator_menu = new gui.MenuItem({ type: 'separator' });
el.submenu.append(separator_menu);
}
});
}
});
}