mirror of
https://github.com/jahruz67/wisp-open.git
synced 2026-08-08 18:14:08 +00:00
11
This commit is contained in:
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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) {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user