Proposal to add Android App Widget

Hi all, I see that this topic came up many times before.

If I understand correctly, the main obstacle is the fact React Native doesn’t support this directly (and, due to it being Android-specific, I doubt it ever will).

I’d be very happy to implement this using a Native Module for Android and was wondering if the Joplin team would be supportive of such an implementation.

Specifically, what I have in mind for the initial implementation is:

  • A simple widget that displays ~5 most recent notes.

  • Clicking on a note opens it in the Joplin app.

The way I’d implement this:

  • Every time a note is open, the main app updates a list of most recently opened notes in JSON inside SharedPreferences. Access to SharedPreferences is achieved using a Native Module.

  • The widget itself just displays everything currently in SharedPreferences.

  • All notes are deep links that open the Joplin app.

My aim is to make the native Android code as trivial as possible, i.e. it would be just a “dumb” view for what’s in SharedPreferences. This greatly reduces the need to maintain two codebases.

I see that rabeehrz was already looking into implementing deep links so this makes the scope of implementing a widget even easier.

In the future, we can potentially add a few other options:

  • Being able to create a note. I’m not sure if that’s needed, since Joplin already supports app shortcuts on Android (long tap on the app icon brings up a menu).

  • Being able to mark to-do items as done. I’d love this feature, but I’d probably prefer to do this as a separate widget in the future. Most notably, the user would need to specify a notebook and the widget would have to display all to-dos inside of it, so most of the logic of this widget is not reusable.

What’s everyone’s thoughts on this?

6 Likes

I really like the idea, but I see a few problems along the way. If we can find solutions to those, I don’t see a reason why this couldn’t be done.

  • What happens on iOS?
  • How will it be packaged? (Is the react-native build process going to include this?)
  • Who will maintain this code?

Maybe splitting it into several components would make sense. The Joplin part for deep linking would be kept in the main repo.
The widget code and distribution in a separate repo. This could be your repo and you distribute the widget on the Play Store, F-Droid, …

Either way, widgets are great and most people love them. However, we should try to make sure that the experience is the same across the board. We try to keep the code base as common as possible, in which we have already failed with the “sharing to Joplin” functionality.

I am no the authority of what goes into the product, so let’s wait for Laurent’s input.

Having a widget would be great and indeed many people would be interested in it.

I’m not too concerned about iOS as this is native code so if it’s Android only for a start that’s fine. Whatever improvement we make, like deep-linking, etc. could be re-used for an iOS widget anyway, if someone can implement one.

The main issue I see is how to implement deep-linking, and secondly how to package the widget with the app. Currently creating the APK is entirely automated and it would need to stay that way.

1 Like

Nice idea @fstanis

For deep links you don’t even need any 3rd party dependencies – Linking is all you need.

I actually did a prototype but realized that deep links are useless by themselves. one way they become useful is with Android’s pinned shortucts. For instance you can have on a note screen button to create a homescreen shortcut for the note (or maybe even a tag or a folder).

There aren’t any good packages for this:

However this functionality is trivial to implement in native code.

3 Likes

Does iOS even have widgets? I thought it doesn't.

There's a native code already so no changes in the build process are required.

Thank you both for the feedback!

Edit: missed @roman_r_m's reply while writing this - glad to hear you've already had a prototype for deep links! Mind sharing the code (if it's in a repo)?

What happens on iOS?

As @laurent said, this wouldn't impact the iOS app directly, i.e. it's not adding a new note type or some sort of platform incompatibility, just a different view that's only applicable to one platform.

Also, my understanding is that iOS doesn't have the same type of widget per se. Today widget is, in some ways, similar, but React Native docs specifically say that these "may work unreliably because the memory usage tends to be too high". I suspect implementing this can be done, but it'd have to be completely separate from the Android widget anyway.

How will it be packaged? (Is the react-native build process going to include this?)
Currently creating the APK is entirely automated and it would need to stay that way.

I believe no additional work is needed for packaging. React Native apps already have to have some native code (Joplin has it here) that seems to be seamlessly included in the build process.

If it proves to impact the build process, I agree it's not worth adding.

Who will maintain this code?

I'm happy to maintain the Android native code that I add since it'd be almost trivial (just writing to a key-value storage and reading from it).

The widget code and distribution in a separate repo. This could be your repo and you distribute the widget on the Play Store, F-Droid, …

I don't think this is (easily) possible (specifically, having a separate app that only contains a widget). This would require a more sophisticated mechanism of getting Joplin data, not only making the whole thing more complicated (to the point where maintenance burden on both me and the Joplin app would be too high), but there would be both UX and security implications (i.e. users would have to setup and maintain a sync in two apps just to have a widget).

The main issue I see is how to implement deep-linking

Any specific concerns here? Seems React Native has good support for this, but I admit I never tried it, so unsure if there's some major issue I'm missing.

However, we should try to make sure that the experience is the same across the board. We try to keep the code base as common as possible, in which we have already failed with the “sharing to Joplin” functionality.

Fully understand this sentiment and overall I agree with it. My view is the following:

  • It's unlikely React Native will ever offer a way to do this without writing native Android code (based on the fact a feature request for it has been open for years).
  • It's a feature that's very commonly requested and Joplin users would benefit from.

Therefore, I'd argue that the demand for this feature is high enough to justify making an exception to "no platform-specific code". Once we have a simple widget in place, either it turns out nobody really needed this and we can remove it or this is something that's worth investing further into and adding more features (e.g. to-do lists). So I guess this proposal is more of a "here's how we can test the waters" rather than "here's a fully fleshed out feature". Hope that makes sense.

3 Likes

Yes, there are widgets. I'm an Android user though. I do own an iPad (got it for free), but I don't really use it. I don't like iOS or iPadOS.

Great.

Ok, I thought it would actually be less work, since I thought, you'd be reading from a certain (shared) memory location. If this makes it more complicated, then it makes no sense of course.

Yep, it does. It looks like Laurent is on board.That is, if his 2 concerns are addressed.

1 Like

There you go: GitHub - roman-r-m/joplin at mobile-deep-linking

And let me know if you have any questions. While I personally don't care much for widgets as a Joplin user, it looks like an interesting thing to work on.

1 Like

I assume we need to define a URL format for deep linking? Like joplin://note/<note_id>? If so, is there any standard format we can implement? I seem to remember there was one (someone mentioned it on this forum), but can’t find it now.

Right now, joplin://<item_id> is how resources and notes are linked internally, but we can use something different if it’s more standard.

Android only requires to specify the name (like joplin://) everything else is up to developers.
I think something like this might make sense:

  • note/<id> to refer to a note
  • folder/<id> for folders
  • tag/<id> for tags
1 Like

Joplin knows what type of resource (note, notebook, tag) the id is anyway, so we don’t really need to specify the type in the URI. We can, but it’s not necessary. Unless we want different behavior between:

joplin://NOTEHASH
joplin://note/NOTEHASH

But I’m not sure what different actions we could choose. On the other side we can always do something like this in the future:

joplin://HASH[/action]

The standard I was looking for is called “x-callback-url” - http://x-callback-url.com/examples/

Bear for example supports it: https://bear.app/faq/X-callback-url%20Scheme%20documentation/

So I guess we could have something similar. At first, just a URL to open a note, and another one to return a list of the latest notes:

  • Open a note:

    joplin://x-callback-url/open-note?id=7E4B681B

  • List notes:

    joplin://x-callback-url/list-notes?order=updated_time&limit=5

In fact, I think that should be just a translation layer above the API, that way there’s no need to re-implement all the end-points.

Right, although I want to point out that APIs usually do not use parameters as in GET requests. APIs use well-defined endpoints, except maybe for search queries.

So open note, would rather look like this:

joplin://x-callback-url/open/7E4B681B

But the list call is the way you mentioned it:

joplin://x-callback-url/list?order=updated_time&limit=5

Isn’t x-callback-url mostly an iOS thing?
Though ultimately the format doesn’t matter all that much and x-callback-urls seems flexible enough for Joplin.

Yes somehow the doc mentions iOS only, although I don't see why it couldn't be used in other contexts including desktop apps. Or maybe I'm missing something and this scheme is useful only for iOS.

Though ultimately the format doesn’t matter all that much

Ideally we should follow existing standards as it means the app is easier to use, and we don't need to re-invent the wheel with a new standard. But if the only one is the x-callback-url and it's perhaps only used for iOS then indeed we don't have to follow it.

Personally I'd prefer something that maps directly to the API, so it would be something like what @tessus mentioned above - joplin://notes/ID

This is the closest to specification for Android that I was able to find: https://developer.android.com/guide/topics/manifest/data-element

Not much there, says it must be a URI and/or a mime-type. It’s generic enough that your x-callback-url matches it.

@fstanis were you still thinking about implementing this?

Are you guys still thinking about this? It would be awesome to have this widget as it would make editing notes so much faster and simpler on Android. It would be really useful as especially on the move, I usually don't have much time to add some thoughts to a note.

A first draft of the widget was implemented in this pull request but it wasn't finished: Android: adds "recent notes" widget by fstanis · Pull Request #3458 · laurent22/joplin · GitHub

2 Likes