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 <ronan@jouchet.fr>
This commit is contained in:
Fabian Wolf 2021-04-29 02:25:15 +02:00 committed by GitHub
parent 41b208fcb7
commit cf8e51e7ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 82 additions and 8 deletions

View File

@ -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()) {

View File

@ -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]
```

32
icon-scripts/convertToTrayIcon Executable file
View File

@ -0,0 +1,32 @@
#!/usr/bin/env bash
# USAGE
# ./convertToTrayIcon <input png or icns> <outfilename>.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}"

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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`,
);
}