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.