NOTE: This is a draft and work in progress.
Roundcube Next is going to entertain a variety of applications ("apps"), integrated with one another to provide the best possible human experience for messaging and scheduling, among other things.
The division of components that make up the complete Roundcube Next application suite has already been established, in that we will at first entertain email messaging, calendar-based scheduling and address books (milestone $x-$y), bearing in mind other object types and different contexts are on the roadmap as well (instant messaging, and others).
These components are seated in a [[ https://git.kolab.org/w/roundcube-next/shell/ | Roundcube Shell ]], which for the purpose of a sustainable roadmap needs its horizon defined.
## Application Model Design Considerations
### Data Communication, Data Storage, Communication and Presentation Layers
For a given user, more than one account may be configured. Multiple "virtual folders" may aggregate the different types of messages from each account in to a merged view, meaning that the INBOX is an aggregate of all INBOX folders, Drafts and aggregate of all Drafts, and such and so forth.
(NOTE) **Aditya says:** Is this a good idea? I see the point and I know some clients do this, but It would be much simpler for both developers and users to not have merged views and just have a menu to switch between accounts; also because it's better to not let users accidentally mix up identities.
This means that when a passive event is triggered (**Data Communication**, passive if something happens on the server and the client is told / notices), the representation in the internal structure (**Data Storage**) needs to be able to represent two things:
(NOTE) **Aditya says:** If we want to do this, the way we've organized exposition of models to components (all the data available at a given route is arranged in the model() method of that route, and all components access only that, without making any queries of their own) should make it simple enough to "annotate" updates and merged model data.
# The event happened for account A, updating the current local working copy of account A's (meta-)data.
# The internal virtual aggregate of the data associated with account A and the data (of the same type) from all other accounts will need to be updated.
This leads to new events to need to be triggered in the client software (**Communication**), which depending on the current view the user is looking at may or may not cause the presentation layer to need to be updated, and in a particular way as well.
### Implications on Application Model Design
For example, we know that when a new email message comes in, we want to emit an event (publish) for other applications (subscribers) to consume.
To illustrate the complexity involved, consider what a notification mechanism may need to be able to deal with at its precipice of evolution;
- If the user is already in a mail view;
- and the real estate that needs updating to represent the new message(s) is within view;
- an additional notification is superfluous;
- unless the update of the presentation layer is insufficiently stimulating (compared to the importance of the event).
- an additional notification may not hurt a user unless the notification blocks real estate in use or blocks work-flow.
- and the real estate that needs updating to represent the new message(s) is outside the current view;
- A simple indicator at the top of the mail view may be sufficient to let the user know of new, unseen messages.- TODO
- If the user is not already in a mail view;
- Notifications of different sorts may be suitable for certain data types.
- Which could mean the browser tab not having focus
- Display native notifications for any and all things that can be notified
- For data updates (and not application state updates like "syncing", "disconnected"), notifications should be persistent
- Notifications for similar data types should be "merged" to avoid clutter- TODO
NOTE: In any case, the changes to the presentation may be subject to a reasonable rate-limit and/or level of smoothness and/or animation.
NOTE: In addition to the former considerations, also consider the effect of a notification that can be clicked on -- to either update the focal point or switch views.
So, when a new message comes in but the user is in a "mail" view already, however that mail view may end up being composed, it means little to both amend the list of messages in a folder display on the current real estate being viewed, and pop up a notification-like UI element to let the user know a new message arrived.
Additionally, the existing focus point (selected message UI element) should probably remain the focal point in all of this, to prevent the focal point moving on the X- or Y-axis.
### Data Types and Treatment
In contrast, however, should the current list of messages displayed have scrolled beyond the slice in which the new message would have been inserted in to the current view, a notification UI element may be justified.
In another example, when a new message comes in to a "mail" app, other "apps" may want to interfere with the representation of that event;
- An iTip invitation may need to be handed of to a "scheduling" app, which may or may not consider itself a terminal end-point for the particular event.
- The same iTip invitation may need to be passed on to a notification mechanism but only after the "scheduling" app has treated the event (but considered itself not a terminal end-point).
The emission of "an event" that "is about to happen" and/or "happened" therefore deserves queuing priority capabilities as well as ordering event subscribers, each of them allowed to determine its own finality in treating the event.
(NOTE) **Aditya says:** Per-ordering event subscribers might be too much to ask if we do not know which apps are going to be present, and it also creates uncertainity about what third-party apps will do. An alternate solution for this problem is to simply have an event subscriber "pass" the event on. See below...
There are two events here: "mail.invitationOpened" and "scheduling.invitationTreated". To establish causality, a subscriber that consumes an event must take the UID property within the event object and pass it on to the events it fires itself.
A third app (after "mail" and "scheduling") may wish to handle the first event if there is no scheduling app, and the second instead if it is present. Thus, it can subscribe in a certain priority order: ["scheduling.invitationTreated", "mail.invitationOpened"]. This order can be published before runtime, by letting the app's initializers "register" it's event consumption priorities in some data structure. The global eventing system can then prune nonexistent event dependencies and take care of firing in the right order.