mirror of
https://github.com/zulip/zulip.git
synced 2025-11-02 21:13:36 +00:00
Expand pointer and unread counts guide.
This commit is contained in:
111
docs/pointer.md
111
docs/pointer.md
@@ -1,40 +1,54 @@
|
||||
# Pointer and unread counts
|
||||
# Unread counts and the pointer
|
||||
|
||||
When you're using Zulip and you reload, or narrow to a stream, how
|
||||
does Zulip decide where to place you?
|
||||
|
||||
In general, Zulip takes you to the place where you left off (e.g. the
|
||||
first unread message), not the most recent messages, to facilitate
|
||||
reviewing all the discussions that happened while you were away from
|
||||
your computer. The scroll position is then set to keep that message in
|
||||
view and away from both the top and bottom of the visible section of
|
||||
messages.
|
||||
Conceptually, Zulip takes you to the place where you left off
|
||||
(e.g. the first unread message), not the most recent messages, to
|
||||
facilitate reviewing all the discussions that happened while you were
|
||||
away from your computer. The scroll position is then set to keep that
|
||||
message in view and away from both the top and bottom of the visible
|
||||
section of messages.
|
||||
|
||||
But there a lot of details around doing this right, and around
|
||||
counting unread messages. Here's how Zulip decides which message to
|
||||
select.
|
||||
counting unread messages. Here's how Zulip currently decides which
|
||||
message to select, along with some notes on improvements we'd like to
|
||||
make to the model.
|
||||
|
||||
## Recipient bar: message you clicked
|
||||
First a bit of terminology:
|
||||
|
||||
* "Narrowing" is the process of filtering to a particular subset of
|
||||
the messages the user has access to.
|
||||
|
||||
* The blue cursor box (the "pointer") is around is called the
|
||||
"selected" message. Zulip ensures that the currently selected
|
||||
message is always in-view.
|
||||
|
||||
## Pointer logic
|
||||
|
||||
### Recipient bar: message you clicked
|
||||
|
||||
If you enter a narrow by clicking on a message group's *recipient bar*
|
||||
(stream/topic or private message recipient list at the top of a group
|
||||
of messages), Zulip will center the new narrow around the message you
|
||||
clicked on. This provides a nice user experience where you get to see
|
||||
the stuff near what you clicked on.
|
||||
of messages), Zulip will select the the message you clicked on. This
|
||||
provides a nice user experience where you get to see the stuff near
|
||||
what you clicked on, and in fact the message you clicked on stays at
|
||||
exactly the same scroll position in the window after the narrowing as
|
||||
it was at before.
|
||||
|
||||
## Search or sidebar click: unread/recent matching narrow
|
||||
### Search or sidebar click: unread/recent matching narrow
|
||||
|
||||
If you instead narrow by clicking on something in the left sidebar or
|
||||
typing some terms into the search box, Zulip will instead focus on the
|
||||
first unread message matching that narrow, or if there are none, the
|
||||
most recent messages matching that narrow. This provides the nice user
|
||||
experience of taking you to the start of the new stuff (with maybe a
|
||||
bit of old stuff still in view at the top), which is usually what you
|
||||
want. (When finding the "first unread message", Zulip ignores unread
|
||||
messages in muted streams or in muted topics within non-muted
|
||||
streams.)
|
||||
typing some terms into the search box, Zulip will instead selected on
|
||||
the first unread message matching that narrow, or if there are none,
|
||||
the most recent messages matching that narrow. This provides the nice
|
||||
user experience of taking you to the start of the new stuff (with
|
||||
enough messages you'ev seen before still in view at the top to provide
|
||||
you with context), which is usually what you want. (When finding the
|
||||
"first unread message", Zulip ignores unread messages in muted streams
|
||||
or in muted topics within non-muted streams.)
|
||||
|
||||
## Unnarrow: previous sequence
|
||||
### Unnarrow: previous sequence
|
||||
|
||||
When you unnarrow using e.g. the escape key, you will automatically be
|
||||
taken to the same message that was selected in the home view before
|
||||
@@ -44,32 +58,53 @@ message in the home view (or the bottom of the feed if there is
|
||||
none). This makes for a nice experience reading threads via the home
|
||||
view in sequence.
|
||||
|
||||
## New home view: "high watermark"
|
||||
### New home view: "high watermark"
|
||||
|
||||
When you open a new browser window or tab to the home view (a.k.a. the
|
||||
interleaved view you get if you visit `/`), Zulip will take you to the
|
||||
highest message ID (a.k.a. "high watermark") that your cursor has ever
|
||||
reached in the home view (called the *"pointer"* in the Zulip
|
||||
API). Because of the logic around unnarrowing in the last bullet, this
|
||||
is usually the same as the first unread message in the home view, but
|
||||
interleaved view you get if you visit `/`), Zulip will select the
|
||||
furthest down that your cursor has ever reached in the home
|
||||
view. Because of the logic around unnarrowing in the last bullet, this
|
||||
is usually just before the first unread message in the home view, but
|
||||
if you never go to the home view, or you leave messages unread on some
|
||||
streams in your home view, this can lag.
|
||||
|
||||
## Narrow in a new tab: closest to pointer
|
||||
We plan to change this to automatically advance the pointer in a way
|
||||
similar to the unnarrow logic.
|
||||
|
||||
### Narrow in a new tab: closest to pointer
|
||||
|
||||
When you load a new browser tab or window to a narrowed view, Zulip
|
||||
will take you to the message closest to your pointer, which is what
|
||||
you would have got had you loaded the browser window to your home view
|
||||
and then clicked on the nearest message matching your narrow (which
|
||||
might have been offscreen).
|
||||
will select the message closest to your pointer, which is what you
|
||||
would have got had you loaded the browser window to your home view and
|
||||
then clicked on the nearest message matching your narrow (which might
|
||||
have been offscreen).
|
||||
|
||||
## Forced reload: historical recreation
|
||||
We plan to change this to match the Search/sidebar behavior.
|
||||
|
||||
### Forced reload: state preservation
|
||||
|
||||
When the server forces a reload of a browser that's otherwise caught
|
||||
up (which happens within 30 minutes when a new version of the server
|
||||
is deployed), Zulip will try to take the user back to the exact same
|
||||
place where you were before the server-initiated reload, in every way
|
||||
(same selected message, and even the same exact scroll position!).
|
||||
is deployed, usually at a type when the user isn't looking at the
|
||||
browser), Zulip will preserve the state -- what (if any) narrow the
|
||||
user was in, the selected message, and even exact scroll position!
|
||||
|
||||
For more on the user experience philosophy guiding these decisions,
|
||||
see [the architectural overview](architecture-overview.html).
|
||||
|
||||
## Unread count logic
|
||||
|
||||
How does Zulip decide whether a message has been read by the user?
|
||||
The algorithm needs to correctly handle a range of ways people might
|
||||
use the product. The algorithm is as follows:
|
||||
|
||||
* Any message which is selected or above a message which is selected
|
||||
is marked as read. So messages are marked as read as you scroll
|
||||
down the keyboard when the pointer passes over them.
|
||||
|
||||
* If the whitspace at the very bottom of the feed is in view, all
|
||||
messages in view are marked as read.
|
||||
|
||||
These two simple rules, combined with the pointer logic above, end up
|
||||
matching user expectations well for whether the product should treat
|
||||
them as having read a set of messages (or not).
|
||||
|
||||
Reference in New Issue
Block a user