Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

User Notifications API #114

Closed
jace opened this issue Apr 15, 2014 · 16 comments
Closed

User Notifications API #114

jace opened this issue Apr 15, 2014 · 16 comments

Comments

@jace
Copy link
Member

jace commented Apr 15, 2014

Lastuser needs to provide a centralised mechanism for controlling notifications sent to users by client apps. The primary purpose of this mechanism is to provide a meaningful "unsubscribe".

Notifications should be modelled on the Growl API, giving us:

  1. Transport: how the notification is delivered (currently in-app, SMS or Email, in future IM, other), with sub-options (HTML or plain text email).
  2. Notification class: A class of notifications from each client type. Funnel may have "Comment alert", for example. Notification classes specify defaults for users who haven't made a choice yet. A class may be defined as mandatory, meaning a user cannot unsubscribe from it (for example, password reset emails). Notification classes should however specify if they are transactional or mass-mails.
  3. UserNotificationPreference: What the user prefers for each class of notification: disabled, preferred transport, preferred sub-option, preferred batching (immediate, digest, silence period (particularly for SMS)).

For email:

  1. Lastuser wraps all email notifications with its own markup, which includes branding, app identification and one-click unsubscribe, or
  2. Lastuser allows the client app to specify its own markup, but ensures required links are present.

To be considered: Should Lastuser preserve a copy of every notification delivered, or even just a transaction id? This is required for proper bounce detection, etc.

Also related: should the existing notice mechanisms (email verification, password reset) be moved on top of the notification API?

@jace
Copy link
Member Author

jace commented Apr 15, 2014

In the case of a user-specified alert, such as jobs matching certain keywords on Hasjob, the unsubscribe link should unsubscribe from that particular alert, not the general notification class. This is a problem because Lastuser doesn't know anything about app preferences.

Notification classes could now contain user ids, linking them to a particular user, so that a class can be added for each alert the user signed up for. However, while this works for something like Hasjob alerts, which are a small set per user, it won't work for Funnel comment notifications, where the user could have participated in hundreds of threads and should be able to manage their preferences for each.

Approach 1: Insist on user-linked notification classes and figure out the UI to make them manageable

Approach 2: Allow apps to override the unsubscribe link with their own version of it. However, given how tricky one-click unsubscribe is, this may not be viable.

@jace
Copy link
Member Author

jace commented Apr 18, 2014

To be considered: allow users to respond to a notification.

@jace
Copy link
Member Author

jace commented Apr 22, 2014

Required: it should be possible to (a) delay a notification and (b) withdraw it.

For example, if a proposal is confirmed in Funnel, it may have been accidental, so the "Confirm" button should (a) post a delayed notification (5 min to 1 hour, subject to another discussion) and (b) if the user reverses the action, the notification should be cancelled. Reversal isn't well defined here. Docflow's transition doesn't keep an undo history, so in effect, an undo is a transition in the reverse direction, but is still an independent transition.

@jace
Copy link
Member Author

jace commented Apr 22, 2014

The notification problem described above sounds like it is a problem elsewhere. Funnel shouldn't post a notification until a reasonable timeout has occurred.

@jace
Copy link
Member Author

jace commented Jun 25, 2014

Perhaps delayed notifications do have a place in Lastuser, but cancelling a notification should remain an app problem. To be resolved:

What is the "context" for a notification? A destination URL? A (presumably global) object id? How does Lastuser batch notifications when it needs to deliver multiple notifications for the same object? Eg: Facebook's "Your Friend and 19 others commented on your post". Where are "Your Friend" (a user), "19 others" (a count) and "commented" (an action) picked up from? Is the client app responsible for tracking these details, or can Lastuser track subject/verb/object and automatically batch?

@jace
Copy link
Member Author

jace commented Jun 25, 2014

Let's take Funnel comment notifications as an example with four users. Funnel has a "Comment on proposal you are subscribed to" notification class:

  1. User A posted a proposal on Funnel.
    • A gets subscribed to this notification class with the proposal as object (object is currently not a part of the notification class definition)
  2. User B posted a comment on this proposal.
    • B gets subscribed to the same notification class.
    • B's action triggers a notification against this class with subject B's userid, verb "comment" and object proposal's buid (which it doesn't have at the moment, but will acquire under Nodular).
    • Lastuser scans for recipients registered for this notification class and object, finds A and B.
    • Lastuser excludes B from recipients as B's userid matches the subject value.
    • Lastuser sends a notification to A ("B left a comment on your proposal"?. "B left a comment on a proposal you are subscribed to"? How is the context introduced?)
  3. User C replied to user B.
    • C gets subscribed to this notification class/object.
    • B is supposed to be notified that they got a reply.
    • A is supposed to be notified that they got a new comment on their proposal as a reply to B.
  4. User D posted another comment on this proposal.
    • Same process as with B's first comment, but A, B, C and D are all subscribed now.
    • Debatable: C should not be notified as they are not part of the thread. Or, C should be notified anyway as D may have accidentally replied to D in a top-level comment (as happens currently with Funnel).
  5. User A replied to user B.
    • A, B, C and D all get notified, A gets filtered out, as above.
    • C and D should arguably be excluded from notifications, as above.

@jace
Copy link
Member Author

jace commented Jun 25, 2014

Another scenario:

  1. User A posts a proposal and subscribers to the "New proposal" class in the ProposalSpace context get notified.
  2. User B, a reviewer, marks the proposal as Accepted
    • User A is subscribed to the "Proposal status change" class with the proposal as context and so gets notified. The class has a default frequency of "delayed", so the notification is queued but not sent.
  3. User B changes the status to Rejected.
    • User A's queued notification is updated to say the proposal was rejected.
  4. User B changes the status to Pending.
    • User A's pending notification is deleted as the status has changed back to the original value.

For this to work, the original status has to be saved somewhere, unless the app has an explicit "undo" action that deletes notifications.

@jace
Copy link
Member Author

jace commented Jun 25, 2014

These scenarios make clear that:

  1. The notifications system is two-way. Apps can query for subscribers and previously queued notifications and amend them.
  2. Notifications store subject/verb/object and perhaps a data field (like previous "status" in the example above).
  3. User preferences are for a notification class and a context (the "object"). A blank string (not null) context can indicate general preferences. Contexts are not organizations, they refer to any object for which notifications are being raised.
  4. A "notification" is a submission by the app to Lastuser. It is not the actual message that is sent. Several notifications can be batched into one message. The message object itself has to be stored somewhere else (perhaps different tables per channel, perhaps a single table with the channel name saved).

@jace
Copy link
Member Author

jace commented Jun 25, 2014

How are batch messages composed? In "User D and two others commented on your proposal", this message requires i18n and cannot be composed by Lastuser. It requires translated strings to be stored in the app.

This means batching is now an app concern. It also means the app is responsible for querying Lastuser about the status of notifications and updating unread notifications with new data.

@jace
Copy link
Member Author

jace commented Jun 26, 2014

Verb appears to be the same thing as notification class. Do we still need verbs? The need for subjects is also questionable. Not every notification has a subject, so they should be optional.

@jace
Copy link
Member Author

jace commented Jun 26, 2014

Preferences for a notification class are different from being subscribed to notifications of that class on a given object. UserNotificationPreference should therefore be two parts, preferences for a class and subscription to a class+object.

@jace
Copy link
Member Author

jace commented Jun 26, 2014

In this scenario, preferences for a class could once again be separate for contexts (user or organization) so that there is always a context, defaulting to the user's id but sometimes an organization's id.

@jace
Copy link
Member Author

jace commented Aug 8, 2017

Consider WhatsApp/Telegram groups:

Notification classes:

  1. A message was posted to the group
  2. You were mentioned

Transports:

  1. Notification icon
    1. Allow peeking
    2. Show on lock screen
  2. Notification light
    1. Colour
    2. Flashing?
  3. Sound
    1. Ringtone
  4. Vibrate

Extra:

  1. Mute sound/vibrate for a specific period for a specific group (a "context")
  2. Mute notification icon/light as well for the same period
  3. Show or cancel mute status

@jace
Copy link
Member Author

jace commented Aug 8, 2017

For in-app and in-browser transports, the notification will be delivered by the client app itself, not by Lastuser. Apps also own the UX for a user to manage notifications from and are the logical place for the user to look. Further, in an OS like iOS, notification management is centralised in the OS system settings. There is no scope of a Lastuser notification settings page in a native iOS app. Therefore, should notifications be centralised in Lastuser, or should they be managed by each app, using a common API (and shared library codebase)?

@jace
Copy link
Member Author

jace commented Oct 1, 2018

Deprecated by the new architecture proposed in #232 and #217. Let client apps be in charge, with Lastuser limited to just handling auth.

@jace jace closed this as completed Oct 1, 2018
@jace
Copy link
Member Author

jace commented Oct 1, 2018

The deprecation is partially inspired by the Meetup app on Android, which offers fine-grained customisation of in-app notifications per meetup group. (No other app I'm aware of does this.) We cannot possibly implement such functionality if users install a HasGeek app, but notifications are managed by the Lastuser app.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

1 participant