Trustroots / trustroots

Travellers' community for sharing, hosting and getting people together.
https://www.trustroots.org
GNU Affero General Public License v3.0
398 stars 137 forks source link

Push notifications #394

Closed simison closed 7 years ago

simison commented 8 years ago
simison commented 7 years ago

@nicksellen commented:

Pushwoosh does not support Remote API [1] in the free tier [2].

[1] http://docs.pushwoosh.com/docs/createmessage [2] https://www.pushwoosh.com/pricing/

simison commented 7 years ago

Asked Boxcar.io about non-profit/opensource pricing. Edit: nope.

nicksellen commented 7 years ago

batch supports unlimited push notifications using the transactional API.

... but I spent a bit of time reading into push notifications as I did not know much about them really (there is the Web Push API now too). I then read the slack chat from before - my past self re-explained it to my current self that had forgotten it all :)

Basically, why not just use FCM? The requirement here is to do push notifications, which FCM is for, works across iOS/Android, and the new Web Push API, and is free with no limits.

All the other fancy startup services are there because they promise to offer something over and above it - perhaps easier APIs, more platforms (kindle fire anyone?), better error handling ... but they are just using FCM under the hood anyway, and don't seem dramatically easier to implement.

simison commented 7 years ago

@nicksellen nice, thanks for studying this! I was looking into Boxcar.io/Onesignal.com docs and it indeed doesn't seem so simple as they advertise.

I think I'll try to set up a demo with FCM. Any help building this feature would be greatly appreciated! ;-) It'm a bit low on spare time there days.

nicksellen commented 7 years ago

A quick overview of how it works:

Push notifications could be very energy consuming, so they came up with a solution to be able to manage them using one service per platform (as opposed to one service per app). For iOS it's APNs, for Google it's GCM/FCM. iOS and Android phones just know where to connect to get their notifications.

The new Web Push API has been built with a similar principle, except it's each browser that has a special push service URL built into it. Currently Chrome, Firefox, Opera support them on desktop and mobile, but nothing else.

FCM though has expanded into a cross platform mobile suite and can push to Android, iOS, and Web. It slightly abstracts the subscription model. The mobile app or website gets a registration token which you post to your backend. This then lets you push to that device by sending messages to FCM. For nodejs google provide an SDK that you can just drop into the server-side app.

To get access to the phone push mechanism it needs to be a native app (hybrid is fine too), and web would work anywhere the features are supported (web workers, and push).

I guess mobile notifications are the main goal, but probably a lot of people don't use trustroots on a mobile browser that supports Push API, so it means waiting for mobile app to be ready.

simison commented 7 years ago

it means waiting for mobile app to be ready.

I made a really quick test and got the website running in React Native wrapper within 5-10mins. Seems like a way to go and then the separate app dudes are working on would be called "Trustroots Messenger" for now.

nicksellen commented 7 years ago

... having said that, building Web Push API notifications would get all the pieces in place ready for the mobile app:

Web frontend:

Backend:

All the backend stuff would be needed for the mobile app too...

simison commented 7 years ago

"react native module for firebase cloud messaging and local notification"

https://github.com/evollu/react-native-fcm/

nicksellen commented 7 years ago

the website running in React Native wrapper

I'm confused, the website is an angular app, how does that run in a React Native wrapper? Did you mean a webview wrapper thing? (like cordova, etc).

simison commented 7 years ago

Yeah, just a webview.

It's this simple:

import React, { Component } from 'react';
import {
  AppRegistry,
  WebView
} from 'react-native';

const siteURL = 'https://www.trustroots.org/';

const webViewInjectedJs = `
// Any JS one might want to inject
`;

export default class Trustroots extends Component {
  render() {
    return (
      <WebView
        source={{uri: siteURL}}
        style={{marginTop: 20}}
        injectedJavaScript={webViewInjectedJs}
      />
    );
  }
}

AppRegistry.registerComponent('Trustroots', () => Trustroots);
nicksellen commented 7 years ago

https://github.com/evollu/react-native-fcm/

I saw that. Made me wonder how making websites got so complicated... (onesignal react native is no better).

nicksellen commented 7 years ago

Yeah, just a webview

Why React Native then? Seems overkill to just use it for creating a single webview... maybe cordova or just an actual native android java app with a single webview?

nicksellen commented 7 years ago

These seem to explain how to create simple apps with just a webview:

https://developer.chrome.com/multidevice/webview/gettingstarted https://gist.github.com/rduplain/2638913

simison commented 7 years ago

I have quite some experience running Cordova in production (and in scale) and gotta say it was terrible. Everything broke on every cordova/OSX/ios/plugin update and it was sooo slow. Weird issues with different iOS versions. Haven't touched it in 2-3 years now, so things might've improved since.

Why React Native then? I think the biggest reason would be to be able to extend to an actual app with react native.

an actual native android java app with a single webview

This is a fair point. This is more relevant for iOS though as for Android there's already that react native messenger.

Depends also on how easy it is to implement those notifications in any of these (reactnative/cordova/native java&swift).

Suppose it's fairly easy to replace the app with new architecture anyway once it's in store already...

nicksellen commented 7 years ago

Maybe it's easy enough to create a nice simple webview iOS app too, e.g.:

http://codewithchris.com/make-an-app-from-website/#webviewapp https://github.com/coffellas-cto/GDWebViewController

At some point something needs to stick the FCM iOS SDK into the iOS app and the Android SDK one into the Android app...

How do you build a cross platform React Native app with FCM SDKs for the relevant platforms?

nicksellen commented 7 years ago

If I were building it now (which I'm not), I would just build android (I don't have a mac), and do it in native java app (I know/like java, and I like as few layers as possible). But those factors will vary if someone else is doing it.

nicksellen commented 7 years ago

Back to the registrations/subscriptions though, the registration token is for a single device, then it seems you create a device group to represent a user, and send messages to that - and doing that on the serverside app seems most sensible (as it has access to all the registrations).

A bit I'm not quite sure about right now is unsubscription flow - I think the device can unsubscribe itself directly from FCM/APNs (uninstall, or in phone settings?) and in that case the client app might not have had a chance to tell the app server about it (? ... or that could always fail too). It might be fine to just check for failed registration tokens in response the app server gets from FCM and remove them, but maybe they can be temporary errors too? (So it would need to track failures over time before removing a registration from the user data).

Edit: seems so - it has a NotRegistered error

simison commented 7 years ago

So it sounds like it would make sense to build web/browser notifications first with FC and publish that fist. Then extend it to get mobile push notifications work as a next step?

nicksellen commented 7 years ago

Sounds like a good plan to me, the frontend web stuff might not be super heavily used though... can definitely start speccing out the backend parts though.

nicksellen commented 7 years ago

Answering my own bullets from earlier:

POST /user/registrations - save registration in user data, then call FCM to add to user device group

(minimal version needs nothing more...)

... probably not essential to start with. simple push notifications on/off setting? - would delete all registrations?

... or maybe that is ugly UX and a list is essential?

This seems the trickiest bit to me, but maybe it piggybacks on some of the other related work done recently? What should be notified, when, and with what content/action?

Just handle NotRegistered errors when app server calls FCM to send message, and remove registrations

simison commented 7 years ago

simple push notifications on/off setting? - would delete all registrations?

Yeah, 99% cases people have one mobile phone so in the case when there are multiple registrations, a simple on/off to remove all of them is okay.

I usually see toggles per type:

but since we push notify only about important stuff like new messages, we can stick to "if mobile app is installed, it'll receive push notifications. To not get them, remove the app." or something like that. It's more important to get these online rather than figure details like that. :-)

simison commented 7 years ago

This seems the trickiest bit to me, but maybe it piggybacks on some of the other related work done recently? What should be notified, when, and with what content/action?

Just unread messages for now — but surely we'll expand it later to other stuff. As long as code for this is generic, expanding/refactoring shouldn't be too painful.

It's already easy to plug into this process: https://github.com/Trustroots/trustroots/blob/master/modules/messages/server/jobs/message-unread.server.job.js#L147-L152

simison commented 7 years ago

@nicksellen :cake: thanks for digging in! I think I'll start tackling this tonight once I'm done with today's errands.

nicksellen commented 7 years ago

if mobile app is installed, it'll receive push notifications

even better 👍

I'm quite interested in the web js stuff, these web workers are pretty funky...

simison commented 7 years ago

Feel free to start playing around on a branch and I can continue from it later tonight. ;-)

On 8 Apr 2017, at 15.39, Nick Sellen notifications@github.com wrote:

if mobile app is installed, it'll receive push notifications

even better 👍

I'm quite interested in the web js stuff, these web workers are pretty funky...

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or mute the thread.

nicksellen commented 7 years ago

I played around in a seperate repo to get a full basic client and server example running. Readme explains all. I have ugly bower error in trustroots project (see slack).

nicksellen commented 7 years ago

They have a feature for grouping a users multiple devices into a group (it gets a notification key), but after trying it I don't think it's useful:

  1. you have to manage creating the notification key (will error if it's already created = hassle)
  2. have to map notification key name to notification key id
  3. more things to save against the user
  4. you can send messages to multiple registration keys directly anyway...

... basically having to sync your view of the notification key with googles for no real benefit.

nicksellen commented 7 years ago

Ok, I implemented a bunch of stuff (branch on my laptop for now):

Frontend:

Backend:

pushsettings

It's not quite ready to show yet, quite scrappy still, todo:

But it works! For now I made foreground notifications (i.e. webpage is open) use the normal message service thing. Not far off from being ready to push though.

nicksellen commented 7 years ago

Working in https://github.com/Trustroots/trustroots/pull/491 now

bitfasching commented 7 years ago

Created pull request adding Exponent push notifications needed for the expo mobile app: https://github.com/Trustroots/trustroots-expo-mobile

simison commented 7 years ago

I fixed a bunch of issues around mobile push notifications and deployed new versions of the site and the app: http://android.trustroots.org