thunder-app / thunder

Thunder - An open-source cross-platform Lemmy client for iOS and Android built with Flutter
https://thunderapp.dev
GNU Affero General Public License v3.0
732 stars 62 forks source link

Implement core architecture to handle push notifications (APNs, UnifiedPush) #1237

Closed hjiangsu closed 1 month ago

hjiangsu commented 2 months ago

Pull Request Description

Note: This replaces the previous draft PR created in #1095. I've updated the description to better match the updates.

This is a draft PR which adds the ability to handle push notifications via Apple's push notification service (APNs) and UnifiedPush.

To do this, we have to rely on two separate packages:

Additionally, implementing push notifications requires a separate server in order to perform notification polling and sending out push notifications for devices. This is still a WIP.

There is still a lot of work required for this to function properly. I'll add a to-do list here:

While I'm developing the server code, I'll keep it closed-source. I'll most likely make it open-source once I'm done with all the local testing (to ensure that no keys are accidentally committed to the repository)

Issue Being Fixed

Issue Number: #219

Screenshots / Recordings

N/A. Will update when I have more logic completed.

Checklist

micahmo commented 1 month ago

Quick question! There were a couple tasks that I did not do as part of my first implementation of local notifications (such as the ability to check for every logged-in account, and the ability to display mentions and messages).

I believe most of these things can be implemented separately from the push notifications feature, but I just wanted to check and see whether you are working on any of these things and/or whether they should wait until this feature is done.

hjiangsu commented 1 month ago

but I just wanted to check and see whether you are working on any of these things and/or whether they should wait until this feature is done.

Sorry for getting back to you so late on this! The changes in this PR moves a lot of logic around, and adjusts a lot of existing logic to be able to handle push notification functionality. I think it might be better to hold off on those changes until this is completed (or at least merged in partially)

For instance, a lot of changes were made to the main file to push the notification stream down and I believe I moved some of the functions related to background notifications to a different file to clean up the main file.

hjiangsu commented 1 month ago

So a bit of an update here - I think this is mostly done at this point (at least for the first iteration of changes). This is a general summary of what has changed:

@micahmo, I've also added you to a new repo which contains the code for the notification server. It's closed off for now since I'd like to get it more fleshed out but you can take a look at that as well if you'd like!

As for all of this, I'd like to first get the code merged in if everything looks good. I'm thinking it would be good to merge the code in first to reduce merge conflicts as this is quite a large change, and just disabling the unified push/apns feature outright for now while I continue to refine the notification server logic. Thoughts on this approach?

hjiangsu commented 1 month ago

Feel free to do a code review on this! I've tried to separate the logic as best as possible so that it's hopefully easier to review 😅

hjiangsu commented 1 month ago

Do we still have logic to handle the app starting due to tapping on a notification?

Yup, I believe this located here. Its only enabled for local and unified push since iOS handles the tap: https://github.com/thunder-app/thunder/blob/34893f16e3e329b6375247044252b48d6790f8de/lib/notification/notifications.dart#L44-L66

It looks like you added multi-account support. On Android (where you can group notifications), are they grouped by account?

It should be grouped by account! Previously, I think it was one single group for replies, but I tried to separate that into accounts. I think you can probably test it better than I can (I tried it on the emulator and it seemed correct).

Will Thunder correctly switch accounts and show the inbox for the right user for the tapped notifications?

Hmm, I have not tried this yet - we would have to do a test to see if this works properly.

I pulled the code to test, but the "Enable Inbox Notifications" setting is disabled, so I'm not sure how to test.

Ahh, I set it so that you need to have at least one logged in account to enable the setting. Can you try that and let me know?

BTW, just a note that I initially got this error when trying to build.

Hmm, I encountered this initially as well when I was initially setting it up. I'm also not sure what the best solution here is. I think the unified push package has a dependency on a specific toolchain version in their build.gradle. I'm not too familiar with this so I'm not sure the best way to go about it.

https://github.com/UnifiedPush/flutter-connector/blob/ca5ed6d078735235c261b8f7ba430a1a36d46203/unifiedpush_android/android/build.gradle#L34-L36

micahmo commented 1 month ago

Thanks for all the responses, everything sounds good!

Yes I think we will have to test the multi-account launching. Either we can use the temp account feature, or we can just completely switch the active account to whatever was prompted from the notification.

I set it so that you need to have at least one logged in account to enable the setting.

Oops! I was testing with a different flavor to not mess anything up and forgot to log in. Now it works and I am able to test a bit.

https://github.com/thunder-app/thunder/assets/7417301/c0b98806-3021-4de9-aaf3-1a974a0bd223

That's all I got for now, but I'll play around!

micahmo commented 1 month ago

I did confirm that tapping a notification for an account that is not active does not show you the right inbox.

In addition, if I'm logged in with multiple accounts and get a notification from one, it seems there's always one for the other that's empty.

https://github.com/thunder-app/thunder/assets/7417301/cfb0afdd-4da3-4253-8785-7ea53c652bfc

EDIT: And it looks like the notifications generated via background fetch are empty.

image
hjiangsu commented 1 month ago

@micahmo I've updated the code to reflect some of the issues mentioned: 6f8f622

hjiangsu commented 1 month ago

In addition, if I'm logged in with multiple accounts and get a notification from one, it seems there's always one for the other that's empty.

Weird, I thought I tested that scenario previously and it seemed to work properly. Let me take a closer look

hjiangsu commented 1 month ago

Just pushed another commit which should fix the issue with empty notification groups. Let me know if that works!

hjiangsu commented 1 month ago

I did confirm that tapping a notification for an account that is not active does not show you the right inbox.

For this, it seems like it might take a bit more work to get it running properly. Do you think it might be better for this to be added in a separate PR? If you'd like, you can have a go at it since you might be more familiar with the general flow!

micahmo commented 1 month ago

Thanks for all the quick updates! And yes I can definitely tackle the user issue. 😊

hjiangsu commented 1 month ago

Sounds good! Let me know if all the issues you mentioned earlier are fixed. If they are, then I'll go ahead and merge this in to get it out of the way 😅

micahmo commented 1 month ago

I probably won't be able to test for a little while, so if you want to go ahead and merge now, feel free!

codenyte commented 1 month ago

This looks very exciting! Is there currently a way to test this?

micahmo commented 1 month ago

@codenyte We are still working out the kinks, so it will probably be a little while until this comes to nightly. The only other option would be to build from source. There are some instructions in the README, although I'm not sure if they're completely up to date.

codenyte commented 1 month ago

I tried both building directly using Flutter and with the Docker container. Neither option worked for me, but this might also have to do with my weird setup or my incredible stupidity.

micahmo commented 1 month ago

Not at all, to be fair, the setup instructions are not documented to be completely foolproof, and there are a some assumptions that they make. If you want help building, feel free to reach out in the Matrix chat and send your errors logs.

hjiangsu commented 1 month ago

This looks very exciting! Is there currently a way to test this?

Thanks! As @micahmo mentioned, this is probably a little ways away still from being fully functional since there's still a lot of other stuff under-the-hood which would make this functional.

For UnifiedPush/Apple Push Notification service (APNs), you need a separate server that polls for new notifications. That server is still being worked on, and I'm trying to make it as simple to self-host as possible (through the use of docker). That would be the ideal scenario, rather than to have you trust me (or anyone else for that matter) with your JWT tokens.

codenyte commented 1 month ago

For UnifiedPush/Apple Push Notification service (APNs), you need a separate server that polls for new notifications

Right, I forgot that Lemmy doesn't support UP yet (I really hope this gets implemented)