mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added native menu support in desktop mode. #5503
This commit is contained in:
@@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user