Skip to content

Commit

Permalink
Merge pull request #265 from andydotxyz/feature/editormenu
Browse files Browse the repository at this point in the history
Link to app editor Fysion if it is installed
  • Loading branch information
andydotxyz authored Oct 27, 2024
2 parents f801dbb + a0d58c6 commit d475dd5
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 3 deletions.
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

0 comments on commit d475dd5

Please sign in to comment.