bubblepipe42 hace 5 meses
padre
commit
0046282fb8
Se han modificado 4 ficheros con 142 adiciones y 4 borrados
  1. 60 0
      electron/create-tray-icon.js
  2. 18 0
      electron/entitlements.mac.plist
  3. 59 4
      electron/main.js
  4. 5 0
      electron/package.json

+ 60 - 0
electron/create-tray-icon.js

@@ -0,0 +1,60 @@
+// Create a simple tray icon for macOS
+// Run: node create-tray-icon.js
+
+const fs = require('fs');
+const { createCanvas } = require('canvas');
+
+function createTrayIcon() {
+  // For macOS, we'll use a Template image (black and white)
+  // Size should be 22x22 for Retina displays (@2x would be 44x44)
+  const canvas = createCanvas(22, 22);
+  const ctx = canvas.getContext('2d');
+
+  // Clear canvas
+  ctx.clearRect(0, 0, 22, 22);
+
+  // Draw a simple "API" icon
+  ctx.fillStyle = '#000000';
+  ctx.font = 'bold 10px system-ui';
+  ctx.textAlign = 'center';
+  ctx.textBaseline = 'middle';
+  ctx.fillText('API', 11, 11);
+
+  // Save as PNG
+  const buffer = canvas.toBuffer('image/png');
+  fs.writeFileSync('tray-icon.png', buffer);
+
+  // For Template images on macOS (will adapt to menu bar theme)
+  fs.writeFileSync('tray-iconTemplate.png', buffer);
+  fs.writeFileSync('tray-iconTemplate@2x.png', buffer);
+
+  console.log('Tray icon created successfully!');
+}
+
+// Check if canvas is installed
+try {
+  createTrayIcon();
+} catch (err) {
+  console.log('Canvas module not installed.');
+  console.log('For now, creating a placeholder. Install canvas with: npm install canvas');
+
+  // Create a minimal 1x1 transparent PNG as placeholder
+  const minimalPNG = Buffer.from([
+    0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
+    0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
+    0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
+    0x01, 0x03, 0x00, 0x00, 0x00, 0x25, 0xDB, 0x56,
+    0xCA, 0x00, 0x00, 0x00, 0x03, 0x50, 0x4C, 0x54,
+    0x45, 0x00, 0x00, 0x00, 0xA7, 0x7A, 0x3D, 0xDA,
+    0x00, 0x00, 0x00, 0x01, 0x74, 0x52, 0x4E, 0x53,
+    0x00, 0x40, 0xE6, 0xD8, 0x66, 0x00, 0x00, 0x00,
+    0x0A, 0x49, 0x44, 0x41, 0x54, 0x08, 0x1D, 0x62,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+    0x00, 0x01, 0x0A, 0x2D, 0xCB, 0x59, 0x00, 0x00,
+    0x00, 0x00, 0x49, 0x45, 0x4E, 0x44, 0xAE, 0x42,
+    0x60, 0x82
+  ]);
+
+  fs.writeFileSync('tray-icon.png', minimalPNG);
+  console.log('Created placeholder tray icon.');
+}

+ 18 - 0
electron/entitlements.mac.plist

@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+    <true/>
+    <key>com.apple.security.cs.allow-jit</key>
+    <true/>
+    <key>com.apple.security.cs.disable-library-validation</key>
+    <true/>
+    <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+    <true/>
+    <key>com.apple.security.network.client</key>
+    <true/>
+    <key>com.apple.security.network.server</key>
+    <true/>
+</dict>
+</plist>

+ 59 - 4
electron/main.js

@@ -1,4 +1,4 @@
-const { app, BrowserWindow, dialog } = require('electron');
+const { app, BrowserWindow, dialog, Tray, Menu } = require('electron');
 const { spawn } = require('child_process');
 const path = require('path');
 const http = require('http');
@@ -6,6 +6,7 @@ const fs = require('fs');
 
 let mainWindow;
 let serverProcess;
+let tray = null;
 const PORT = 3000;
 
 function getBinaryPath() {
@@ -109,6 +110,49 @@ function waitForServer(resolve, reject, retries = 30) {
   req.end();
 }
 
+function createTray() {
+  tray = new Tray(path.join(__dirname, 'tray-icon.png'));
+
+  const contextMenu = Menu.buildFromTemplate([
+    {
+      label: 'Show New API',
+      click: () => {
+        if (mainWindow === null) {
+          createWindow();
+        } else {
+          mainWindow.show();
+          if (process.platform === 'darwin') {
+            app.dock.show();
+          }
+        }
+      }
+    },
+    { type: 'separator' },
+    {
+      label: 'Quit',
+      click: () => {
+        app.isQuitting = true;
+        app.quit();
+      }
+    }
+  ]);
+
+  tray.setToolTip('New API');
+  tray.setContextMenu(contextMenu);
+
+  // On macOS, clicking the tray icon shows the menu
+  tray.on('click', () => {
+    if (mainWindow === null) {
+      createWindow();
+    } else {
+      mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show();
+      if (mainWindow.isVisible() && process.platform === 'darwin') {
+        app.dock.show();
+      }
+    }
+  });
+}
+
 function createWindow() {
   mainWindow = new BrowserWindow({
     width: 1400,
@@ -128,6 +172,17 @@ function createWindow() {
     mainWindow.webContents.openDevTools();
   }
 
+  // Close to tray instead of quitting
+  mainWindow.on('close', (event) => {
+    if (!app.isQuitting) {
+      event.preventDefault();
+      mainWindow.hide();
+      if (process.platform === 'darwin') {
+        app.dock.hide();
+      }
+    }
+  });
+
   mainWindow.on('closed', () => {
     mainWindow = null;
   });
@@ -136,6 +191,7 @@ function createWindow() {
 app.whenReady().then(async () => {
   try {
     await startServer();
+    createTray();
     createWindow();
   } catch (err) {
     console.error('Failed to start application:', err);
@@ -145,9 +201,8 @@ app.whenReady().then(async () => {
 });
 
 app.on('window-all-closed', () => {
-  if (process.platform !== 'darwin') {
-    app.quit();
-  }
+  // Don't quit when window is closed, keep running in tray
+  // Only quit when explicitly choosing Quit from tray menu
 });
 
 app.on('activate', () => {

+ 5 - 0
electron/package.json

@@ -58,6 +58,11 @@
     "mac": {
       "category": "public.app-category.developer-tools",
       "icon": "icon.png",
+      "identity": null,
+      "hardenedRuntime": false,
+      "gatekeeperAssess": false,
+      "entitlements": "entitlements.mac.plist",
+      "entitlementsInherit": "entitlements.mac.plist",
       "target": [
         "dmg",
         "zip"