Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Electron Tray Icon doesn't show after once I package

I've got an Electron app that shows a tray icon, which, when clicked, shows my main window. works great in development mode, but when I package it, (into a .app file), and double click the .app file, none of the menus show up, and more importantly, the icon doesn't show up, and so the user can never see my app.

I'm using the electron React/Redux Boilerplate (https://github.com/chentsulin/electron-react-boilerplate)

here's my main.dev.js file - any guesses are appreciated:

import { app, BrowserWindow, Tray } from 'electron';
import MenuBuilder from './menu';

let mainWindow = null;
let tray;

if (process.env.NODE_ENV === 'production') {
  const sourceMapSupport = require('source-map-support');
  sourceMapSupport.install();
}

if (
  process.env.NODE_ENV === 'development' ||
  process.env.DEBUG_PROD === 'true'
) {
  require('electron-debug')();
  const path = require('path');
  const p = path.join(__dirname, '..', 'app', 'node_modules');
  require('module').globalPaths.push(p);
}

const installExtensions = async () => {
  const installer = require('electron-devtools-installer');
  const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
  const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];

  return Promise.all(
    extensions.map(name => installer.default(installer[name], forceDownload))
  ).catch(console.error);
};

/**
 * Add event listeners...
 */

app.on('window-all-closed', () => {
  // Respect the OSX convention of having the application in memory even
  // after all windows have been closed
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

const getWindowPosition = () => {
  const windowBounds = mainWindow.getBounds();
  const trayBounds = tray.getBounds();

  // Center window horizontally below the tray icon
  const x = Math.round(
    trayBounds.x + trayBounds.width / 2 - windowBounds.width / 2
  );

  // Position window 4 pixels vertically below the tray icon
  const y = Math.round(trayBounds.y + trayBounds.height + 4);

  return { x, y };
};

function createTray() {
  const path = require('path');
  const iconPath = path.join(__dirname, 'confluence.png');
  tray = new Tray(iconPath);
  tray.setToolTip('Confluence Helper');
  tray.on('click', event => {
    toggleWindow();

    // Show devtools when command clicked
    if (mainWindow.isVisible() && process.defaultApp && event.metaKey) {
      mainWindow.openDevTools({ mode: 'detach' });
    }
  });
}
const toggleWindow = () => {
  if (mainWindow.isVisible()) {
    mainWindow.hide();
  } else {
    showWindow();
  }
};

const showWindow = () => {
  const position = getWindowPosition();
  mainWindow.setPosition(position.x, position.y, false);
  mainWindow.show();
  mainWindow.focus();
};

app.on('ready', async () => {
  if (
    process.env.NODE_ENV === 'development' ||
    process.env.DEBUG_PROD === 'true'
  ) {
    await installExtensions();
  }

  mainWindow = new BrowserWindow({
    show: false,
    width: 500,
    height: 728,
    icon: `${__dirname}/confluence.icns`
  });

  mainWindow.loadURL(`file://${__dirname}/app.html`);

  createTray();
  // @TODO: Use 'ready-to-show' event
  //        https://github.com/electron/electron/blob/master/docs/api/browser-window.md#using-ready-to-show-event
  mainWindow.webContents.on('did-finish-load', () => {
    if (!mainWindow) {
      throw new Error('"mainWindow" is not defined');
    }
    if (process.env.START_MINIMIZED) {
      mainWindow.minimize();
    }
  });
  mainWindow.on('blur', () => {
    mainWindow.hide();
  });

  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  const menuBuilder = new MenuBuilder(mainWindow);
  menuBuilder.buildMenu();
});
like image 849
raingod Avatar asked Sep 17 '18 20:09

raingod


People also ask

What is tray in electron?

Advertisements. System tray is a menu outside of your application window. On MacOS and Ubuntu, it is located on the top right corner of your screen. On Windows it is on the bottom right corner. We can create menus for our application in system trays using Electron.


2 Answers

When i right clicked the .app file, and chose "Show Package Contents", I could see a Contents/Mac folder, and inside that was a unix executable file, which when I ran in the command line, showed me a rejected promised that had to do with my tray icon - I was doing a path.join(__dirname,'icon.png'), that ended up being the wrong path (console.log(path.join(__dirname,'icon.png')) to the rescue!

When I changed that to an absolute path ('users/myname/app/icon.png') and rebuilt, it worked!

However, this obviously won't work on OTHER people's computers - it did work on my computer(tm), but that's not good enough.

To REALLY fix it, I might have gone overboard - but this is what worked for me - by creating a NativeImage, using a path.join(__dirname,'resources','icon.png') in what I passed into that. I also added resources under build/files in package.json.

If you run into this kind of problem, i would recommend doing what I did (show package contents, etc) to see the issue in the packaged electron app.

like image 126
raingod Avatar answered Oct 18 '22 13:10

raingod


I had the same problem on Windows (didn't tested in other OSes). Tray icon was working when running the app from VSCode, but it was invisible after packaged for Windows. Like the answer from @raingod, I was using the absolute path:

//Gets the icon to use in the tray
icon = nativeImage.createFromPath(path.join(__dirname, "build", "32x32.png"))
//Creates the tray
tray = new Tray(icon)

But what I found to be the problem was that I was pointing to a file in the "build" folder, where all the icons for my app were stored. Somehow it was causing this problem with the tray icon in the packaged app specifically. So I moved just the file used in the tray icon to another folder: "./src/icons/32x32.png". So the code looked like this:

//Gets the icon to use in the tray
icon = nativeImage.createFromPath(path.join(__dirname, "src", "icons", "32x32.png"))
//Creates the tray
tray = new Tray(icon)

Posting this here because another person might have the same problem. So use absolute path, and don't store the icon file in the "build" folder.

like image 33
juninholiveira Avatar answered Oct 18 '22 14:10

juninholiveira