From cf8e51e7aba6305ff756181b97e99d6ccfdc2f4c Mon Sep 17 00:00:00 2001 From: Fabian Wolf <22625791+fabiwlf@users.noreply.github.com> Date: Thu, 29 Apr 2021 02:25:15 +0200 Subject: [PATCH] macOS: Fix crash when using --tray (fix #527), and invisible icon (fix #942, fix #668) (#1156) This fixes: 1. A startup crash on macOS when using the `--tray` option; see #527. ![image](https://user-images.githubusercontent.com/22625791/115987741-99544600-a5b6-11eb-866a-dadb5640eecb.png) 2. Invisible tray icon on macOS; see #942 and #668. ![image](https://user-images.githubusercontent.com/22625791/115988276-24364000-a5b9-11eb-80c3-561a8a646754.png) Co-authored-by: Ronan Jouchet --- app/src/components/trayIcon.ts | 13 +++++++++++-- docs/api.md | 2 ++ icon-scripts/convertToTrayIcon | 32 ++++++++++++++++++++++++++++++++ src/build/buildIcon.ts | 13 ++++++++----- src/build/buildNativefierApp.ts | 13 ++++++++++++- src/helpers/iconShellHelpers.ts | 17 +++++++++++++++++ 6 files changed, 82 insertions(+), 8 deletions(-) create mode 100755 icon-scripts/convertToTrayIcon diff --git a/app/src/components/trayIcon.ts b/app/src/components/trayIcon.ts index 778e3c0..6e633ea 100644 --- a/app/src/components/trayIcon.ts +++ b/app/src/components/trayIcon.ts @@ -1,6 +1,6 @@ import { app, Tray, Menu, ipcMain, nativeImage, BrowserWindow } from 'electron'; -import { getAppIcon, getCounterValue } from '../helpers/helpers'; +import { getAppIcon, getCounterValue, isOSX } from '../helpers/helpers'; export function createTrayIcon( nativefierOptions, @@ -11,7 +11,16 @@ export function createTrayIcon( if (options.tray) { const iconPath = getAppIcon(); const nimage = nativeImage.createFromPath(iconPath); - const appIcon = new Tray(nimage); + const appIcon = new Tray(nativeImage.createEmpty()); + + if (isOSX()) { + //sets the icon to the height of the tray. + appIcon.setImage( + nimage.resize({ height: appIcon.getBounds().height - 2 }), + ); + } else { + appIcon.setImage(nimage); + } const onClick = () => { if (mainWindow.isVisible()) { diff --git a/docs/api.md b/docs/api.md index f9900c9..42910cb 100644 --- a/docs/api.md +++ b/docs/api.md @@ -620,6 +620,8 @@ Application will stay as an icon in the system tray. Prevents application from b When the optional argument `start-in-tray` is provided, i.e. the application is started using `--tray start-in-tray`, the main window will not be shown on first start. +Limitation: when creating a macOS app using option `--tray`, from a non-macOS build machine, the tray icon (in the menu bar) will be invisible. + #### [basic-auth-username] ``` diff --git a/icon-scripts/convertToTrayIcon b/icon-scripts/convertToTrayIcon new file mode 100755 index 0000000..a9657df --- /dev/null +++ b/icon-scripts/convertToTrayIcon @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# USAGE + +# ./convertToTrayIcon .png +# Example +# ./convertToTrayIcon ~/sample.icns ~/converted.png + +set -e + +SOURCE=$1 +DEST=$2 + +if [ -z "${SOURCE}" ]; then + echo "No source image specified" + exit 1 +fi + +if [ -z "${DEST}" ]; then + echo "No destination specified" + exit 1 +fi + +NAME=$(basename "${SOURCE}") +EXT="${NAME##*.}" + +if [ "${EXT}" == "png" ]; then + cp "${SOURCE}" "${DEST}" + exit 0 +fi + +sips --setProperty format png --resampleHeightWidth "256" "256" "${SOURCE}" --out "${DEST}" diff --git a/src/build/buildIcon.ts b/src/build/buildIcon.ts index 2b79c5b..f45570d 100644 --- a/src/build/buildIcon.ts +++ b/src/build/buildIcon.ts @@ -7,6 +7,7 @@ import { convertToPng, convertToIco, convertToIcns, + convertToTrayIcon, } from '../helpers/iconShellHelpers'; import { AppOptions } from '../options/model'; @@ -72,7 +73,6 @@ export function convertIconIfNecessary(options: AppOptions): void { log.debug( 'Building for macOS and icon is already a .icns, no conversion needed', ); - return; } if (!isOSX()) { @@ -83,12 +83,15 @@ export function convertIconIfNecessary(options: AppOptions): void { } try { - const iconPath = convertToIcns(options.packager.icon); - options.packager.icon = iconPath; - return; + if (!iconIsIcns(options.packager.icon)) { + const iconPath = convertToIcns(options.packager.icon); + options.packager.icon = iconPath; + } + if (options.nativefier.tray) { + convertToTrayIcon(options.packager.icon); + } } catch (error) { log.warn('Failed to convert icon to .icns, skipping.', error); options.packager.icon = undefined; - return; } } diff --git a/src/build/buildNativefierApp.ts b/src/build/buildNativefierApp.ts index 4cdc168..fe863cc 100644 --- a/src/build/buildNativefierApp.ts +++ b/src/build/buildNativefierApp.ts @@ -65,7 +65,18 @@ async function copyIconsIfNecessary( options.packager.platform === 'darwin' || options.packager.platform === 'mas' ) { - log.debug('No copying necessary on macOS; aborting'); + if (options.nativefier.tray) { + //tray icon needs to be .png + log.debug('Copying icon for tray application'); + const trayIconFileName = `tray-icon.png`; + const destIconPath = path.join(appPath, 'icon.png'); + await copyFileOrDir( + `${path.dirname(options.packager.icon)}/${trayIconFileName}`, + destIconPath, + ); + } else { + log.debug('No copying necessary on macOS; aborting'); + } return; } diff --git a/src/helpers/iconShellHelpers.ts b/src/helpers/iconShellHelpers.ts index 48f17c2..457548a 100644 --- a/src/helpers/iconShellHelpers.ts +++ b/src/helpers/iconShellHelpers.ts @@ -9,6 +9,11 @@ const SCRIPT_PATHS = { convertToPng: path.join(__dirname, '../..', 'icon-scripts/convertToPng'), convertToIco: path.join(__dirname, '../..', 'icon-scripts/convertToIco'), convertToIcns: path.join(__dirname, '../..', 'icon-scripts/convertToIcns'), + convertToTrayIcon: path.join( + __dirname, + '../..', + 'icon-scripts/convertToTrayIcon', + ), }; /** @@ -81,3 +86,15 @@ export function convertToIcns(icoSrc: string): string { `${getTempDir('iconconv')}/icon.icns`, ); } + +export function convertToTrayIcon(icoSrc: string): string { + if (!isOSX()) { + throw new Error('macOS is required to convert from a .icns icon'); + } + + return iconShellHelper( + SCRIPT_PATHS.convertToTrayIcon, + icoSrc, + `${path.dirname(icoSrc)}/tray-icon.png`, + ); +}