-
-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add the controller for what's new notification for feature announcements #329
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be interested to hear why an array was chosen for the Notification state. It seems that it's almost always being accessed by id
, so would it be more appropriate to store them in a Record
keyed by id
?
One potential downside would be losing the sort order, but we can already derive the sort order here because we have the date
property. I wouldn't be concerned about performance here, especially given that Objects will preserve their insert order by default, so we can make the "sort" step really cheap by having them configured in the order we view them in.
I just realized a requirement of the designs that we have not thought of a good solution for yet: the button or link associated with each notification is expected to have a unique set of methods called / actions taken on click. For instance, the current action taken on click of the button in the current swaps pop up is:
But on click of the mobile link, the user is supposed to see another popup, or maybe be taken to an external link. This controller, or at least the notification data structure, will need to support the passing of some information about this to the front end. First I'll get clarity on what the product/design requirements are. |
Regarding my previous comment: I spoke with Jacob and it seems that the action taken on each link/button click can just be to direct the user to a link. I think we can handle metrics for the clicks of these on the front end without any need for configuration via the notification object. And we can stop supporting custom actions like However, we will need to add one more property to the notification type, which is a |
Using a route for each action seems like overkill. These actions may not have any associated UI after all. We don't need to contort our routes to perform arbitrary actions. Note that we don't need the action for each notification to be some serializable value - it can be a function. We don't need this controller to know what the action is. It can just be given an |
Yes, agreed. I think that as long as notifications can include a url, then we are good. So current implementation should work fine. |
Just to be clear - I was saying the opposite of this. If we require all notification actions to have an associated URL, we'll need to create a route for each one. That is not good. We use routes to represent "pages" in the UI (or UI state in general), we shouldn't have to use them for arbitrary actions too. That would be a misuse of the routing system. It seems that that solution was arrived at because the rest of the notification configuration is JSON, so it can't contain functions. But there's no reason for the notification configuration to be JSON. The state has to be, but the configuration doesn't. It would be easy and straightforward to pass functions in as part of the notification config to act as handlers for any buttons, and it wouldn't require us to migrate each action to a route. The swaps notification for example, we could leave the handler exactly as-is. Does that make sense? Or is there some reason for this change that I'm not seeing? |
@Gudahtt I know we discussed this on Friday, but after rereading your comments here, I just want to clarify what may have been a misunderstanding between us. I never meant to suggest we use a route for each action. My intended meaning was: I believe that, on click of the action button/link associated with a notification, only 1 thing should happen: to take the user to a new location. That location can either be within MetaMask or an external site. We simply won't support any additional actions being taken on click of those buttons/links. (We would, of course, track metrics for each of those clicks, but that doesn't need to be accounted for in the notification configuration.) I arrived at that first when learning the requirements of the current notifications: The "MetaMask Mobile" and "Help Improve MetaMask" links will take the user to external sites. I'll contend that the swaps notification button only needs to take the user to the swaps page, i.e. something like I like the simplicity of a notification feature that only does two things: gives the user some information via text, and gives them a link to follow for more information or to take further action. I still think it will be simpler, with this approach, to eventually support remotely hosted notifications. Of course, allowing arbitrary function calls on click is much more powerful... and maybe we will need that some day, so maybe the time is now. So I fully agree with you that if we want to support "a unique set of methods called / actions taken on click" we should take your recommended approach. I am just skeptical that we really need to support it. |
It's not just confining what we can do with the notification action though - it's also more work. I don't agree that it's simpler - even when we consider the possibility of remotely hosted notifications. To be honest I don't follow why you'd think it was simpler. As for whether routes would serve our needs here just fine, they already don't. In the example you showed for instance, we don't have a way to specify that it should be an ETH swap (the |
Right, I don't think we should do any of these things with a route. I realize I said some things that could have obscured that further so I'll add some more notes to clarify further. For metrics, I think we can have a general "Notification action clicked" event, and it can be passed the notification title, or unique id. That is how we handle the metrics actions. And instead of doing ... maybe we should clarify synchronously |
date: string; | ||
image?: string; | ||
actionText: string; | ||
isShown?: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add actionFunction
to the interface here
.filter((newNotification) => !existingNotificationIds | ||
.some((existingId) => (existingId === newNotification.id))) | ||
.map((notification) => { | ||
if (!((notification.actionText as string).length > 0 && notification.hasOwnProperty('actionFunction'))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is correct, but I think there is an elegant way to ensure this condition is met just by using the type definition. Could be to have an action
property which is an object, which is optional, but which itself has two properties (function and text) that are both required. You might have to read into some typescript documentation
*/ | ||
actionCall(id: number): action | null { | ||
const notification = this.allNotifications.find((notify) => notify.id === id); | ||
return notification ? notification.actionFunction as action : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So instead of returning the action function, we could just call it here.
Replace return notification ? notification.actionFunction as action : null;
with something like
notification?.actionFunction?.()
This could use a rebase - it's behind |
ea6be92
to
7d4a89f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
interface Notification { | ||
id: number; | ||
date: string; | ||
image?: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could probably get rid of this property too, since nothing in this controller uses this 🤔
Not a blocker though I suppose! We can always remove it later.
6ef9696
to
2f505d7
Compare
cbe2df2
to
32f6687
Compare
Co-authored-by: Mark Stacey <markjstacey@gmail.com>
#375) * Remove use of actionCall, fix updateViewed, manage state with objects instead of arrays, simplify types * Only store isShown in state, not in the config * Remove undefined possibility from the allNotifications type * Fix NotificationController tests * Fix logic in NotificationController _addNotifications: ensure current state notifications are not deleted.
32f6687
to
18ab002
Compare
The controller adds the notifications to the state and keeps and updates the status of whether it is seen by the user or not.
Associated to issue #23