Adventures in Desktop App development II: Revenge of the Gopher

Adventures in Desktop App development II: Revenge of the Gopher

Wat

Few weeks ago I posted about how I wanted to see what it was like to work with desktop apps.

I ended up saying that I was going to try Vala, well I did not go too far with that.

If just feels like the community is not there, but I might try again in a few months.

What I did instead was to post the same article on dev.to and I got some answers to the post, and a few nice suggestions came in:

  1. Try Flutter
  2. Try Fyne
  3. Try Tauri

All of those would require me to (re)learn another language.

Flutter

flutter-lockup.png Flutter uses Dart, a hybrid between Typescript and Java, but better. It looks like has loads of momentum going and I have to say the VSCode extension for it works flawlessly and it is just amazing.

I went over some tutorials about the language itself but I got bored quite quickly and I decided to give up for now and come back later.

Fyne

fyne.png

Fyne was fine. It uses Go, which is a language I have used in one of my previous companies, so I decided to dust it off and try it out.

I worked for a few days on a TODO App with a persistence layer, something I had done with AvaloniaUI.

It just not doing anything for me. I mean it does work and ticks a lot of boxes for me: Screenshot 2022-10-07 at 09.10.43.png

  • Small binary
  • Easy to build with
  • not too much code to handle basic things

I joined the discord and asked about things, but it kind of felt like it is just the main dev there helping out and most of the time is kind of "find your own solution" or RTFM, which was exactly the opposite with the community of AvaloniaUI.

What didn't really work was how hard it feels to do simple things, like binding a list of objects to a listview on the actual app UI.

list := widget.NewListWithData(
        data,
        func() fyne.CanvasObject {
        // in this function you design what your item UI looks like
            c := widget.NewCheck("", nil)
            return container.New(layout.NewBorderLayout(nil, nil, nil, c), c, widget.NewLabel(""))
        },
        func(di binding.DataItem, co fyne.CanvasObject) {
        // here will run for each item on the list using the result of the other function as canvas to paint on kind of thing
            t := todoFromDataItem(di)
            container := co.(*fyne.Container)
            label := container.Objects[1].(*widget.Label)
            check := container.Objects[0].(*widget.Check)
            label.Bind(binding.BindString(&t.Description))
            check.Bind(binding.BindBool(&t.Done))
        },
    )

// and to cast your dataitem into your struct you need to do something like this
func todoFromDataItem(item binding.DataItem) *models.Todo {
    u, _ := item.(binding.Untyped)
    v, _ := u.Get()
    t, _ := v.(models.Todo)
    return &t
}

There is no simple way of removing items for lists, nor to update a single one on that list. I think the main problem is that the examples on the main docs: List and ListWithData are using primitive types, and not too many details are given.

Even looking around on the extension libs fyne-x there isn't much for this simple use case.

The layout docs are a bit confusing and the examples are a bit simplistic, so you cant really do a simple operations like stretch a widget to occupy the whole available space, unless you combine loads of containers and make your code a bit messy.

I asked if there was a plan to use some sort of XAML kind of language to define UI structure and I was told no, which is fair enough

I guess there are not enough people working on enough complex scenarios to make it worthwhile to build more complex and dev friendly ways of doing things.

It is a pity though as the code looks neat and the app runs smoothly and looks gorgeous.

Will come back to that in the future I am sure, and maybe will edit the main doc to add the simple case scenario of biding a list of struct to the UI for the next person like me.

Tauri

Tauri looks like electron on steroids, and it uses Rust which I am in a bit of a love/hate relationship with and I need to refresh at some point.

Other things

I really want to like Avalonia and use it more, so I tried out to make packaging and publishing the Muscurd-i - Password Manager binaries using GitHub Actions.

I had the problem that cross-building the app with Linux it would always open up a console underneath the app, that does not seem to happen if you cross-build with Windows, so I did that, and it worked like a charm.

What now

Now I am a bit in two minds, I might give a bit more of a chance to Avalonia with a project I tried to do 600 times already: A Football Manager game but focussed on Transfer Market. I started that in:

That is a lot of tries.... maybe this time is the one, as they say the 10th is the charm.

bye for now.