Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions electron-builder.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ const config: Configuration = {
target: [
{ target: 'nsis', arch: ['x64'] }
],
icon: 'resources/icon.ico'
icon: 'resources/icon.ico',
publisherName: 'Wrkmark',
legalTrademarks: 'Wrkmark'
},

linux: {
Expand All @@ -75,7 +77,9 @@ const config: Configuration = {
oneClick: false,
allowToChangeInstallationDirectory: true,
createDesktopShortcut: true,
createStartMenuShortcut: true
createStartMenuShortcut: true,
shortcutName: 'Wrkmark',
uninstallDisplayName: 'Wrkmark'
},

publish: null,
Expand Down
13 changes: 13 additions & 0 deletions resources/ICONS_TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Icon TODO
Windows tray requires icon.ico (16x16 and 32x32).
Current: using programmatic nativeImage fallback.

To create proper icon.ico:
1. Have a designer create 1024x1024 icon.png
2. Use ImageMagick:
convert icon.png -resize 256x256 \
-define icon:auto-resize=256,128,64,48,32,16 \
resources/icon.ico
3. Or use online converter: convertio.co/png-ico/

Until then, the emerald fallback is used on Windows.
70 changes: 65 additions & 5 deletions src/main/tray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,77 @@
* What this is NOT: standard main process lifecycle management (see index.ts).
*/

import { resolve } from 'path'
import path, { resolve } from 'path'
import { Tray, Menu, BrowserWindow, app, nativeImage } from 'electron'
import { getObserver } from './observer-instance'

let tray: Tray | null = null

export function createTray(window: BrowserWindow): Tray {
const iconPath = resolve(__dirname, '../../resources/icon.png')
const icon = nativeImage.createFromPath(iconPath)
function getTrayIcon(): Electron.NativeImage {
if (process.platform === 'win32') {
// Better approach: use existing png, resize for tray
const pngPath = path.join(
process.env.VITE_PUBLIC ?? __dirname,
'../resources/icon.png'
)
try {
let icon = nativeImage.createFromPath(pngPath)
if (icon.isEmpty()) {
const fallbackPngPath = resolve(__dirname, '../../resources/icon.png')
icon = nativeImage.createFromPath(fallbackPngPath)
}
if (!icon.isEmpty()) {
// Resize to 16x16 for Windows tray
return icon.resize({ width: 16, height: 16 })
}
} catch { /* fall through */ }

// Windows needs .ico format for tray
// Try to load icon.ico, fallback to generating
// from icon.png via nativeImage
const icoPath = path.join(
process.env.VITE_PUBLIC ?? __dirname,
'../resources/icon.ico'
)

try {
let icon = nativeImage.createFromPath(icoPath)
if (icon.isEmpty()) {
const fallbackIcoPath = resolve(__dirname, '../../resources/icon.ico')
icon = nativeImage.createFromPath(fallbackIcoPath)
}
if (!icon.isEmpty()) return icon
} catch {
// ico not found, fall through
}

// Fallback: create a small icon programmatically
// A 16x16 emerald square as data URI
const iconDataURL = 'data:image/png;base64,' +
// 16x16 emerald green square
'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/' +
'9hAAAABmJLR0QA/wD/AP+gvaeTAAAASUlEQVQ4jWNg' +
'GJRAYWHh/4SEhP9MS0v/MzAwMDAwMjL+ZxgFgx8AAA' +
'AA//8DABZyAv8jPe7RAAAAAElFTkSuQmCC'

return nativeImage.createFromDataURL(iconDataURL)
}

tray = new Tray(icon)
// Mac and Linux use png
const iconPath = path.join(
process.env.VITE_PUBLIC ?? __dirname,
'../resources/icon.png'
)
let icon = nativeImage.createFromPath(iconPath)
if (icon.isEmpty()) {
const fallbackPath = resolve(__dirname, '../../resources/icon.png')
icon = nativeImage.createFromPath(fallbackPath)
}
return icon
}

export function createTray(window: BrowserWindow): Tray {
tray = new Tray(getTrayIcon())
tray.setToolTip('Wrkmark')

const updateContextMenu = (): void => {
Expand Down
10 changes: 10 additions & 0 deletions src/main/window-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ async function getActiveAppWindows(): Promise<{
const child = spawn('powershell', [
'-NoProfile',
'-NonInteractive',
'-WindowStyle', 'Hidden',
'-Command',
script
])
Expand All @@ -363,6 +364,15 @@ async function getActiveAppWindows(): Promise<{
.replace(/[\x00-\x1F\x7F]/g, '')
.substring(0, 100)

// Sanity check: if we somehow still get powershell
// as the result, something is wrong — skip this tick
if (safeProcessName === 'powershell' ||
safeProcessName === 'pwsh' ||
safeProcessName === 'powershell_ise') {
resolve(null)
return
}

resolve({
bundleId: safeProcessName,
appName: safeProductName
Expand Down
Loading