Something like SwiftUI but open source and targeting GTK4 would be pretty close to my "dream framework" for cross-platform desktop UI.
I will admit, Swift syntax is an acquired taste, but once you're familiar with all of the concepts (and understand that some design decisions were made for Objective-C interoperability), then it's a very usable language. To be frank, the only thing that stops me from using Swift is the fact that Linux support isn't as good as on Apple platforms. But if I am targeting nothing but Apple platforms, then Swift is probably the best choice, just for SwiftUI and SPM alone.
Why not go with Qt's QML?
As someone who works with QML daily, I had the same question. The work is already done. Why write a common UI backend in swift when you can have the whole thing common using QML/Qt.
It’s the best way to write native Multiplatform apps at the moment. It just is.
I’m not entirely convinced that multiplatform UI is a good idea for anything other than the simplest of applications. It always ends up looking out of place on at least one platform and sometimes all of them.
It just takes an effort to make Qt apps look and behave native. This has been one of the goals with my new note-taking app, and I think it looks pretty native (at least on macOS): https://www.get-plume.com/
Hey, I don't use your app because it's too limited for my "PKMS" needs (I use trilium notes instead), but I appreciate that you make being "native and fast" a distinguishing feature (vs all the other electron based alternatives boiling the oceans).
Thanks for the feedback, although the app isn’t released yet so you should at least give it a shot once it’s out.
I do try to strike a balance between flexibility and ease of use. I think Notion is too complicated (yet very flexible/powerful). With Plume, the focus is to be able to organize your thoughts in a powerful way, effortlessly. Sign up to the waitlist and try it once it’s out. Much more is coming soon.
I wrote about the problem space extensively on this site before, tl;dr, to me the issue lies in the fact that most of the contenders aim to manage data/knowledge/notes as "types" (for categorization, templating and derivation/re-purposing), but, to my knowledge, only trilium is enabling that with a "sound" design. Notion is exposing a lot of incidental complexity due to its "unsoundness".
Just read this comment of yours[1]. Plume is aimed to be much simpler than Trilium, I want a non-tech-savvy 40-year-old mom that doesn't know what Kanban is to be able to happily use it as someone that is tech-savvy that knows all about Kanbans. Something that just works for many people, like Apple Notes but with a more advanced editor and features.
[1] https://news.ycombinator.com/item?id=39034749
Looks gorgeous. Is it QML or pure Qt?
Thanks! It’s both. The model side and logic is written in C++ while the view is written in QML. That way I get the best of both worlds, the performance of C++ with the ease of use, flexibility, animations, etc of QML. It’s worth noting that most Qt Quick components and much of QML code is compiled to C++, so even code on that side is performant.
Amazing. This is very inspiring, thanks.
For me, QML, while expressive, had a lot of rough edges.
If most of your logic is inside the C++ backend, its JS engine is just useless overhead. If you do something like lite data wrangling in QML, or worse, try to adapt existing JS libraries for it, it quickly becomes a nightmare of standard JS weirdness, non-compliance with normal JS, and just outright ridiculous and difficult to diagnose issues like data getting passed by reference from the previous page and that page getting popped off the stack, resulting in error.
And besides that, QML tooling is virtually non-existent. Major code editors don't even ship basic syntax highlighting for it out-of-the-box, the linter doesn't catch anything useful forcing you back into manual testing, and recently added language-server is at best a little useless and at worst impossible to get working correctly because your components live inside the build container and cannot be installed on the host without risk to system stability (Ubuntu Touch Clickable and Lomiri.Components).
If something like that was possible for Qt, I'd probably switch in a heartbeat. If our modern programing languages are finally expressive enough to write sane reactive UI and statically verify parts of your logic, why keep relying on the unverifiable and slow DSL?
Well, if most of your logic in C++, what's the problem then? For my app[1] most of the logic in C++ but there's still a good amount of logic in JS (out of laziness or ease). BTW, much of QML code is compiled to C++ these days[2]
This is very true, it's quite difficult to diagnose issues in QML, and it doesn't seem to me like Qt ships debugger tools for errors as available for C++ when a program crashes.
I relate to your issues with syntax highlighting (although the linter is good imo). Also auto-complete is pretty bad in Qt Creator for QML.
I wonder how feasible it is to integrate Typescript into QML rather than JS.
But I think that while all these issues should be addressed, developing with C++ and QML is the most joyful combination I've experienced so far for GUI development (I also developed in React and React Native).
[1] https://www.get-plume.com/
[2] https://www.qt.io/blog/the-new-qtquick-compiler-technology
It just is is a relative term, for example - I already know SwiftUI.
I hate Qt, the apps look non-native and don't obey Ubuntu's appearance settings and fonts.
Nobody bats an eye when apps built for Windows don't adhere to its design patterns. Some goes to a large extent for MacOS. I swear Linux users have the strangest obsessions..
Mac users are worse than ordinary Linux users I think (writing this as a Linux user who right now uses a Mac :-)
As an ordinary Linux user I at least welcome all applications with bonus points if they are well integrated into KDE.
Maybe the Gnome crowd is more picky?
Longtime mac users definitely have a preference for apps that are not only native, but designed to be good citizens of the mac desktop by abiding by its UI conventions, feature progressive disclosure of power user features, etc.
To be fair, even Microsoft isn't consistent on what people feel like native should look like. I'm primary a linux/mac user as home, but at work I have to use Windows 11. It is surprising that Microsoft gets paid the Windows given that the control panel has a new updated UI that meshes with Windows 11 fairly well, but then you open up something in control panel and need to access more advanced features and your greeted by a UI that I am pretty sure is from Vista or 7. A standard winforms UI looks totally different from a WinUI. Yes, technically they are all native, but they all look completely different.
Qt apps arguably look more "native" on average than anything else I've seen, considering that it mimics the native look and feel of the target platform for a wide range of them. Now compare that to Gtk, which just leaves you with gnome-style shortcuts and controls on Windows/Mac, and nothing in the area of desktop integration if that's a feature gnome doesn't have (e.g. tray).
Sounds like Compose and Kotlin, although multiplatform still being more in a beta stage.
Kotlin is probably the most similar in syntax to Swift out of the languages I’ve written, but it’s somewhat quirky and opinionated and I’m not sure I agree with its opinions (lack of guard statement, no ternary ifs, etc). Also it involves Java ecosystem stuff like Gradle which can drive a person mad sometimes.
Interesting. Why is that? I've been out of the Java loop for some years (although I did a fair amount of work with it earlier), so not up to date with this stuff.
Gradle combines the inscrutable magic of Maven with the unpredictable structurelessness of Ant in one bundle of pain.
What really irritates me about gradle is that they have significant API churn but there's still five ways to do everything.
I will never pass up an opportunity to heap scorn on Gradle. I agree with everything said so far, except I would argue Ant was easier to use.
Every single Gradle build system I have encountered in the wilds of GitHub has been broken on Fedora. I eventually realised it works if I run it in an Ubuntu container (using "toolbox"). So it's only portable if you bundle up the OS with your build system.
Now it should be portable. It's written in a JVM language and every Gradle project I have seen commits a copy of the Gradle JAR to its GitHub repo, which gives me those arbitrary code execution heebie-jeebies.
ooh where do I start... Let's see:
1. Every single gradle script is a unique snowflake of mishmashed plugins and custom functions
2. Gradle likes to pretend it is declarative, but as people very quickly learn it really isn't.
3. The one thing a build system is expected to do is be reliable in face of changing platform version, libraries and plugins. But gradle, being built on top a language on top of JDK itself has a Compatibility Matrix[0] that one has to be aware of. Often when upgrading a project you have to update JDK and gradle in explicit order, sometimes multiple times.
4. Speaking of which, did you know that gradle, being designed to build java projects does not even manage multiple JDK versions?!
5. untyped groovy means you're forever left wondering whether what you wrote is actually correct until you run it, at which point it fails with excellent errors that tell you nothing. Granted, this situation has improved in recent days, but a jump from 90th floor compared to 100th is still painful.
6. Every single fkin thing that gradle offers can be done in half dozen ways and nothing tells you which way is better or why. Ex.A: is it providedCompile or implementation? Yes, one is intended to be a replacement for another, and no, they are /not/ same.
7. The 'One Nice Thing' gradle had going for is that it bootstraps itself. But look, if want to add gradle to a 'new' project, you have to install it to your system first and use it to add the wrapper. But after that, you are expected to use the wrapper. Nobody tells you that, you just have to figure it out. Oh and when it comes time to upgrade the wrapper version, you're to use the wrapper itself, not the system gradle, again mentioned nowhere, and if you try updating the wrapper using system gradle, the error helps exactly not.
8. Gradle takes free reign in breaking APIs /between minor versions/. WTF!
9. gradle starts a daemon to cache stuff, which is nice I guess. Except when you don't want it to run a daemon, so you tell it with `--no-daemon`. Do you know what that does? It starts a daemon, runs the build and shuts it down. This may not sound like a big deal, but it is just cherry on top of this shitcacke that tells you just how thoughtfully and well designed gradle is. /s
/endrant
[0]: https://docs.gradle.org/current/userguide/compatibility.html
What about toolchains?
My dealbreaker for kotlin is that it’s possible to call a throwing function with no indication it will throw. In swift, the compiler forces every throwing function do be inside a try/catch block or be called by another throwing function.
I also am extremely unhappy that those functions can be 16 layers deep somewhere in a lib and cause your app to blowup.
There are entire languages built with unchecked exceptions, Python, Ruby, Nodejs and most recent ones. Even with checked exceptions you can write code and miss to throw or declare an exception somewhere so ultimately the developer has to deal with exceptions somehow.
Yep, this is a problem I’ve encountered several times. Even if none of your own code has unhandled throws, you’ll inevitably get crash reports coming in from fooLib throwing an exception somewhere because the moon was in the wrong phase.
There is only one reason to use Gradle instead of Maven, being stuck on Android.
If I had a nickel for every time I got excited about something with experimental multiplatform support...
The Kotlin platform looks good and I've kept an eye on it, but the problem is, if I have to start working on an app now, it's still kind of scary, as you're basically just placing a bet on a horse race of which one will mature the fastest down the road.
At a previous job, I decided to adopt React Native in its early stages for a project. By some miracle (and with a lot of rolling-our-own) it managed to not hold us back and seemed to mature about as fast as we needed it to, but boy, even then it was still stressful, and I feel like we got a little lucky. (Just to be clear, I also knew this going into it and the choice was mine, I may just have a deathwish)
We had a Kotlin app written with view bindings and the various other bits and pieces of Android app stack “no now this thing” detritus over the years. I hated it. I cut my teeth on 20 years of smalltalk, so it wasn’t even the “let’s hate on OO now” thing. It was just so much unfinished/inconstant things.
We have been porting to Jetpack Compose, and I really like it. It’s still got some growing pains. We don’t use ViewModels, hardly any Flow stuff, just mutable states and render trees and I’ve been pretty pleased. What makes me happiest is that it’s much more consistent. I don’t feel like I’m in a line at the DMV anymore; “oh you need that, go stand in that line and learn that stack, then come back”.
Like you, I’m extremely skeptical about the multiplatform siren. We tried it in Smalltalk land. The Java guys tried it and failed. I tried Flutter for a couple of apps, early testing iOS users were totally turned off (so fine for internal simple utility apps only). I would love it if someone really succeeded. We have 2 Swift UIKit apps I’ll have to convert to SwiftUI someday. So I will wish all that try well, but I’m not holding my breath at all.
Having a “write once run everywhere” pitch is about the same as politicians who run on “change”. It always sells; it never really delivers.
The first two paragraphs has been my experience on Android too. Android Framework is an incredibly disjointed mess that leaves you neck-deep in half-baked APIs.
Compose is better for sure. I’m still figuring it all out but it’s a marked improvement.
Take a look at skip.tools. It's pure SwiftUI on iOS and Jetpack Compose on Android, with the tool automatically handling the translation from Swift to Kotlin as part of the Xcode build process.
Flutter Linux targets GTK3 and is currently investigating a GTK4 migration. Flutter also supports Windows and macOS.
But it doesn't use GTK widgets, it just uses GTK to make a window.
That said GTK on Windows and macOS is very meh. You don't choose GTK for making a cross platform app.
Deluge and Transmission are good cross platform GTK apps.
Transmission only uses GTK on linux.
There is a Qt and CLI client, too.
And a web UI! (My preferred method as I run it on my home server)
Transmission uses Qt on Windows, either GTK or Qt on Linux, and something AppKit on macOS.
Transmission has Qt and Win32-native GUI clients as an alternative to its GTK client.
I don't think Transmission is a good example.
Evidentially it is possible to make GTK apps work at least somewhat nicely on Windows and Mac since there are a few out there. But it's clearly a ton of work. If you just make a standard GTK app it will be terrible. Most toolkits (e.g. Qt or even Flutter) work much nicer without having to fix them.
And it's a Google project, which means as soon as the low-hanging promo fruit is harvested it will immediately go EOL.
Like golang? Dart? Or Angular? They kill consumer products not programming languages or major frameworks..
These folks built their whole business on DartAngular only to be dropped when some manager decided that it’s time to push Flutter. https://medium.com/wriketechclub/wrike-is-sunsetting-its-ang...
Hardly anyone used the Dart Angular bindings so it was not surprising they got dropped. They were an early adopter and got bit.. this happens everywhere especially in frontend web development, and is certainly not specific to Google's frameworks.
Well, Angular is kind of dead now (or rather - will be). See https://twitter.com/sarah_edo/status/1770478763253379488
Wiz is awful and it's my read that a Wiz manager "won" a corporate battle and Angular (as it was) is dead.
Isn't Wiz internal only at Google? How can it replace Angular (honest question)?
That's definitely still a problem for libraries etc., but thanks to very recent developments (see the article) at least getting your app to users is super simple thanks to the new Swift Flatpak runtime: https://flathub.org/apps/org.freedesktop.Sdk.Extension.swift...
It says the runtime is under GPL3. Does the copyleft apply to all Flatpak apps written using Swift?
I thought that Apple actively avoided GPLv3
a. It's the author using something which is GPL b. GPL is allowed as long as complied. c. GPL mostly limits ability for use within iOS / AppStore.
It looks like the runtime is owned by the author of this article, who (from his bio) doesn't seem to be affiliated with Apple. Either way, I agree it seems like an odd choice.
No, it is the runtime, it's not a part of your app, it just runs it. You can basically think of it as a Docker container (but specifically for desktop apps). You don't have to make your app GPL, the same way as you can run a proprietary app on Linux even though the Linux kernel is GPL
It isn't that simple. If your application links against the runtime, be it dynamically or statically, then it is a derivative work and thus must be distributed under the GPL. This is why Java, also being under GPL, has an explicit exception for the runtime library despite even being a VM.
The Linux kernel allows you to run proprietary apps because the kernel code and the userland code exist in two separate "planes" connected by the syscall interface. The kernel even has an explicit exception for any code that may need to be shared between the kernel and the userland to make clear that this code is excluded from GPL.
As another similar case, the Free Pascal compiler is licensed under GPL including the runtime and almost all libraries/units that come with it but it also has an exception to allow linking without having the GPL extend to the programs the users write. AFAIK the GNU C library also has a similar GPL-with-linking-exception license.
FWIW I very much enjoyed using SwiftUI once I got the hang of it!
I'd been out of iOS dev for a good long while, and was still thinking in UIKit and Obj-C.
Overall I've found SwiftUI to be the most productive and enjoyable declarative framework and developer experience I've used!
To be fair my experience is limited to React and Flutter, but still, Apple have done a rather excellent job IMHO!
YMMV :-)
Rewriting an app from UIKit to SwiftUI not only eliminates storyboards but also reduces the code base. So once again: you have code plus storyboard XML vs. just code that is smaller! My jaw dropped when I first discovered this while rewriting something.
Unfortunately though SwiftUI hasn't completely matured yet. Especially if you are targeting iOS versions prior to 16, you will encounter many of SwiftUI's shortcomings. Some (many?) UI components are still UIKit under the hood, scroll view and its derivatives are still not as flexible as you sometimes want them to be etc. For some custom UI tricks that would be a piece of cake in UIKit are impossible in SwiftUI and you often resort to wrapping the old components in your custom ones.
Oh and don't get me started on resorting to the main thread (because of the underlying UIKit code) in the age of structured concurrency.
All in all, the concept of SwiftUI coupled with structured concurrency is beyond amazing but its maturing process is still underway.
There is Relm (https://relm4.org/). Which is in Rust is just GTK (through it's Rust bindings) with a nice reactivity layer on top.
I remember a few years ago, a few really cool cross-platform UI libraries were starting to emerge such as libui [0] that got me excited. I've kind of lost track of them since then (libui itself went dormant for a while before this fork) so I am not sure how mature/useful they are now, but the potential for writing native desktop UIs in basically any language seemed like an absolute dream. Perhaps it's feasible for very basic things?
[0] https://github.com/libui-ng/libui-ng
??
Do you know of any GTK4 app that runs well on non-Unix platforms?