Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link to app editor Fysion if it is installed #265

Merged
merged 7 commits into from
Oct 27, 2024
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
7 changes: 7 additions & 0 deletions icons.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ type AppData interface {
Categories() []string // Categories is a list of categories that the app fits in (platform specific)
Hidden() bool // Hidden specifies whether instances of this app should be hidden
Icon(theme string, size int) fyne.Resource // Icon returns an icon for the app in the requested theme and size

Source() *AppSource // Source will return the location of the app source code from metadata, if known
}

// AppSource represents the source code informtion of an application
type AppSource struct {
Repo, Dir string
}

// ApplicationProvider describes a type that can locate icons and applications for the current system
Expand Down
26 changes: 23 additions & 3 deletions internal/icon/fdo.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ type fdoApplicationData struct {
categories []string
hide bool
iconCache fyne.Resource

source *fynedesk.AppSource
}

// Name returns the name associated with an fdo app
Expand All @@ -55,7 +57,7 @@ func (data *fdoApplicationData) IconName() string {
return data.iconName
}

// IconPath returns the path of the icon that an fdo app wishes to use
// Icon returns the path of the icon that an fdo app wishes to use
func (data *fdoApplicationData) Icon(theme string, size int) fyne.Resource {
if data.iconCache != nil {
return data.iconCache
Expand All @@ -73,6 +75,10 @@ func (data *fdoApplicationData) Icon(theme string, size int) fyne.Resource {
return data.iconCache
}

func (data *fdoApplicationData) Source() *fynedesk.AppSource {
return data.source
}

// extractArgs sanitises argument parameters from an Exec configuration
func extractArgs(args []string) []string {
var ret []string
Expand Down Expand Up @@ -106,7 +112,7 @@ func (data *fdoApplicationData) Run(env []string) error {
return cmd.Start()
}

func (data fdoApplicationData) mainCategory() string {
func (data *fdoApplicationData) mainCategory() string {
if len(data.Categories()) == 0 {
return fallbackCategory
}
Expand Down Expand Up @@ -457,7 +463,21 @@ func newFdoIconData(desktopPath string) fynedesk.AppData {
if strings.HasPrefix(line, "[") {
currentSection = line
}
if currentSection != "[Desktop Entry]" {
switch currentSection {
case "[X-Fyne Source]":
if fdoApp.source == nil {
fdoApp.source = &fynedesk.AppSource{}
}
if strings.HasPrefix(line, "Repo=") {
name := strings.SplitAfter(line, "=")
fdoApp.source.Repo = name[1]
}
if strings.HasPrefix(line, "Dir=") {
name := strings.SplitAfter(line, "=")
fdoApp.source.Dir = name[1]
}
case "[Desktop Entry]": // fall through to code below
default:
continue
}
if strings.HasPrefix(line, "Name=") {
Expand Down
10 changes: 10 additions & 0 deletions internal/icon/fdo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ func TestFdoIconHicolorFallbackScalable(t *testing.T) {
assert.Equal(t, true, exists(data))
}

// applications/com.fyne.app.desktop
func TestFdoIconSource(t *testing.T) {
setTestEnv(t)
data := NewFDOIconProvider().(*fdoIconProvider).lookupApplication("app2")

assert.NotNil(t, data.Source())
assert.Equal(t, "https://example.com/repo", data.Source().Repo)
assert.Equal(t, "cmd/dir", data.Source().Dir)
}

// applications/app7.desktop and icons/default_theme/apps/16x16/app7.png
func TestFdoLookupDefaultThemeDifferentSize(t *testing.T) {
setTestEnv(t)
Expand Down
4 changes: 4 additions & 0 deletions internal/icon/macos.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ func (m *macOSAppBundle) Run([]string) error {
return exec.Command("open", "-a", m.runPath).Start()
}

func (m *macOSAppBundle) Source() *fynedesk.AppSource {
return nil
}

func loadAppBundle(name, path, category string) fynedesk.AppData {
buf, err := os.Open(filepath.Join(path, "Contents", "Info.plist"))
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions internal/icon/testdata/applications/com.fyne.app.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,7 @@
Name=App2
Exec=app2
Icon=app2

[X-Fyne Source]
Repo=https://example.com/repo
Dir=cmd/dir
7 changes: 7 additions & 0 deletions internal/ui/bar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"image/color"
"testing"

"fyshos.com/fynedesk"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/test"
Expand Down Expand Up @@ -40,6 +42,11 @@ func (d *dummyIcon) Run([]string) error {
return nil
}

func (d *dummyIcon) Source() *fynedesk.AppSource {
// no-op
return nil
}

func testBar(icons []string) *bar {
testBar := newBar(wmTest.NewDesktopWithWM(&embededWM{}))
testBar.children = []fyne.CanvasObject{} // remove divider, then we add it again later
Expand Down
85 changes: 85 additions & 0 deletions internal/ui/baricon.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ package ui

import (
"image/color"
"os"
"os/exec"
"os/user"
"path/filepath"

"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
deskDriver "fyne.io/fyne/v2/driver/desktop"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"

Expand Down Expand Up @@ -143,6 +149,13 @@ func (bi *barIcon) TappedSecondary(ev *fyne.PointEvent) {
}

items := []*fyne.MenuItem{addRemove}
editor := editorPath()
if app.Source() != nil && editor != "" {
items = append(items, fyne.NewMenuItem("Edit", func() {
editApp(app, editor)
}))
}

fynedesk.Instance().ShowMenuAt(fyne.NewMenu("", items...), ev.AbsolutePosition)
}

Expand All @@ -154,9 +167,81 @@ func (bi *barIcon) CreateRenderer() fyne.WidgetRenderer {
return render
}

func cloneRepo(src *fynedesk.AppSource, path string) error {
spin := widget.NewActivity()
prop := canvas.NewRectangle(color.Transparent)
prop.SetMinSize(fyne.NewSquareSize(56))

w := fyne.CurrentApp().Driver().(deskDriver.Driver).CreateSplashWindow()
w.SetContent(
container.NewBorder(nil, widget.NewLabel("Downloading..."), nil, nil,
container.NewStack(prop, spin)))
spin.Start()
w.Show()

defer func() {
w.Hide()
spin.Stop()
}()

cmd := exec.Command("git", "clone", src.Repo, path)
return cmd.Run()
}

func editApp(app fynedesk.AppData, editor string) {
root := sourceRoot()
srcDir := filepath.Join(root, app.Name())

if !exists(srcDir) {
if !exists(root) {
err := os.MkdirAll(root, 0755)
if err != nil {
fyne.LogError("Failed to make source root", err)
return
}
}

err := cloneRepo(app.Source(), srcDir)
if err != nil {
fyne.LogError("Error cloning the app source", err)
return
}
}

cmd := exec.Command(editor, srcDir)
err := cmd.Start()

if err != nil {
fyne.LogError("Failed to start app editor: "+editor, err)
}
}

func newBarIcon(res fyne.Resource, appData fynedesk.AppData, winData *appWindow) *barIcon {
barIcon := &barIcon{resource: res, appData: appData, windowData: winData}
barIcon.ExtendBaseWidget(barIcon)

return barIcon
}

func editorPath() string {
fysion, err := exec.LookPath("fysion")
if err == nil && fysion != "" {
return fysion
}

return ""
}

func exists(path string) bool {
_, err := os.Stat(path)
return err == nil
}

func sourceRoot() string {
u, err := user.Current()
if err != nil {
return ""
}

return filepath.Join(u.HomeDir, "FysionApps")
}
4 changes: 4 additions & 0 deletions modules/status/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,3 +184,7 @@ func (n *networkApp) Hidden() bool {
func (n *networkApp) Icon(theme string, size int) fyne.Resource {
return wmtheme.WifiIcon
}

func (n *networkApp) Source() *fynedesk.AppSource {
return nil
}
4 changes: 4 additions & 0 deletions test/icons.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ func (tad *testAppData) Icon(theme string, size int) fyne.Resource {
return wmTheme.IconifyIcon
}

func (tad *testAppData) Source() *fynedesk.AppSource {
return nil
}

type testAppProvider struct {
apps []fynedesk.AppData
}
Expand Down