Improve branding layout and fix GNOME icon
This commit is contained in:
parent
b6100a0c7b
commit
b1ddf81f4d
|
|
@ -1044,6 +1044,8 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
|
||||||
logoPreviewBorder,
|
logoPreviewBorder,
|
||||||
container.NewPadded(logoPreview),
|
container.NewPadded(logoPreview),
|
||||||
)
|
)
|
||||||
|
previewMin := canvas.NewRectangle(color.NRGBA{A: 0})
|
||||||
|
previewMin.SetMinSize(fyne.NewSize(220, 0))
|
||||||
updateBrandingTitle := func() {}
|
updateBrandingTitle := func() {}
|
||||||
|
|
||||||
menuPreviewSize := func() (int, int) {
|
menuPreviewSize := func() (int, int) {
|
||||||
|
|
@ -1275,11 +1277,14 @@ func buildAuthorMenuTab(state *appState) fyne.CanvasObject {
|
||||||
info := widget.NewLabel("DVD menus are generated using the VideoTools theme and IBM Plex Mono. Menu settings apply only to disc authoring.")
|
info := widget.NewLabel("DVD menus are generated using the VideoTools theme and IBM Plex Mono. Menu settings apply only to disc authoring.")
|
||||||
info.Wrapping = fyne.TextWrapWord
|
info.Wrapping = fyne.TextWrapWord
|
||||||
|
|
||||||
logoPreviewGroup := container.NewVBox(
|
logoPreviewGroup := container.NewMax(
|
||||||
widget.NewLabel("Preview:"),
|
previewMin,
|
||||||
logoPreviewLabel,
|
container.NewVBox(
|
||||||
logoPreviewBox,
|
widget.NewLabel("Preview:"),
|
||||||
logoPreviewSize,
|
logoPreviewLabel,
|
||||||
|
logoPreviewBox,
|
||||||
|
logoPreviewSize,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
logoButtonRow := container.NewHBox(
|
logoButtonRow := container.NewHBox(
|
||||||
|
|
|
||||||
124
internal/utils/desktop_linux.go
Normal file
124
internal/utils/desktop_linux.go
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.leaktechnologies.dev/stu/VideoTools/internal/logging"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EnsureLinuxDesktopEntry installs a user-level desktop entry and icon so GNOME can
|
||||||
|
// associate the running app with a stable icon.
|
||||||
|
func EnsureLinuxDesktopEntry(appID, appName string) {
|
||||||
|
iconPath := findLinuxIconPath()
|
||||||
|
if iconPath == "" {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: icon not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
exe, err := os.Executable()
|
||||||
|
if err != nil || exe == "" {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: executable path unavailable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
home, err := os.UserHomeDir()
|
||||||
|
if err != nil || home == "" {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: home dir unavailable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
iconDir := filepath.Join(home, ".local", "share", "icons", "hicolor", "256x256", "apps")
|
||||||
|
if err := os.MkdirAll(iconDir, 0755); err != nil {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: create icon dir failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
iconTarget := filepath.Join(iconDir, fmt.Sprintf("%s.png", appID))
|
||||||
|
if err := copyFileIfDifferent(iconPath, iconTarget); err != nil {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: icon copy failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
desktopDir := filepath.Join(home, ".local", "share", "applications")
|
||||||
|
if err := os.MkdirAll(desktopDir, 0755); err != nil {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: create desktop dir failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
desktopTarget := filepath.Join(desktopDir, fmt.Sprintf("%s.desktop", appID))
|
||||||
|
desktopContents := fmt.Sprintf(`[Desktop Entry]
|
||||||
|
Name=%s
|
||||||
|
Exec=%s
|
||||||
|
Icon=%s
|
||||||
|
Type=Application
|
||||||
|
Categories=AudioVideo;Video;Utility;
|
||||||
|
Terminal=false
|
||||||
|
StartupWMClass=%s
|
||||||
|
`, appName, exe, appID, appID)
|
||||||
|
|
||||||
|
if err := writeFileIfDifferent(desktopTarget, desktopContents); err != nil {
|
||||||
|
logging.Debug(logging.CatUI, "desktop entry skipped: write failed: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findLinuxIconPath() string {
|
||||||
|
candidates := []string{
|
||||||
|
filepath.Join("assets", "logo", "VT_Icon.png"),
|
||||||
|
}
|
||||||
|
if exe, err := os.Executable(); err == nil {
|
||||||
|
dir := filepath.Dir(exe)
|
||||||
|
candidates = append(candidates, filepath.Join(dir, "assets", "logo", "VT_Icon.png"))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range candidates {
|
||||||
|
if _, err := os.Stat(p); err == nil {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyFileIfDifferent(src, dst string) error {
|
||||||
|
srcInfo, err := os.Stat(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if dstInfo, err := os.Stat(dst); err == nil {
|
||||||
|
if srcInfo.Size() == dstInfo.Size() && srcInfo.ModTime().Equal(dstInfo.ModTime()) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer in.Close()
|
||||||
|
|
||||||
|
out, err := os.Create(dst)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := io.Copy(out, in); err != nil {
|
||||||
|
out.Close()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := out.Close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chtimes(dst, srcInfo.ModTime(), srcInfo.ModTime())
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeFileIfDifferent(path, contents string) error {
|
||||||
|
if existing, err := os.ReadFile(path); err == nil {
|
||||||
|
if strings.TrimSpace(string(existing)) == strings.TrimSpace(contents) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os.WriteFile(path, []byte(contents), 0644)
|
||||||
|
}
|
||||||
6
internal/utils/desktop_other.go
Normal file
6
internal/utils/desktop_other.go
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package utils
|
||||||
|
|
||||||
|
// EnsureLinuxDesktopEntry is a no-op on non-Linux platforms.
|
||||||
|
func EnsureLinuxDesktopEntry(appID, appName string) {}
|
||||||
2
main.go
2
main.go
|
|
@ -6530,6 +6530,8 @@ func runGUI() {
|
||||||
// Initialize UI colors
|
// Initialize UI colors
|
||||||
ui.SetColors(gridColor, textColor)
|
ui.SetColors(gridColor, textColor)
|
||||||
|
|
||||||
|
utils.EnsureLinuxDesktopEntry("com.leaktechnologies.videotools", "VideoTools")
|
||||||
|
|
||||||
a := app.NewWithID("com.leaktechnologies.videotools")
|
a := app.NewWithID("com.leaktechnologies.videotools")
|
||||||
|
|
||||||
// Always start with a clean slate: wipe any persisted app storage (queue or otherwise)
|
// Always start with a clean slate: wipe any persisted app storage (queue or otherwise)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user