This commit is contained in:
jahruz67
2026-05-09 10:59:26 -07:00
parent 4ea6675450
commit 52cf789eab
8 changed files with 98 additions and 33 deletions
+1 -1
View File
@@ -476,7 +476,7 @@ func (a *App) startupHeadless() {
} }
// Ensure desktop integration for Wayland portals // Ensure desktop integration for Wayland portals
if err := platform.EnsureDesktopFile(); err != nil { if err := platform.EnsureDesktopFile(tray.DefaultIconBytes()); err != nil {
logger.Error("Failed to ensure desktop file: %v", err) logger.Error("Failed to ensure desktop file: %v", err)
} }
+28 -7
View File
@@ -15,31 +15,52 @@ const baseDesktopFileTemplate = `[Desktop Entry]
Type=Application Type=Application
Name=WIS Free V3 Name=WIS Free V3
%s %s
Icon=%s
StartupWMClass=%s
Terminal=false Terminal=false
Categories=Utility; Categories=Utility;
` `
const autostartDesktopFileTemplate = baseDesktopFileTemplate + "X-GNOME-Autostart-enabled=true\n" const autostartDesktopFileTemplate = `[Desktop Entry]
Type=Application
Name=WIS Free V3
%s
Icon=wis-free-v3
StartupWMClass=wis-free-v3
Terminal=false
Categories=Utility;
X-GNOME-Autostart-enabled=true
`
func EnsureDesktopFile() error { func EnsureDesktopFile(iconBytes []byte) error {
home, err := os.UserHomeDir() home, err := os.UserHomeDir()
if err != nil { if err != nil {
return err return err
} }
appsDir := filepath.Join(home, ".local", "share", "applications") appsDir := filepath.Join(home, ".local", "share", "applications")
if err := os.MkdirAll(appsDir, 0755); err != nil { if err := os.MkdirAll(appsDir, 0755); err != nil {
return err return err
} }
desktopPath := filepath.Join(appsDir, appName+".desktop") desktopPath := filepath.Join(appsDir, appName+".desktop")
exePath, err := getExecutablePath() exePath, err := getExecutablePath()
if err != nil { if err != nil {
return err return err
} }
content := fmt.Sprintf(baseDesktopFileTemplate, desktopExecField(exePath)) // Write icon to local pixmaps so the desktop file Icon= field resolves
pixmapsDir := filepath.Join(home, ".local", "share", "pixmaps")
if err := os.MkdirAll(pixmapsDir, 0755); err != nil {
return err
}
iconPath := filepath.Join(pixmapsDir, appName+".png")
if err := os.WriteFile(iconPath, iconBytes, 0644); err != nil {
return fmt.Errorf("failed to write icon to pixmaps: %w", err)
}
content := fmt.Sprintf(baseDesktopFileTemplate, desktopExecField(exePath), appName, appName)
return os.WriteFile(desktopPath, []byte(content), 0644) return os.WriteFile(desktopPath, []byte(content), 0644)
} }
+2 -2
View File
@@ -31,6 +31,6 @@ func IsProcessRunning(pid int) bool {
return linux.IsProcessRunning(pid) return linux.IsProcessRunning(pid)
} }
func EnsureDesktopFile() error { func EnsureDesktopFile(iconBytes []byte) error {
return linux.EnsureDesktopFile() return linux.EnsureDesktopFile(iconBytes)
} }
+1 -1
View File
@@ -31,7 +31,7 @@ func IsProcessRunning(pid int) bool {
return windows.IsProcessRunning(pid) return windows.IsProcessRunning(pid)
} }
func EnsureDesktopFile() error { func EnsureDesktopFile(iconBytes []byte) error {
// Not applicable on Windows // Not applicable on Windows
return nil return nil
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

+10 -22
View File
@@ -10,7 +10,6 @@ import (
"os" "os"
"runtime" "runtime"
"strings" "strings"
"sync"
"wis-free-v3/internal/config" "wis-free-v3/internal/config"
"wis-free-v3/internal/logger" "wis-free-v3/internal/logger"
@@ -22,6 +21,9 @@ import (
//go:embed icon.ico //go:embed icon.ico
var iconData []byte var iconData []byte
//go:embed icon.png
var iconPNGData []byte
//go:embed icon_recording.png //go:embed icon_recording.png
var iconRecordingData []byte var iconRecordingData []byte
@@ -152,30 +154,16 @@ func buildTooltip(app App) string {
return trayLabel + " - " + shortcut + " to record" return trayLabel + " - " + shortcut + " to record"
} }
var (
defaultIconOnce sync.Once
defaultIconBytes []byte
)
func getDefaultIcon() []byte { func getDefaultIcon() []byte {
if runtime.GOOS != "linux" { if runtime.GOOS == "linux" {
return iconData return iconPNGData
} }
return iconData
}
defaultIconOnce.Do(func() { // DefaultIconBytes returns the raw default icon bytes for the current platform.
pngData, err := icoToPNG(iconData) func DefaultIconBytes() []byte {
if err != nil { return getDefaultIcon()
logger.Error("Failed to convert tray icon to PNG for Linux: %v", err)
defaultIconBytes = iconData
return
}
defaultIconBytes = pngData
})
if len(defaultIconBytes) == 0 {
return iconData
}
return defaultIconBytes
} }
func icoToPNG(data []byte) ([]byte, error) { func icoToPNG(data []byte) ([]byte, error) {
+14
View File
@@ -0,0 +1,14 @@
//go:build linux
package tray
/*
#include <glib.h>
*/
import "C"
import "unsafe"
func init() {
cstr := C.CString("wis-free-v3")
defer C.free(unsafe.Pointer(cstr))
C.g_set_prgname(cstr)
}
+42
View File
@@ -56,6 +56,43 @@ fi
# 2. Check for Linux dependencies # 2. Check for Linux dependencies
echo "[1/3] Checking system dependencies..." echo "[1/3] Checking system dependencies..."
MISSING_DEPS=0 MISSING_DEPS=0
# 2a. GNOME tray icon support check (before build — avoids launching app if this will fail)
# AppIndicator icons need the GNOME Shell extension on GNOME desktop environments.
# Other DEs (KDE Plasma, XFCE, Cinnamon, etc.) usually support them natively.
if [ "$XDG_CURRENT_DESKTOP" = "GNOME" ] || [ "$XDG_CURRENT_DESKTOP" = "ubuntu:GNOME" ]; then
if ! gnome-extensions show appindicator@altamirano.fabio &>/dev/null; then
echo ""
echo "==============================================================="
echo " ERROR: GNOME AppIndicator extension is not installed"
echo "==============================================================="
echo ""
echo " GNOME does not show system tray icons without this extension."
echo " The app will run but the tray icon will be invisible."
echo ""
if command_exists dnf; then
echo " Install it with:"
echo ""
echo " sudo dnf install gnome-shell-extension-appindicator"
echo ""
elif command_exists apt-get; then
echo " Install it with:"
echo ""
echo " sudo apt install gnome-shell-extension-appindicator"
echo ""
else
echo " Install the 'gnome-shell-extension-appindicator' package"
echo " for your distribution."
echo ""
fi
echo " Then log out and back in, and enable it in:"
echo " Settings > Extensions > AppIndicator and KStatusNotifierItem Support"
echo ""
echo "==============================================================="
exit 1
fi
fi
DEPS=("gcc" "pkg-config") DEPS=("gcc" "pkg-config")
for dep in "${DEPS[@]}"; do for dep in "${DEPS[@]}"; do
@@ -200,6 +237,10 @@ if [ ! -f "$EXECUTABLE" ]; then
exit 1 exit 1
fi fi
# wails build sometimes auto-launches the binary on Linux — kill it so it
# doesn't block the terminal while we ask about installation.
pkill -f "$EXECUTABLE" 2>/dev/null || true
echo "[3/3] Build successful!" echo "[3/3] Build successful!"
echo " Output: $EXECUTABLE" echo " Output: $EXECUTABLE"
echo "" echo ""
@@ -232,6 +273,7 @@ Comment=Voice Dictation App
Exec=/usr/local/bin/$APP_NAME Exec=/usr/local/bin/$APP_NAME
TryExec=/usr/local/bin/$APP_NAME TryExec=/usr/local/bin/$APP_NAME
Icon=$APP_NAME Icon=$APP_NAME
StartupWMClass=$APP_NAME
Terminal=false Terminal=false
Categories=Utility;Audio; Categories=Utility;Audio;
EOF EOF