Apparently, while b38ae6e0ed was correct
for the default Zulip UI, it was not correct for the fluid width case,
where we did actually want to override the 1400px width rule for the
non-fixed `.app-main` element.
The right fix here is to add an additional CSS rule tweak to our
scrollbar logic. This has been carefully tested with both initial
setting states as well as toggling the state.
In a838de63d8, we incorrectly changed
the selector for accessing .fixed-app .app-main to just be .app-main,
which resulted in it affecting parts of the site it should not have.
The end result was a significant layout regression of the floating
recipient bar at some widths.
This commit migrates the Subscription's notification fields from a
BooleanField to a NullBooleanField where a value of None means to
inherit the value from user's profile.
Also includes a migrations to set the corresponding settings to None
if they match the user profile's values. This migration helps us in
getting rid of the weird "Apply to all" widget that we offered on
subscription settings page.
The mobile apps can't handle None appearing as the stream-level
notification settings, so for backwards-compatibility we arrange to
only send True/False to the mobile apps by applying those defaults
server-side. We introduce a notification_settings_null value within a
client_capabilities structure that newer versions of the mobile apps
can use to request the new model.
This mobile compatibility code is pretty effectively tested by the
existing test_events tests for the subscriptions subsystem.
If MAX_FILE_UPLOAD_SIZE is set to 0, then UI elements like the upload
icon in the compose and message edit UI and "Attachments" menu in
"/#settings" are not displayed.
A different error message is also displayed if a user tries to drag and
drop or paste a file into the compose message box.
Fixes#12152.
This adds three bools to message_container object which calculate bools
where the "(EDITED)" label should appear:
* `edited_in_left_col` -- when label appears in left column.
* `edited_alongside_sender` -- when label appears alongside sender info.
* `edited_status_msg` -- when label appears for a "/me" message.
We use the new bools and remove the complicated if else statements
from the templates for the "(EDITED)" label.
This also allows us to add a unit test to verify the logic.
This commit renames the `create_stream_permission` field in the
templates to `create_stream_policy`, matching the field used in the
database model. This matches what `invite_to_stream_policy` does and
will be clearer when the `waiting_period_threshold` is split into its
own field.
This commit replaces the `create_stream_by_admins_only` setting with a
new `create_stream_policy` setting, which mirroring the structure of
the existing `invite_to_stream_policy`.
This is important preparation for migrating the waiting period feature
to be its own independent setting.
Fixes#12236.
The error message, that is displayed when a user tries to upload a file
larger than the allowed size, currently displays a hardcoded max file
size of 25MB.
Changed this to show the correct max_file_upload_size value that has
been set by the server admin.
Fixes#12251.
Previously when disabling name changes in server settings, instead
of realm settings, the name edit button did not get disabled.
Changing name resulted in a message stating `no changes made`.
Fixes#12132.
Realm setting to disable avatar changes is already present.
The `AVATAR_CHANGES_DISABLED` setting now follows the same
2-setting model as `NAME_CHANGES_DISABLED`.
This is useful when syncing avatars from an integrated LDAP/active
directory.
The upload avatar and delete avatar buttons are hidden if avatar
changes are disabled and the user is a non-admin.
If the user has a gravatar set, then the user will not be able to
upload an image as their avatar if avatar changes are disabled.
Part of #12132.
Update stream-subscription-row in stream settings, when
subsctiption add/removal event is received. This is only
to show dynamic effects to user on sub events.
This adds the same "x" button as we have in "stream search" or "people
search" to the user status modal.
The button is shown if someone types something, or if the status
message was already set (meaning there was already a value in the
input field). If the input field is empty, the button is not visible.
This fixes the follow-up comments from #12179.
This commit removes code to update-stream-privacy-btn
in stream settings from update-sub-settings function.
Because stream-privacy-btn is not part of regular
sub-settings, it is admins only settings.
When user unsubscribe from stream by clicking on
subscription-checkmark, the URL changes to unsubscribed
stream but stream settings UI is not updated.
We should change URL and stream settings modal
simultaneously. This PR moves update-hash function
inside open-stream-modal function, which make sure that
URL is getting updated everytime open-stream-modal
function is called and not otherwise.
This commit adds `stream_ui_updates.js` module. This module
will includes functions which will update different ui elements
(i.e. subscription button, subscriber count).
This commit creates a new organization setting that determines whether
a user can invite other users to streams. Previously this was linked
to the waiting period threshold, but this was both not documented and
overly limiting.
With significant tweaks by tabbott to change the database model to not
involve two threshhold fields, edit the tests, etc.
This requires follow-up work to make the create stream policy setting
work how this code implies it should.
Fixes#12042.
This commit adds a `insert_tip_box` function and thus adds a
`organization-settings-tip` handlebars file to add a genaralised tip for
all organization settings pages. This further removes the code for tipbox
which was added in `populate_auth_methods` functions, as it wasn't making
sense there, making it more clear and readable.
This commit adds a class prop-element for all the property elements, so
that later on we can directly use this to access elements.
In `get_subsection_property_elements`, we were finding these elements using
a makeshift method, where we were finding all these elements by mentioning
all input elements, textarea, select elements, which is not a desirable
method.
So now, here in `get_subsection_property_elements` function, we are finding
these properties using the newly added class `prop-element` which makes
code more clear and readable.
In handlebars and settings_org.js, the subsection in which
`realm_message_retention_days` property lies doesn't agree, and this wasn't
observed for a long time as it's disabled, still to make things right, in
this commit we have moved the logic which handles the collection of data
from `other_permission` to `other_settings` as it makes more sense there.
This is a small patch to fix the error message an admin would receive if
they tried to change bot info and owner from the "bots" setting of the
organization settings panel.
Previously the selector returned an undefined element when trying to select
the message edit save button (since `closest` selects the closest parent in
the DOM tree). This is fixed in this commit.
The current behavior treats uppercase and lowercase characters
differently resulting in incorrect sorting of lists.
This change fixes that and makes the alphabetic sorting of columns
case insensitive.
Apparently, our use of JavaScript string `.replace()` here was buggy,
because replace() has several special escape sequences starting with
`$` if they appear in the replacement content string. We can work
around this through something of a hack, which is to pass a function
as the second argument to replace, which seems cleaner than replacing
all $s with $$s.
Thanks to Shreya for the report.
This reverts commit 6441ad0677 since it
causes two bugs: (1) when rendering new message there is glitch where
the profile picture flashes (2) when someone sends a new message their
profile picture flickers.
Now that we have a scroll container for the PM list,
it doesn't make much sense to limit the number to
five.
We may resurrect this feature if "more conversations"
actually fetches more conversations, but it doesn't
currently.
We also may soon make it easy to limit PMs to just
unread messages, which will make the max-5 feature
perhaps less necessary, and we don't want to make
the UI overly complicated.
We now just calculate two vars:
pm_list - which individual PM conversation to highlight
is_pm_filter - highlight "Private messages"
The logic is structured so that we err on the side of **not**
spuriously selecting list items:
* be defensive about `filter` not existing for some reason
* don't select anything if we have multiple pm-with
operands in the search (which is sort of undefined
behavior)
Tweaked by tabbott to add a comment explaining the multiple pm-with case.
We are basically just inlining remove_expanded_private_messages,
skipping the resize call that happens at the end of rebuild_recent.
This change makes sense even if we keep the
current UI for Private Messages.
This is the part where the whole selection is analyzed to get the
`start_id` and `end_id` of the messages that are selected (the
loop part of the copy handler).
This is extracted and exported as well.
All the inline javascript code present in email_log.html(which is
rendered when the user visits "/emails" in development mode) is
transferred to a new file: email_log.js in portico/ directory.
Fixes#11608.
Private messages too have non-`undefined` stream name. It is usually
an empty string. The check has been changed to not check specifically
for stream name to be undefined.
Color and background is made according to "day mode"
exclusively here because when copying the content
into, say, Gmail compose box, the styles come along.
This is done to avoid copying the content with dark
background when using the app in night mode.
We can avoid other custom styles since they are wrapped
inside another parent such as `.message_content`.
Using lazysizes we only load images if they are in view.
This decreases load time and save more bandwidth since images are loaded
after html is loaded and if they are on screen.
Fixes#3564.
The delete operator could throw a TypeError when attempting to
remove a non-configurable property, which is rare in practice since
they can only be created using `Object.defineProperty()` and
`Object.freeze()`. We also never uses the output of `del()` anyway.
This commit removes inline javascript code present in
accounts_send_confirm.html and moves it to signup.js. This page is
rendered when the "/accounts/send_confirm" endpoint is visited. An
empty div element is added in accounts_send_confirm.html with
unique data-page-id attribute to make it more easy to find in which
page we are, while working with the javascript code.
This commit removes inline javascript code present in reset_confirm.html
and moves it to signup.js. The reset_confirm.html page is rendered when
the user visits "/accounts/password/reset" confirmation page. An empty
div element is added in reset_confirm.html with unique data-page-id
attribute to make it more easy to find in which page we are, while
working with the javascript code.
This commit removes inline javascript code present in reset.html and
moves it to signup.js. The reset.html page is rendered when the user
visits "/accounts/password/reset". An empty div element is added in
reset.html with unique data-page-id attribute to make it more easy
to find in which page we are, while working with the javascript code.
A new javascript file "dev-login.js" is created in static/js/portico/
and the inline javascipt code present in dev_login.html is transferred
to that file. An empty div element is added in dev_login.html with
unique data-page-id attribute to make it more easy to find in which
page we are, while working with the javascript code.
This commit removes inline javascript code present in create_realm.html
and moves it to signup.js. The create_realm.html page is rendered when
the user visits "/new". An empty div element is added in
create_realm.html with unique data-page-id attribute to make it more easy
to find in which page we are, while working with the javascript code.
This commit removes inline javascript code present in
accounts_home.html and moves it to signup.js. The accounts_home.html
page is rendered when the user visits "/register". An empty div
element is added in accounts_home.html with unique data-page-id
attribute to make it more easy to find in which page we are, while
working with the javascript code.
This commit removes inline javascript code present in login.html and
moves it to signup.js. An empty div element is added in login.html
with unique data-page-id attribute to make it more easy to find in
which page we are, while working with the javascript code.
slice always returns a new string, so this could have been motivated
by ensuring we always duplicate the string, but reading the code, it's
already sliced by the caller.
This is the follow-up of PR #10267.
Here, we add typeahead for slash commands `/me` and `/poll` in compose box.
The slash typeahead will open only when `/` is the first character and all
slash commands will be displayed when one types `/`, as this helps a lot in
discoverability. This also adds a description of what the slash command
does in the typeahead.
This also remove:
- meta.current_bot_element: As usage of meta has been wrongly exploited, we
should refrain us from using meta this way i.e. to share variable between
function using the global variable, as they reduce code readability.
- update_view_on_deactivate_reactivate_failure: Again to deduplicate the the
code we're compromising with readability which isn't worth it here, also
we need to this because we have removed above meta key.
We should pass row as an argument to update_view_on_deactivate because we
update deactivate view of a row when the user get activated/deactivated by
the event system.
This also removes a redundant data variable.
This disables the Deactivate button for the current user in the Users tab,
so that it becomes hard to deactivae yourself accidently from Users tab.
Fixes#10427.
Apparently, this has been broken since
dee4e3fb89, due to the beforeSend code
here overriding the default beforeSend function that sets the CSRF
token. The correct fix was actually to just run the relevant code
directly before the channel.patch call.
Fixes#11938.
When new PMs came in, we would do a little
animation to show you the incoming message.
Unfortunately, it was broken and would animate
too many things. (The code looks at a single
var to see if PM counts changed, but there are
actually mulitple PM counts. We could fix that,
but we decided that this feature just isn't
worth the complexity.)
We still animate incoming mentions.
Fixes#11868.
This renames references to user avatars, bot avatars, or organization
icons to profile pictures. The string in the UI are updated,
in addition to the help files, comments, and documentation. Actual
variable/function names, changelog entries, routes, and s3 buckets are
left as-is in order to avoid introducing bugs.
Fixes#11824.
This allows user to download the latest version of android apk from
the apps/android.
This will help the users who use Android without Google Play to
download the app and install it with ease.
To implement this I added a Download APK link on the apps.html page
which always points to the latest released version.
Fixes part of #11647.
Or on the scroll triggered by that resize.
Then we don’t need a kludge that skips the resize handler in
situations where it might hide popovers.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This makes the "more topics" option which appears below the list of
known topics in the left sidebar appear only when it's possible there
are actually more topics to be displayed. Two specific cases it
resolves completely include:
* Newly created realms; this widget was a common source of confusion
for new organization administrators.
* Newly created streams.
There are still some corner cases this doesn't handle, e.g. if you
just joined a private stream with protected history, but there isn't
as easy a fix for those.
Essentially rewritten by tabbott to fix code duplication and comment
extensively.
Fixes#10265.
As a follow up of commit (bf1c9420df), this
commit removes the `build_realm_day_mode_logo_widget` and
`build_realm_night_mode_logo_widget` function , and changes
`build_realm_logo_widget` to take single argument `is_night` and depending
on this argument, corresponding `day mode` or `night_mode` widget is
handled.
It was impossible to add emoji to the message or to react on other's
message in mobile browsers because emoji popover used to get closed
due to the resize event being fired by the virtual keyboard. This
commit solves this issue by ignoring the resize event when the user
is trying to use emoji popover.
Fixes#11448.
Firefox and Chrome handle selection of multiple messages differently. FF
creates multiple Ranges and Chrome creates one. Code written previously
terminated when we got an empty Range or Range with same starting and ending
message. This behaviour was incorrect since the selection was valid.
* Check for same message is done after looping through all the ranges now.
* `construct_copy_div` is called once since it is much easier to determine
start_id and end_id with confidence and this avoids any overlap between
same message ids.
Extended by tabbott to include a ton of comments on how this works.
Fixes#11805.
This changes the "new private message" button to be instead "new
conversation" when looking at PMs, to avoid confusion that the button
was the right thing to do to reply to the current private message
conversation.
Fixes#11679.
Even though there are only ever zero or one active
topic widgets in our current sidebar, it's almost the
same amount of code to just manage them with a Dict.
Also, we can more easily do possible future features
like setting streams to be always-open.
This moves the configuration of widget type from settings_org to instead
live in respective HTML templates, via `data-widget-setting-type` and we
also remove `get_subsection_property_types` and refactor function
`populate_data_for_request` accordingly.
Fixes: #11708.
This fixes the bug where the `Saved` state button faded out almost
instantly (that is actually 300 ms) and `Discard` button fades out
along with `Saved` state button; the key problem here was that the
setTimeout intended to fade was actually delaying the transition from
"saving" to "saved".
Now, first of all, we use `setTimeOut` function to fadeout elements giving
fadeout_delay time as `800 ms` and we hide discard button during `saving`
state. Also, when `Discard` button is selected, `Save changes` and `Dicard`
fade out simultaneously.
Fixes: #11737.
This was introduced in e0236646
For 1.5 years we did not find a case that needed it (besides the
`a` tag hover state, that is not obvious if it was needed or it was
used as an example)
It is not obvious if this solution was a good idea. The concern was
that `body.night-mode` is more specific than `body` and some styles
might override others less specific in cases we might not want that.
Of course, we want that in the majority of cases, and css-specificity
rules are not simple to comprehend.
Good further reading:
http://cssspecificity.com/https://specificity.keegan.st/
The added complexity of the resulting styles and the added code that
might not serve any practical purpose seem to not be worth it.
If you click on the avatar, we now show the menu
right next to the avatar. The current behavior
is particularly funny for long names. (I confirmed
this with Rishi.)
This fixes several bugs with /me messages:
* We no longer hover name if you're over
the message.
* We now launch the user popup if you
click on the name.
* Even if you click on the avatar, we
launch the user popup to the right
of the name. (I think this is odd,
but it's consistent with how we
do it for normal messages.)
The underlying problem here is that you have
two possible organizations.
From a logical standpoint, the image and
name go together (and both launch the user menu):
img Alice | says hi
From a physical perspective, the main message
is "Alice says hi" and it's aligned differently
from the image:
img | Alice says hi
Our HTML reflects the latter.
HTML doesn't allow overlapping diffs, of course,
so you have to pick your poison.
The code that was removed here wasn't doing what it
was intending to do, and we really just want to pop
up the user menu above the currently selected message.
Previously, because our check for whether to close compose for clicks
on the page body was looking at popover-content, not popover, parts of
larger popover-title areas (e.g. the big avatar at the top of the user
popover) did not have the proper click handler behavior.
Also, rearrange the comments to be a bit clearer.
The modal-backdrop and user-profile-modal had their on-click behavior
overridden to simply hide the modal, thus preserving the compose box.
Keeping the compose box open after viewing a user's profile feels
like a more natural UX.
Tweaked by tabbott to move the fix into the central click handler.
Fixes: #11585.
Adds possibility for users to use | as an OR-operator (besides ,)
when searching for other users.
This is a thing reasonable folks might try, and | in the thing to
search for isn't a realisitic possibility, so there's no real downside
to adding this.
Fixes#4109.
It was impossible to search people in mobile browsers because virtual
keyboard used to fire resize event and the function call that we used
to handle this event caused the input field to loose focus and this
made it impossible to type in the people search bar.
The code in this commit fixes this by simply ignoring the resize
events when the user wants to search.
Fixes#11795.
In this commit, I've added a feature to unstar all the starred
messages. This is useful, e.g., for folks who are using starred
messages to keep track of things they should come back when next at
their desktop.
The event flow is the standard one for a feature with a confirmation modal:
(1) User clicks on unstar all messages.
(2) We display a confirmation modal; if the user confirms, we send a
request to the backend to clear all starred messages.
(3) The events system sends that UI update back to us, removing the
stars from the UI.
Fixes#11401.
This commit deduplicates the code for `build_realm_logo_widget` and
`build_realm_night_logo_widget`. It deduplicates the common code for
`build_realm_day_mode_logo_widget` & `build_realm_night_mode_logo_widget`
into tthe function `build_realm_logo_widget`.
We no longer have an empty message_content div for
messages like this:
/me gets some coffee
This requires a minor change in how we compute the
position of the message for editing.
This is totally broken on master. If you "collapse" a /me
message, it adds the "More..." link without actually
hiding any content.
I have another branch related to collapse/condense that
will make this easier to resurrect.
This is a fairly big commit, but at the end
it simplifies a lot of things.
It's difficult to fix highly coupled code in
incremental steps because, well, it's highly
coupled code.
The main thing this does is give each type of
chevron in the left sidebar its own class
* all-messages-arrow (NEW)
* stream-sidebar-arrow
* topic-sidebar-arrow
Before this change, the "All messages" chevron
was using stream-sidebar-arrow, which was a
strange name for something that's not actually
in the stream sidebar. Obviously this was
cargo culted.
There was not much JS to change here--we just
fix the click handler for "All messsages".
And then there's a one-line change to the template,
and the rest is re-organizing the CSS.
Using a more specific class avoids confusion related
to the .arrow class, which is not only a popover concept,
but also a Zulip concept in the left sidebar.
When the user logs in as an admin, and clicks on the 'edit user'
button under the url path #organization/user-list-admin, the modal
that was displayed didn't contain the user's email address under the
list of information. This commit adds the email input as a readonly
element, which at the very least provides helpful confirmation that
you have the right user.
Fixes part of #11453.
The night logo synchronization on the settings page was perfect, but
the actual display logic had a few problems:
* We were including the realm_logo in context_processors, even though
it is only used in home.py.
* We used different variable names for the templating in navbar.html
than anywhere else the codebase.
* The behavior that the night logo would default to the day logo if
only one was uploaded was not correctly implemented for the navbar
position, either in the synchronization for updates code or the
logic in the navbar.html templates.
Add a background highlight to vote count button if currently
logged in user votes on that option.
Tweaked by tabbott to use better variable names and Rishi for better
styling.
This just puts the style more clearly that one shouldn't be using
`this` to refer to the outer MessageListview object, because that
breaks unexpectedly when inside a loop.
This is a pure data function, so it shouldn't be in popovers.js file
(Steve Howell added test coverage here, and tabbott removed an
accidental functional change.)
This fixes an issue where blank lines between blocks were causing
auto-numbering of list to stop before the blank line resulting
in two separate numbered list instead of one.
Edited significantly by tabbott to explain the tricky details in the
comments.
Fixes: #11651.
Fixes#11589.
Adds SCSS style for the "unavailable" user status and enables its
usage in `buddy_data.js`.
The style is a red circle with a horizontal line. The values might
look a bit 'magic' but they were considered carefully ` height` of
1px was too thin, 2px was too thick, thus 1.5px was chosen.
If you topic-edited a single message within a narrow, we would update
all our unreads/sidebar/etc. data structures, and would rerender the
message if appropriate. However, for the corner case of being inside
a topic narrow when you did this, we didn't have logic to remove the
message from the narrow (which is the appropriate situation when you
just topic-edited a message in a narrow).
When topic-editing multiple messages including the currently selected
message (the more common case), we would end up changing the narrow,
resulting in this issue being masked.
Fixes#11601.
The correct behavior here is that we want to ensure there is
whitespace in between the syntax being added and the content on either
side. Our smart_insert logic handled this for the cases that were
common with inserting emoji (etc.), but didn't handle the more complex
cases with "quote and reply".
Fixes#11702.
Accomplished by adding a function to clear the status message with
an empty string. The html is then updated to reflect changes without a
refresh.
Currently, it's a small hassle to clear a status message. This option
makes things a bit easier.
Fixes#11630.
This new helper allows us to do the same operation
on every message in our message_store. We will
use this in a future commit to clear the `is_tall`
flags on all messages, after a resize.
We should be somewhat cautious about using this,
but simple operations should be really fast, even
if you have lots of messages in the store.
Previously, if you were in the process of editing the last message in
a narrow and a new message came in, we'd rerender that second-to-last
message, causing your editing widget to lose focus (and thus the next
few keys you typed to be interpreted as keyboard shortcuts, which
had a good chance of resulting in your navigating somewhere random).
This rerendering was essentially unnecessary; the only change to state
going into the rendering process was the next_is_same_sender CSS class
being toggled on the messagebox in the message. So, at most, we
should have been just toggling that CSS class (and this commit makes
us do precisely that).
It seems like we could further improve this code by just removing the
next_is_same_sender CSS class entirely and removing this block, but
I'm leaving that for follow-up work.
Fixes#11656.
This fixes an issue where closing stream search was not working if
user had not entered a search term and tried to close the search box
by clicking on the close icon; the problem was that we'd end up
re-opening the widget immediately after through event propagation.
Fixes: #11636.
The is_editable field includes topic edits, so we need a separate
field for whether to display these icons which are all for content
editing.
Fixes#11666.
Also adds tests to ensure that we do not accidentally overwrite
the 'beginning' variable that contains the message content upto
that point. These should prevent similar errors in the future.
The bug was added in 8119258c4d.
The bug here was that when we rerendered messages following local echo
through the echo.process_from_server code path, the eventual call to
_rerender_header() made the implicit assumption that all messages in a
message group had the same date. As a result, it created a totally
new/fake message group and called the rendering logic on that group
without calling the functions for setting up recipient row dates,
which would always result in no recipient bar date being added. This
bug was latent/invisible before, because when introduced, the locally
echoed messages were always being added to a recipient group from
today, where the recipient bar's date area was by default empty anyway.
This latent bug was revealed when we modified the structure of the app
to do date dividers between individual messages within a message
group, rather than strictly between message groups.
When we're handling a single message that was locally echoed, there
will very likely be 0 messages not removed by
`echo.process_from_server`, and we can skip the unnecessary call to
`message_events.insert_new_messages`. This is a small performance
optimization and logical simplification when sending messages.
This commit achieves two things:
1. Changes the UI of the "Create stream" form to make the
textarea previously used to get the stream description
a simple input field of type text (to suggest a single
line description).
2. Adds an extra check on the frontend side to make sure that
when users create a new stream via. the "Create stream"
option in the settings panel, they can't enter any newline
characters (i.e. we disallow the enter key from being
registered when typing out the stream description).
We must also make sure that they cannot copy-and-paste over
descriptions containing newline characters.
resolves#11617
For consistency, we should keep all the code that works with
@mentions in markdown.js. In this case, message_list_view was
rewriting the contents of the mentions in cases where users'
names had been changed since we rendered their mention.
This change should help people discover to distinguish
silent mentions in text as a part of Zulip syntax while
differentiating them from regular mentions.
To test formatting we want a hard coded date, so we
can verify the date arithmetic with stable dates.
To make the test less brittle, we disable the
feature to remove old drafts.
This was an emergency fix. We should probably just
remove the last N drafts instead of having the 30-day
limit. Or we should have a better way to stub the cutoff
date.
This is mostly adding markup, calling some convenient
functions in buddy_data.js, and adjusting CSS.
To make the circles update dynamically, I mostly
orchestrate this though activity.js for now. It's
possible we'll want to adjust that eventually to
happen through something like a `presence_events`
dispatcher, but that's essentially what
a good part of `activity.js` does now.
We now have a function get_user_circle_class
that returns one of these values:
"user_circle_green"
"user_circle_orange"
"user_circle_empty"
And we put that in the templates.
And then CSS renders the circle of the appropriate
color.
The unit tests now explicitly capture whether
we are rendering the correct kind of circle.
This is a pure code move.
We want to use user circles in the left sidebar,
so this code will no longer belong in
right-sidebar.scss.
This code is just related to drawing the circles.
We can still position in size in other CSS files
(with more context-specific selectors).
This fixes a longstanding UI issue when you have way too many recent
private message conversations, as you can now scroll down the list to
find what you're looking for.
Fixes#5384.