Apparently, our logic was broken on systems where altKey and metaKey
are different, because we didn't ignore hotkey combinations that
included altKey.
Fixes#3738.
This restyles the subscriber list in the subscription settings panel to
have a more padded and lighter aesthetic and replaces the dark red
buttons with transparent buttons that have only red borders and inner
text.
Change `from django.utils.timezone import now` to
`from django.utils import timezone`.
This is both because now() is ambiguous (could be datetime.datetime.now),
and more importantly to make it easier to write a lint rule against
datetime.datetime.now().
It's currently broken (e.g. see Issue #3713) and non-responsive. The whole
page needs to be styled anyway, so these can be added back once that
happens.
This makes text look bad in Chrome on Linux; it happened to not cause
problems in production because our minifier broke it (see
https://github.com/yui/yuicompressor/issues/91), but text looked bad
in development.
The transition "all" by default also affected the transition
on the height change of the compose box which ended up making the
compose box appear to be laggy and choppy.
Add neccesary UI in #administration and #settings for
changing the bot owner. The bot owner select control
is rendered dynamically in order to avoid performance
issues in case of large number of users.
Fixes: #2719.
Previously the mechanism worked such that the innerHTML was being
appended to directly potentially thousands of times which has horrific
performance implications. By concating all the strings together before
appending to the HTML it all gets rendered in one chunk without forcing
a re-render of previous elements. Performance is ~15x-20x faster now.
Use `name_to_codepoint.json` file (and the similar structure in
emoji_codes.js) to map emoji names directly to codepoints and change
the rendered emoji image to `unicode/<codepoint.png>` rather than
`<emoji_name>.png`.
Fixes: #3539.
If you send a group PM from the home view, and then one of the
recipients changes their email, and then you send a group PM
to the same recipients, we need to make sure we don't create
a spurious recipient bar. This fix makes this happen by
changing util.same_recipient() to look at user ids instead of
emails.
Using stream_id in recipient comparisons fixes a
bug in this scenario: go to home view, send message
to stream, wait for admin to rename stream, send
another message to the stream. Before this change,
the stream name would live-update but you'd get a
spurious recipient bar due to the prior message still
having the old stream name in places internally.
There were other ways to fix the live-update glitch,
but it's just generally cleaner to do stream id
comparisons.
Part of this change is to add stream_id to
compose_fade.set_focused_recipient().
Change the remaining "Admin settings" with a button, namely
changing a stream's privacy, to instead be a "[Change]" link
opening a confirmation modal.
Fixes: #3493.
This changes the time render to be done on the client-side and
therefore take advantage of knowing the client’s timezone, along with
being formatted in a more human-parseable way.
This removes the arrow from the subscriptions header at full
widths where the arrow is not required because the subscription
settings/stream creation prompt don't take up the full width of
the screen and require an arrow to go back to the streams list.
Fixes: #3762.
This changes the layout of administration for non-administrators such
that they can view organization settings and emoji settings and
displays everything as readonly unless they have the capability to edit.
For now, we just enabled this for the emoji settings and organization
settings features.
This removes all the .expectOne statements and replaces with a
single broad stroke .hide() that doesn't check if they exist,
but rather just ensures they are hidden by default until triggered.
This adds to Zulip support for a user changing their own email
address.
It's backed by a huge amount of work by Steve Howell on making email
changes actually work from a UI perspective.
Fixes#734.
* Created a drafts modal to display/restore/delete drafts
* Created a Draft model to support storing draft data in localstorage
* Removed existing restore-draft functionality
* Added casper and node tests for drafts functionality
Fixes#1717.
This re-adds the deleted "Delete Avatar" button back to the
settings/your-account tab view in the overlay, which only appears
if you do not currently have a gravitar.
We now sweep all active messages for avatar changes and update
the message items and re-render, rather than patching the
DOM. This avoids some quirks that happen when subsequent messages
get sent and we re-render previous messages out of the message
store.
Our approach here is similar to how we do full-name updates.
In f75af94984 I added some
lines of code that made it so that live updates for avatar
urls would affect messages currently in the browser.
This change worked well when the live update actually happened,
but then the next time the user would reload, the avatar in
the message pane would regress back to showing the avatar urls
from the server (which could have caching issues of their own).
This fix removes a couple lines of code that had the intended
effect of making all of your messages from any given sender
show the same url (good) but which generally grabbed
the url from an old message (bad).
After this fix, we go back to having old messages possibly
showing the old avatar urls, but new messages will display the
new avatar.
(There are lots of moving parts in the avatar system, because
not only do browsers cache image urls, but our server caches
messages and recipient info, so there have been "fixes" to
avatars since this change that are valid fixes in their own
right but not directly relevant to this commit.)
This provides a fairly intense highlighting of when you're hovering
over a given emoji reaction element.
We may want to tone down the color a bit; I'm hoping for some feedback on this.
This makes life a lot easier for people inviting users to a new Zulip
organization, since they can give some form of context now.
Modified by tabbott to clean up CSS, backend code flow, and improve
the formatting of the emails.
Fixes: #1409.
The current logic that we have is as follows:
* If a message is locally echoed, the draft is stored via the locally
rendered message, and that system takes care of it. So no need to
store it here.
* If the message isn't locally echoed, we don't close the compose box
until, so the content is safe here as well. It'll be saved as a draft
if the compose box is later closed due to a failure sending.
This replaces the settings toggle which had the same markup as the
current component toggle, but not the same JavaScript, along with
having an issue with inline-block spacing, with the new JS generated
one.
We now call activity.build_user_sidebar when we initialize
the user sidebar, which avoids some janky jQuery code
that was intended for partial updates.
With 2000 users in dev, the amount of time to build the sidebar
decreases from 1100ms to 700ms in my tests. (Times vary a bit,
but it does seem consistently faster now.)
Activity.update_users() is still used to handle partial
updates of users in the buddy list, but now all the places
that want to re-build the whole widget go through
build_user_sidebar().
The pinned streams were sorted in alphabetic order (i.e. Verona appears
before devel). The reason is that after we plucked pinned streams out from
stream_data.subscribed_streams(), we didn't sort them again, so they
remained in the alphabetic order used in stream_data.
However, we did sort unpinned streams explicitly by using custom compare
function in stream_list.js (by default sort by lowercase stream name,
but when there are more than 40 subscribed streams, sort active streams
first). That's why this issue only relates to pinned streams.
Changes were made to sort pinned streams by lowercase stream name, always,
whether they are active or not (different from unpinned streams).
Tests were added to ensure this overall sort order is correct, i.e.
1. pinned streams are always sorted by lowercase stream name.
2. pinned streams are always before unpinned streams.
3. unpinned streams are sorted by lowercase stream name, if there are more
than 40 subscribed streams, sort active streams at the top, among active
and inactive streams, still sorted by lowercase stream name.
Fixes#3701
User search for streams will now return results where the stream
description (but not the stream name) include the string in the
user query.
The filtering process first obtains the streams whose names match the
user search query, then sorts and displays them. From the remaining
streams, it obtains streams whose description matches the query and
displays them in sorted order after the name match results. Other
streams are not displayed.
Fixes: #2674.
When an admin deactivate a stream, we now remove the
appropriate row from the default streams tables for other
folks viewing default streams in the admin tables.
We add a default_streams_table() function that builds an
object encapsulating the defaults streams table in the admin
system.
This function allows us to simplify the click handler code by
closing on row/stream_name rather than picking those values out
of the DOM.
Fixes#268.
Modified significantly by tabbott to:
* improve code cleanliness / repetition
* add missing translation tags
* move code into message_edit.js
* correspond with the new backend.
* not display the option for messages only topic-edited
The new behavior is:
(1) If enter-sends is enabled, just send the messsage.
(2) If enter-sends is not enabled, return focus to the compose area.
Based on great work by khantaalaman in #3673.
Fixes#3489.
This is a fairly risky, invasive change that speeds up
stream deactivation by no longer sending subscription/remove
events for individual subscribers to all of the clients who
care about a stream. Instead, we let the client handle the
stream deactivation on a coarser level.
The back end changes here are pretty straightforward.
On the front end we handle stream deactivations by removing the
stream (as needed) from the streams sidebar and/or the stream
settings page. We also remove the stream from the internal data
structures.
There may be some edge cases where live updates don't handle
everything, such as if you are about to compose a message to a
stream that has been deactivated. These should be rare, as admins
generally deactivate streams that have been dormant, and they
should be recoverable either by getting proper error handling when
you try to send to the stream or via reload.
(There was a method with the same name before, but it wasn't
being used. The new version will accept stream_id instead
of name, and we will use it as part of deactivating streams.)
We already do detection of the client on the backend based on
User-Agent and the fact that it's a JSON view, which is pretty safe.
This fixes an issue where the server was not treating the Electron app
as its own client.
This significantly simplify the logic for our logging process, making
it the case that websockets message sending requests always are logged
as having the exact same client as a normal AJAX request from that
server.
This prevents users from either dragging formatted markup into content
editable boxes or pasting it in. This uses the “input” event rather
than “paste” because “paste” does not have the end result of the
contents whereas “input” does.
This is not a security vulnerability as it may seem. Processing on the
backend sanitizes input if it contains HTML.
We use to have client-side logic that would append timestamps
or random numbers to avatar URLs to force browsers to
refresh their cache.
We no longer need this now that the back end maintains
versions for avatar changes and puts the version in the URLs.
When we process messages for unread counts, we now call
people.pm_reply_user_string() to get a string of user ids,
rather than using emails that may have changed since the
message was originally created.
There is a particular case in which when a user clicks on a tab, then
uses the goto method to go to another, and then clicks on the original
tab again, it will not load the original tab. This is due to the fact
that the goto function that is used to navigate to a tab without
clicking does not set the last_value, therefore leaving a state that is
incorrect and denying a view update in the case that a user performs
the following:
Click B -> Goto A -> Click B
In this case, it saves the last_value as “B” and so when a user clicks
back on “B” it does not trigger any change as it thinks the user is
going from “B” to “B”.
This fixes the issue where scrollbars that take up space (eg. Chrome on
Linux) force the inline-block items to overflow their container and
fall down a line.
For our user administration, we now primarily work with user ids
that get put into data-user-id attributes. We still put emails in the
tags to make our Casper tests easy to maintain.
This requires a minor change to the back end to pass down user ids
for the /users endpoint (in get_members_backend).
Like the topic edit pencil icon, the new UI is mostly invisible, but
appears when you hover over the recipient bar.
* Added a tag to hold the mute button in recipient_row.handlebars with
corresponding styling in zulip.css.
* Added an event handler for the mute button in click_handlers.js.
Fixes: #2235.
Now message senders are vertically aligned with the content, whether
mesasges are /me style status messages or not.
We'll want to do more in the future to move both sender names and
message bodies further towards the avatars, I think, but this is
definitely an improvement.
The original templating for this code was super complicated, due to
what appears to be a misguided effort to share code between the
status_message and non-status-message cases, that really just resulted
in a lot of if statements.
When we get notified of an email change and the compose box is
open for PMs, we should update the email in the compose box.
This helper will be useful when we start handling such events.
We now convert our pm-with search operand to a list of user ids
for matching against messages, rather than using emails. On the
message side we look at user ids from display_recipient.
This replaces the bootstrap default modal footers that have a
[data-dismiss] button with an .exit button in the top section of the
overlay that is styled congruently to the current subscriptions page.
This adds usage notes and comments to the component.toggle class
to make it more readable and usable for those who are unaware with
the prototype of the class or how to create a new instance.
API: Adds a "display_order" to the response, which is a suggested order of
importance for the clients or recipient types respectively.
frontend: Changes messages_sent_by_{client,recipient_type} to use a fixed
order for any given user.
Also includes a number of changes to messages_sent_by_recipient_type that
were convenient to do at the same time, since the two charts share a lot of
code.
In preparation for turning messages_sent_by_client into a bar chart.
This removes the "pie-specific" pieces from the functions used by
messages_sent_by_{client,type}.
This is technically part of the settings page redesign in the next
commit, but it's probably useful to keep separate, since it touches
totally different code.
This makes the subscriptions page responsive by having the settings tab
slide over when a user taps on a stream, giving almost the whole screen
to view the settings.
Previously, set_muted_topics was calling update_unread_counts once for each
topic in the input; this results in poor performance when there is a large
number of muted topics.
Fixes: #3605
Adds a new webhook integration for WordPress blogs. Both WordPress.com
and self-installed blogs are supported, with minor differences that
are described in the documentation. It creates a new message for each
action, the stream and topic may be specified or use default values.
WordPress actions supported:
publish_post: a new blog post was published
publish_page: a new page was published
user_register: a new user account was created
wp_login: a user logged in
Notes: comment_post only provides the id of the parent post, not title
or link, so was not included. On further testing, I found edit_post is
not very practical, it also fires while a new post is being written, and
when posts are deleted. (I think it tracks drafts too.) I've removed it,
as it seems more confusing than useful.
Fixes#3245
We have added people.pm_with_url(message), which computes a
PM url from a private message using user ids rather than emails.
We call this in add_message_metadata(), since the slugs will
be valid even if emails change, so we don't need to compute
them on the fly during message rendering.
Currently, searching for group private messages requires typing each
person's email individually. This change improves the typeahead
suggestions for group `pm-with` searches by suggesting additional people
whenever a comma is entered.
Fixes: #3575
Previously, we were incorrectly not updating the data-message-id used
in the .message_reactions section to use the final ID when
echo.reify_id was called.
This meant in particular that if someone else reacted to a message you
sent, and you clicked it to share the reaction, you'd get an exception.
The function people.update_email() is not yet connected
to anything, but it sets the stage for upcoming changes.
When emails get updated, fundamentally we just update
the appropriate person object and add a new key to
people_dict. We sort of get a shim for free--old email
lookups will continue to work--but we add blueslip warnings
for stale lookups.
Now that we have the minified_source_filenames feature, we don't need
to serve zxcvbn from node_modules/ directly to avoid re-minifying it.
Moving this this allows us to stop shipping the (duplicate)
node_modules directory in release tarballs, which will save many
megabytes of unnecessary increase in our release tarball size.
In a96fdd18b1, I introduced a few
regressions related to the blue highlighting that happens
in the top left corner for Home, Private messages, Starred
messages, and @-mentions. Basically, we weren't clearing
the highlighting when we thought we were, so Home would stay
blue too long and the other filters wouldn't turn blue.
We went a surprising long time before noticing the regression.
This fix adds a function called deselect_top_left_corner_items()
to clear the blue backgrounds, so that will happen more explicitly.
And then I restored a line of code to pm_list.js that puts the
blue in place when you are in an is:private narrow (vs. a
specific PM narrow).
When filtering streams, we were incorrectly treating the regexp input
provided by the user as a regular expression, meaning that terms like
`c++` would trigger errors because they are invalid regular expression
syntax. We fix this by replacing RegExp with a simple IndexOf check.
Node test added by tabbott.
Fixes#3559.
The [More...] link for un-collapsing messages has been made easier to
click, by giving it a top margin which prevent clicks on the top
portion of it from being masked by the top part of the message body.
Fixes#3313.
This fixes a number of issues in the prototype /stats graphs, including:
* Adding a Total Users number to the Users graph.
* Changing the Messages sent over time graph so that the bot
trace is hidden by default.
* Fades out the last bars in the weekly view to represent unfinished
ata.
* Sets the default view to weekly only if the realm is > 12 weeks old.
* Gets rid of the tooltips and replaces them with hover text
for the Number of Users graph.
* Fixes a bug in the legend colors for the Messages Over Time
graph.
* It also adds the year to the hover text.
* Sets the pie chart colors and adds spaces between sectors.
* Changes the font to Humbug.
This fixes an issue where Array.prototype.split is called on an
undefined instance due to the EventTarget.oldURL property not being
recorded in IE. We fix this by recording it ourselves.
This adds a frontend for the analytics system we've had for a few
months, showing several graphs of the data in Zulip.
There's a ton more that we can do with this tooling, but this initial
version is enough to provide users with a pretty good experience.
Fixes#2052.
Various server events can be passed into admin.js before
the initial widgets have been set up. This code short
circuits live update code when these events happen.
Note that live updates don't consistently work for the
admin pages before this fix (and after it), since don't
store data changes when the widgets aren't built.
The of stream-search box in left-sidebar was being opened incorrectly
when clicking the + icon to add a new subscription (because that's
what would happen if you clicked the area around the +). Changes were
made in click_handlers.js by adding e.stopPropagation and
e.preventDefault in appropriate click handler.
Fixes#3517.
Currently the loading spinner on the settings page is too small
and is in the left corner of the parent box. This changes the width
to the same as the main page: 100% fill inside a 38px square container.
We now trigger an event in user_events.js, and we dynamically
build the list of names in pm_list.js by calling out to
people.get_recipients().
We have a few variations of functions that build lists of names
for huddles, which should be cleaned up eventually. They are
called at different times in the code path, so the different
functions, while doing mostly the same thing, start with different
data sources.
This breaks the function
message_store.get_private_message_recipient into two functions:
get_pm_emails and get_pm_full_names.
The get_pm_emails function behaves the same way as the original
function, but get_pm_full_names now dynamically gets full names
from people.js using the user_id in the message.display_recipient
row.
This makes the recipient bar show the correct new name if you reload
your page. It doesn't help with live updates.
Note that this only works for people who are currently logged in.
Folks that log in after you may pick up the old full name from
the message. (I'll address this in a separate commit.)
Replaces the hardcoded list of emoji_names and unicode_emoji_names in
static/js/emoji.js with a list generated from emoji_map.json, both to get
the list out of version control and so we can start modifying it for our
autocomplete. This does not change the contents of emoji_names. It sorts and
removes duplicates from unicode_emoji_names (causes no change in behavior,
since unicode_emoji_names is only used as if it were a set).
Previously, if you pressed the escape key with various modals open
(keyboard shortcuts, markdown help, etc.), the modals would close but
also the compose box would close and the user would be unnarrowed.
This changes makes it so all that happens is the modal closes.
Fixes#3472.
This fixes CSS issues such as removing padding with negative margins
and then re-adding padding back later. It also ensures the width of the
picker is exactly six columns wide and does not shift around when zoom
is enabled in the browser.
We now allow spaces and other special characters to be part
of the token (following "#", "@", or ":") that the typeahead
code will further evaluate as a typeahead candidate.
This is important for folks with short/common first names
on larger realms.
We have links when to create a stream to "Click all" or
"Unclick all" for checkboxes.
In FF it's easy to accidentally start dragging these links,
which has no real value (since their href is uninteresting)
and is confusing.
Perhaps these should just be buttons.
This adds a capped height of 70px to the description box (same as the
images) and then uses a gradient to fade out any text that may be near
the bottom.
This changes all references of the data-stream-name to more
predictable data-stream-id references in the subscriptions overlay.
This prevents unescaped characters from breaking selectors and stream
renames from breaking selectors.
This function throttles the function and only allows the on scroll
event to fire the popovers.hide_all() function once on scroll start
(determined as > 250ms after the last scroll event fire on .app.
This should resolve some performance issues surrounding constantly
firing queries and potentially changing the document tree.
Apparently, the updated version of this has a serious scrolling
performance problem in the left sidebar that basically makes scrolling
in that area unusable.
This reverts commit b683b2d3c3.
This change makes it so that when you are creating a stream
and use "Copy from Stream", the UI will immediately
check/uncheck the user checkboxes that correspond to the
stream's subscribers.
In concrete terms this allows Cordelia to create a new
stream call "Paris" that has all the "Verona" subscribers
except for Hamlet.
It also makes it so that when you go to create the stream,
the response is a little quicker, because we don't have to
iterate the streams.
Finally, it removes an odd quirk from the original design,
where if you clicked on Denmark but then collapsed the
streams, we wouldn't actually add the Denmark subscribers
to your new stream.
The current UI will still be slightly intuitive for people, as
I think checkmarks don't really make sense here. What we
really want are Add/Remove links (or buttons) next to each
of the existing streams.
I moved the UI element for "Copy from Stream" to be above
the list of users, including the filter box and check/uncheck
links, which no longer get applied to the list of streams.
The reason I no longer apply the filter to streams is...
* It's kind of confusing to have filters apply to both
streams and users. There should be separate filters for
them, and I will try to resuscitate that feature later.
* The code to filter the streams was doing a sketchy
regex operation against user-inputted data. (`match()`)
* We want to use the same stream filtering code as the
right sidebar uses.
* It improves performance for the common case that you
are filtering users.
The reason I no longer apply the check-all/uncheck-all actions
to streams is that it would be crazy to select all your streams
to copy users from, and it would be expensive/slow for large
realms, and it would likely be done by accident if somebody was
trying to manage individual users.
Finally, the check-all/uncheck-all actions have been scoped
to the users filtered by the text box, so I moved the links
under the text box to make that hopefully more clear to users.
If we blank out the user filter for users (by hitting backspace,
for example), then we now have short-circuit logic to display all
the user checkboxes. (The user-facing behavior doesn't change here,
but now we don't have to process all the strings.)
The function people.filter_by_search_terms() used
to return a JS object with emails as keys to represent
a set of users. Now we return a Zulip Dict() object
with user_ids as keys.
The old implementation was O(N squared) for N = number of
users due to its using an O(N) selector inside of a loop.
Now we simply iterate through all the checkboxes and turn them
on or off based on a bunch of O(1) operations.
One of my commits from yesterday erroneously set the
"mentioned" flag on messages that weren't mentioning
the current user, so you would get the pink/salmon
background when you sent at-mentions to other people.
Now we check the user_id before setting the flag.
Previously, if one starred very old messages (or ones in a stream
you're not subscribed to), your other open browsers would likely throw
an exception syncing the message flag.
It's probably a bug that this throws exceptions sometimes, but it's
not consistently reproducible (or maybe, browser dependent?), and it
isn't really a problem to fail to abort some requests as part of the
page reload process; the abort was just there to make sure as little
as possible is happening so we can garbage-collect effectively.
Most of the magic happens in message_live_update.update_avatar().
The prior code was buggy, as it was using person.id instead of
person.user_id, and it was not setting the image resolution.
This change is a partial bug fix for avatar live updates.
It makes it so that we prefer the person.avatar_url to
the message.avatar_url when rendering messages. Our live
update code was already populating person.avatar_url, but
we were ignoring it until now.
This commit does not affect messages that were already
rendered with the old url.
If we get a realm_user update for a user that is **not**
changing their full name, we no longer call
admin.update_user_full_name().
This was probably a fairly minor bug.
Earlier commits removed all uses of page_params.email outside
of people.js, and it turns out we have page_params.user_id, so
we don't even need page_params.email for seeding the data.
When we subscribe ourselves using the "Add" button in the
right pane of "Stream settings", we now call
stream_data.subscribe_myself(), which properly updates our
data structures (more than just sub.subscribed) and prevents
some console errors when you un-subscribe yourself using
the check mark.
The local echo code now marks up mention buttons with user ids
instead of email. Our code in message_list_view.js deals with
either the old style or the new style of markup now to determine
which mention buttons need to be highlighted.
As part of this commit we extract mention_button_refers_to_me().
After this change, if a user sends a message with at-mentions, the
local echo code will add the `mentioned` flag to 'message.flags`
as part of the callback to build the HTML, rather then doing it
hackily during a post-processing step.
The function echo.apply_markdown() actually applies markdown to
a message now, instead of simply computing markdown. Passing
in the outer `message` object will allow us to avoid some hacky
post-processing of messages after rendering, because we can
have our parser callbacks update message on the spot in a more
atomic fashion.
This commit doesn't change any behavior yet, but it starts us
down the road of deprecating page_params.email and allowing
people.js to control all access to the current user's email,
which will be important for email changes.
- Remove `jquery-mousewheel` from `static/third` and fetch it from npm.
- Upgrade `jquery-mousewheel` to 3.1.6.
- Bump up the `PROVISION_VERSION` to 4.5.
- Change some js code to comply with this `jquery-mousewheel` version.
Part of #1709.
- Remove `underscore.js` from `static/third` and fetch it from `npm`.
- Upgrade `underscore.js` to 1.8.3.
- Bump up the `PROVISION_VERSION` to 4.2.
Part of #1709
- Remove `codepointat` from `static/third` and fetch it from `npm`.
- Upgrade `codepointat` to 0.2.0.
- Bump up the `PROVISION_VERSION` to 4.1.
Part of #1709.
- Remove `winchan.js` from `static/third` and fetch it from `npm`.
- Upgrade `winchan` to 0.2.0.
- Bump up the `PROVISION_VERSION` to 4.0.
Part of #1709.
If a new user is auto-subscribed to a stream called "new
members", we will automatically narrow them to that stream
after the tutorial. Otherwise, we fall back to the code's
previous behavior, which is to direct them to the notifications
stream (often called "announce").
This is somewhat experimental. If we try this concept out on
the public Zulip realm and it works well, we will create a nice
realm setting for the "new members" stream.
In people.emails_strings_to_user_ids_string, we just warn
for bad emails going forward.
Users can enter bad emails into the search location bar,
for example, and that causes us to compute a browser hash,
which in turn uses this function.
(It's possible that we should adjust the search code not
to compute hashes for narrowing when the narrow doesn't
make sense, but that could be a non-trivial fix.)
This change makes it such that the stream filtering operation will only
run if the subscription overlay is visible, preventing any issues with
the lack of existence of elements or processing something that users
won’t be able to see.
Fixes#3388.
The new subs.close() function should unify all closing events of the
subscriptions overlay. The function also now tracks whether the
subscription overlay is in a closed or open state.
For the "GROUP PMs" part of the right sidebar, we now have
accurate hrefs when you hover over the groups or right-click
to copy links or open links in new tabs.
The slugs for PM-with narrows now have user ids in them, so they
are more resilient to email changes, and they have less escaping
characters and are generally prettier.
Examples:
narrow/pm-with/3-cordelia
narrow/pm-with/3,5-group
The part of the URL that is actionable is the comma-delimited
list of one or more userids.
When we decode the slugs, we only use the part before the dash; the
stuff after the dash is just for humans. If we don't see a number
before the dash, we fall back to the old decoding (which should only
matter during a transition period where folks may have old links).
For group PMS, we always say "group" after the dash. For single PMs,
we use the person's email userid, since it's usually fairly concise
and not noisy for a URL. We may tinker with this later.
Basically, the heart of this change is these two new methods:
people.emails_to_slug
people.slug_to_emails
And then we unify the encode codepath as follows:
narrow.pm_with_uri ->
hashchange.operators_to_hash ->
hashchange.encode_operand ->
people.emails_to_slug
The decode path didn't really require much modication in this commit,
other than to have hashchange.decode_operand call people.slug_to_emails
for the pm-with case.
Contributor visualization showing the avatar, user name and number
of commits for each contributors. The JSON data would be updated
upon deployment, triggered by the `update-prod-static` script.