Flutter-ing Around Rclone

Follow me on my still ongoing journey of possibly actually maybe perhaps finishing a project: Creating a mobile app that wraps rclone for automatic backups!

Some Background

I’ve been messing around on and off with Flutter for a few years, first just because of an elective in university, then attempting to make some of my own projects (emphasis here is on “attempting”). In short, Flutter is a framework based on the Dart programming language for creating cross-platform graphical applications. The concept is cool, the reality is a bit of a mess in my eyes, but it’s currently the only approach to making a mobile application that is both technically feasible for me and that I have some marginal experience with, so it will have to do. 🙃

I use an Android phone (at least until mobile linux saves me (soon please)) and I don’t use any proprietary cloud crap for backups, so I’ve had to find alternatives for backing up files and application data. For small amounts of data, something like Syncthing has been perfect for me, however for bigger files like various media or the multi-gigabyte automatic backups that Signal creates this is not ideal. I would prefer such large stuff to not be synced constantly in the background, but rather in longer, regular time intervals like each night or weekend.

There are some apps on F-Droid that do this, I have tried them all (unless new ones emerged already) and they have not satisfied me for various reasons (I am reminding myself of xkcd 927 (Standards)). One thing I learned from looking around though is that rclone exists and that it supports a ton of different providers as targets with various operations like moving, copying and syncing data. I already use the rclone-based application RSAF to access my SMB shares at home, but while other rclone-based apps (Round Sync, RCX) did not work well for me, why not create my own?

The Good

I’m off to a good start already! I somehow managed to figure out how to cross-compile rclone as a library with dart’s hooks/code_assets packages and created some very basic bindings for it (you can have a look in my repo librclone_dart). If you are experienced with dart, this is probably awful, but it works and I’m proud of it and that’s good enough for me.

I also got started on the application itself, the repo is simplerclone, I have a bunch of local changes that aren’t pushed yet though so I don’t even know what state the repo is in right now. I have implemented some UI for creating remotes based on all the providers and I’ve verified that actually copying/syncing stuff works, though there is no UI for that yet. So this part also works but I am not proud of it, more details are lower down. 🫠

The Bad

This is mostly flutter itself. Flutter also has a bit of a dependency explosion culture with all its security and complexity downsides. Dart is also a very powerful language that allows you to do a lot of really weird stuff that is too complex for me to understand and too complex for me to use in good faith.

As my other blog posts may indicate, I use Alpine Linux ❤️, which does not use the common GNU C library (“glibc”) but rather musl libc (website is very slow at the time of writing, not sure what’s up there). Unfortunately, upstream flutter on musl has various problems (eg. tries to link against glibc-specific stuff when creating a linux build, which fails) and Alpine’s packaged (and patched for compatibility) version of flutter is quite far behind upstream due to even more problems in newer flutter versions.

I am very unhappy to use software with such poor compatibility, but as mentioned at the start, it is the only option I currently have for creating an Android application (and having to use Android Studio to write a native Kotlin app sounds like an even worse deal). So as bizzare as it is, I am not able to take advantage of the cross-platform part of this cross-platform framework.

The Ugly

That’s just mostly my application code… 🙃

There are about a million approaches to state management in flutter and they (almost) all come with their own library full of things I probably don’t need and definitely don’t understand. Since I am not okay with bloat, blind copying and needless dependencies, I am not happy just using one of these million state management libraries.

I initially picked provider for state management as it’s officially recommended by flutter docs but found it a bit messy and cumbersome. I then switched to flutter_it (get_it, watch_it etc.) as a simpler and more modular solution but I still don’t get it (hah) and all the AI crap in their docs is really vibing me off (in addition to needless dependencies).

I suppose I’m still in the middle of finding a solution but I think a decent one might be vendoring klizma because it’s so small and simple that even I understand it and it comes with zero dependencies. Let’s see whether it works out for me, right now I’m in the middle of re-writing a bunch of stuff with it.

On the topic of re-writing a bunch of stuff, at first I didn’t really get the point of all the layers of models like MVVM (Model-view-viewmodel). But as I have struggled with choosing between data structures that make the most sense for the application and data structures expected by the librclone API, I have come to understand some of the benefits of separately defining both the domain data structures and API data structures and handling them in different classes. The current state of things is a bit of a mess, so that’s the biggest aspect of the re-writing that I’m doing now.

Lastly, there is testing - I’m frankly just skipping that for now, this is my own personal fun project and dealing with that doesn’t sound like fun right now, so I’m investing that time and energy into more simple and robust code.

What’s Next

To make it short: A full re-write with what I’ve learned about state management from my first struggle attempt, while throwing out flutter_it.

Join me next time when I tell you how it went (or more realistically, how it’s going)!