Proposal: use Flutter for KDE development whenever possible
Problem
Development on KDE primarily relies on C++ and QML, which have positives but also negatives such as:
- Tempermental documentation generator
- Complexity of developing multi-platform
- Not approachable to new developers
- Poor tooling
- Frustrating package/dependency management, setting up a development environment, achieving working doc comment popups / IntelliSense / autocomplete suggestions in IDE (little-to-no support for modern, user-friendly IDEs), etc.
Solution
I propose that we should consider using Flutter whenever possible.
Flutter is a cross-platform, open-source framework built on top of the Dart programming language and from a single codebase they support:
- Desktop (linux, windows, mac)
- Mobile (android, ios)
- Web
- Support for embedded systems and IoT (internet of things) devices is forthcoming.
Simply being able to "write once, deploy anywhere" is an excellent benefit on its own, though they come with other positives as well, for example:
Dart
-
Familiarity -- Dart uses C-style syntax:
(it also supports named parameters, a personal favorite!)
import 'dart:math' show Random;
void main() async {
print('Compute π using the Monte Carlo method.');
await for (final estimate in computePi().take(100)) {
print('π ≅ $estimate');
}
}
/// Generates a stream of increasingly accurate estimates of π.
Stream<double> computePi({int batch = 100000}) async* {
var total = 0; // Inferred to be of type int
var count = 0;
while (true) {
final points = generateRandom().take(batch);
final inside = points.where((p) => p.isInsideUnitCircle);
total += batch;
count += inside.length;
final ratio = count / total;
// Area of a circle is A = π⋅r², therefore π = A/r².
// So, when given random points with x ∈ <0,1>,
// y ∈ <0,1>, the ratio of those inside a unit circle
// should approach π / 4. Therefore, the value of π
// should be:
yield ratio * 4;
}
}
Iterable<Point> generateRandom([int? seed]) sync* {
final random = Random(seed);
while (true) {
yield Point(random.nextDouble(), random.nextDouble());
}
}
class Point {
final double x;
final double y;
const Point(this.x, this.y);
bool get isInsideUnitCircle => x * x + y * y <= 1;
}
- Dart is strongly typed, and supports sound null safety.
- Dart has a rich set of core libraries.
Flutter
- Familiary -- Flutter syntax and concepts have many similarities with QML:
class SampleItemListView extends StatelessWidget {
const SampleItemListView({
Key? key,
this.items = const [SampleItem(1), SampleItem(2), SampleItem(3)],
}) : super(key: key);
static const routeName = '/';
final List<SampleItem> items;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Sample Items'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
Navigator.restorablePushNamed(context, SettingsView.routeName);
},
),
],
),
body: ListView.builder(
restorationId: 'sampleItemListView',
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
final item = items[index];
return ListTile(
title: Text('SampleItem ${item.id}'),
leading: const CircleAvatar(
foregroundImage: AssetImage('assets/images/flutter_logo.png'),
),
onTap: () {
Navigator.restorablePushNamed(
context,
SampleItemDetailsView.routeName,
);
});
},
),
);
}
}
- Stateful hot reload -- while running a debug build, your changes to the code appear on screen in seconds, without losing the state of the app.
- Customizable, adaptable, composable widgets.
- In order to maintain a smooth UI, Flutter is designed to always reach a smooth 60 fps (120 fps for devices capable of 120Hz).
Also..
-
Flutter applications compile down to fast, native platform code:
- Linux & Windows: C++
- Android: Java and C++
- MacOS & iOS: Objective-C/Objective-C++
- Web: Javascript
-
Robust testing for unit, widget, and ingtegration tests
-
Flutter and Dart have excellent documentation. In addition, because the documentation is generated directly from the source code you can always use
Go To Definition
on a method, class, widget, etc to see the implementation & documentation right at the source. -
YouTube has tons of Flutter & Dart related resources from both the community and the official Flutter channel. Especially excellent is the "Widget of the Week" playlist, which is an amazing resource to get a primer on Flutter or to refresh yourself on a specific widget.
-
A large and diverse collection of third-party packages. Adding a package from the official repository is as simple as adding it to the list of dependencies like so:
dependencies: dbus: ^0.6.3
- Packages can also be specified as relative or absolute file path, git url w/optional reference/tag, and even a custom package repository could be implemented if truly desired.
-
Support for C interop with dart:ffi allows calling native C APIs (and C++ wrapped for C compatability).
-
Communicate with platform-specific native code via MethodChannel as part of the app or a plugin, allowing one to for example call functionality from C++ on desktop if needed.
-
See also: Flutter FAQ
Bonus: Dartpad
Dartpad is an open-source tool that allows one to run Dart & Flutter in a browser, excellent for trying out new things, quickly debugging some small item in seclusion, and sharing runnable snippets.
You can even embed dartpads in html.
Summary
- dartdoc converts doc comments automatically into excellent, searchable documentation that supports linking and styling, with an easy to use syntax: markdown. See the Dart documentation for an example, which is itself generated with dartdoc.
- Multi-platform by default from a single codebase.
- Friendly to newcomers & experienced devs with a sensible syntax + great syntactic sugar, fully open and commented source, many resources for learning and reference in different formats, and (IMHO) hands-down the best tooling of any language I have seen.
I don't claim that Dart or Flutter are perfect, but I do think they are very good and would make for a better development experience than using C++ / QML for some projects. For example, we should consider when creating an application: why make a music player, game, educational app, Matrix client, etc.. that are frustrating to work on, difficult to onboard new contributors, and port between platforms if they don't need to be C++ and QML?
Example
I have put together an example of what this might be like, using something relatively simple and self-contained for demonstration purposes: an emoji picker.
Creating this was a fast and pleasant development experience, and now there is an emoji picker that has better than feature-parity with the current KDE implementation that could be dropped in as a replacement.
This example emoji picker is fast, functional and beautiful, while being a pleasure to develop for. A couple of further thoughts on it:
- Right now this uses internal themes. We would need to develop a package for Flutter apps to use that would allow it to take on the native theme KDE is using. Would require a bit of work, but sounds quite doable.
- Reusable. As an example, why should a project like NeoChat write a brand-new emoji picker, when:
- Custom widgets can be imported in other projects, so other Flutter projects that wanted a built-in emoji picker could simply do something like
import emoji_picker
. - For non-Flutter projects this app would require minimal changes to accept run-time arguments that configure the app's window decorations, size, position, etc. This would allow the app to seamlessly integrate into any other application. Following NeoChat as an example, it could just direct this app to open with no decorations, in a place and size that would emulate a "popup emoji picker" that felt like a part of the application.
- Custom widgets can be imported in other projects, so other Flutter projects that wanted a built-in emoji picker could simply do something like
Links to check out this emoji app:
I have had excellent experiences developing with both Dart and Flutter, and I can really see using them as a way to:
- Improve the general development experience.
- Simplify & improve documentation efforts.
- Reduce complexity by having one code-base seamlessly support multi-platform by default.
- Make for a better supported and more pleasant entrypoint for potential new contributors.
I would love to hear what others think. :)