Lets administrators view a list of open(unconfirmed) invitations and
resend or revoke a chosen invitation.
There are a few changes that we can expect for the future:
* It is currently possible to invite an email that you have already
invited, it might make sense to change this behavior.
* Resend currently sends an invite reminder instead of resending the
original invite, this is because 'custom_body' was not stored when
the first invite was sent.
Tweaked in various minor ways, primarily in the backend, by tabbott,
mostly for style consistency with the rest of the codebase.
Fixes: #1180.
We were incorrectly reporting active bots as non-active in
popovers, and we had no test coverage for cross-realm bots.
We also rename the function to is_active_user_for_popover,
since the old name, realm_user_is_active_human_or_bot, suggested
the wrong semantics for cross-realm bots.
Last but not least, we only do a blueslip warning if a user id
is not found. When lookups fail, we are pretty confident that
the user is not active, so an error is overkill. We can change
that as part of issue #7120.
Fixes#7153
It's easier to unit test logic inside of people.js than compose.js.
We allow users to compose emails to any of our cross-realm bots.
Someday we may tighten up which cross-realm bots are valid targets,
since it's not necessarily the case that those bots do anything
useful when you send them messages.
The function name `get_realm_human_user_ids` was a lie--it
includes active bots as well.
The only user of this function is `activity.js`, which wasn't
impacted by the misleading name, because we eventually filter
out bots in the `info_for` function.
It's possible that we actually want to include bots in the right
sidebar, since they can be difficult to discover in other parts
of the UI. Or, if we want to keep the right sidebar as all
human users, we may eventually want to make the logic to exclude
bots happen higher in the stack (but for real, this time).
Apparently this is a bug that slipped in when we started showing
normal users as deactivated in the user popovers: all bot users were
treated that way as well.
We'll want to do #7153 as a follow-up to get things fully working how
we want them.
We were getting several exceptions in mark_subscribed if the streams
overlay wasn't open, basically because we'd try to filter the
right-side stream list when it wasn't present in the DOM.
This changes the behaviour of the typeahead in the compose box to
start appearing with single letter lying in the range of a-z or '+'.
This is a nice solution, because all emoji names start with lower-case
letters, while most emoticons like :P use a capital letter or similar.
Fixes: #6808.
We never make an actionable distinction between the "unknown"
presence status and the "offline" status, so we now
just use "offline" as the status for persons who don't
have recent presence records that the client knows about.
(Usually, users without presence rows have never been online,
or they have been deactivated, or they have been offline so long
that they don't show up in our date-limited queries.)
We sometimes get blueslip errors from browsers that are clearly still
attempting to reload long after they should have. These browsers can
produce a lot of unnecessary presence update exceptions.
To solve that, we start checking reload_in_progress in the presence
code path.
While we're at it, we also add some blueslip logging for the reload
code path, in case it becomes useful when debugging future issues.
Previously it was called before the event was processed by the server
and the subscription was updated to have the user subscribed to a
stream, so there was a race condition that would make it iso that
sometimes the stream line would disappear on the next render pass due
to the event not having completed yet.
This makes it so that the re-render happens after the event is
processed in `stream_events.js`.
Fixes: #6797.
Request for adding an reaction only if there is a default emoji or
an active realm emoji with that name while request for removing a
reaction should be sent only if there is a default emoji or a realm
emoji(may be active or deactivated) with that name. Earlier we were
not including deactivated realm emojis while deciding whether a
request for removing a reaction should be sent or not which was
causing requests for the removal of reactions with deactivated realm
emojis not to be sent to the backend.
Fixes: #6007.
The original "quality score" was invented purely for populating
our password-strength progress bar, and isn't expressed in terms
that are particularly meaningful. For configuration and the core
accept/reject logic, it's better to use units that are readily
understood. Switch to those.
I considered using "bits of entropy", defined loosely as the log
of this number, but both the zxcvbn paper and the linked CACM
article (which I recommend!) are written in terms of the number
of guesses. And reading (most of) those two papers made me
less happy about referring to "entropy" in our terminology.
I already knew that notion was a little fuzzy if looked at
too closely, and I gained a better appreciation of how it's
contributed to confusion in discussing password policies and
to adoption of perverse policies that favor "Password1!" over
"derived unusual ravioli raft". So, "guesses" it is.
And although the log is handy for some analysis purposes
(certainly for a graph like those in the zxcvbn paper), it adds
a layer of abstraction, and I think makes it harder to think
clearly about attacks, especially in the online setting. So
just use the actual number, and if someone wants to set a
gigantic value, they will have the pleasure of seeing just
how many digits are involved.
(Thanks to @YJDave for a prototype that the code changes in this
commit are based on.)
We now return user_ids for subscribers to streams in add-stream
events. This allows us to eliminate the UserLite class for
both bulk adds and bulk removes. It also simplifies some JS
code that already wanted to use user_ids, not emails.
Fixes#6898
This function was extracted from build_user_sidebar(). We
also slightly streamlined it to not unnecessarily call
filter() when the filter text was blank. This extraction
also eliminated the need for us to have the two-line
filter_and_sort() function.
Also, we get to 100% coverage in this commit.
We now intialize user-list-filter within activity.initialize(),
which gives us more control to set the module variable
`meta.$user_list_filter` before we build the user sidebar,
while setting up its handlers after we build the sidebar.
Emojis which are represented by a sequence of codepoints or emojis
with ZWJ are not included until we implement a mechanism for dealing
with their unicode versions.
Fixes: #6279.
We've iterated on this code incorrectly something like 3 times now, so
it's worth rewriting it with a lot of comments in a way that makes
sense.
The main actual functional change here is that modified key + enter
now is consistently the opposite of enter (in terms of whether to
provide a newline or send the message) in all cases.
Fixes#6489.
Now that we display the name and aliases of the currently focused
emoji at the bottom of the emoji picker, we don't need to display
the title text for emojis separately.
Fixes: #6111.
Emoji showcase refers to the space at the bottom of the emoji
picker we use for showing name as well as aliases of the currently
focused emoji.
Fixes: #6110.
This commit switches to use sprite sheets for rendering emojis
in all the remaining places, i.e., message bodies and composebox
typeahead. This commit also includes some changes to notifications.py
file so that the spans used for rendering emojis can be converted
to corresponding image tags so that we don't break the emoji rendering
in missed message emails since we can't use sprite sheets there.
As part of switching the bugdown system to use sprite sheets, we need
to switch the name_to_codepoint mappings to match the new sprite
sheets. This has the side effect of fixing a bunch of emoji like
numbers and flag emoji in the emoji pickers.
Fixes: #3895.
Fixes: #3972.
This adds the perfectScrollbar to the right side and theoretically
updates it any time a piece of code interacts with the sidebar and
updates the counts of users displayed in it.
We now use a template to render the "more topics" link.
We also remove an unnecessary conditional and an unnecessary
attribute.
Finally, our unit tests are a bit more granular now.
Despite a few warts, we are going forward with getting topic
history from the server when you click "more topics." This
commit simplifies the code by removing the feature flag
checks.
On a standard keyboard, 'q' is to the left of 'w', so it makes sense
for the hotkeys for the left and right sidebars to be `q` and `w`,
respectively, not the other way around.
This allows user to view all group private conversation messages
with a specific user. That is, it views all the the group private
messages from groups which include the given user.
Add search suggestion for group-pm-with. Add operator name
and description in "Search operators" tab.
Add change in tab name to "Group Messages" when using this operator.
Add frontend_tests for group-pm-with search operator.
Fixes: #3882.
This reverts commit c953759486.
The client side logic for dealing with server counts is actually
fine, as far as we know, but there are still some data-related
issues with cleaning up old unread counts.
The function is confusing and added unnecessary complexity, given that it is
only called in one place, and is not a function that should be exposed to
other modules.
If you typed in more than one word for a stream with multiple words in
it's name, it would not show up in the search list. This fixes that
and adds some more tests covering the entire functionality of the
filter.
If both users haven't posted in the current topic, then
as a second order sort, check which user has posted first
in the stream as a whole.
Fixes part of #5956; we still need to sort by sending in the
organization.
The server sends down lists of unread message ids in various
buckets, and we now use those on the client to provide more
complete counts of unread messages.
This restructures organization settings and permissions to be
more accurately grouped and for the permissions page to not be too
long.
CHANGES:
PROFILE:
(this was split out)
organization-profile-admin.handlebars:
form #1:
name
description
(SUBMIT)
avatar:
(UPLOAD)
(DELETE)
SETTINGS:
organization-settings-admin.handlebars:
language (mostly untouched)
message editing:
time limit/history/retention
message feed:
mandatory-topics
preview images
preview websites
PERMISSIONS:
organization-permissions-admin.handlebars
(mostly stuff was removed)
Joining:
restrict domains
require invite
User Identity:
name changes
email changes
Streams/Emoji:
creating streams:
waiting period (ADDED)
adding emojis
(SUBMIT) for whole panel
The profile group (name, description, avatar) were split into a new
page that did not previously exist, and the permissions was stripped
of message settings (message editing, message feed), but keeping the
"waiting period" input and putting it in the "Streams & custom emoji"
section.
Fixes: #5844.
We continue to have page_params.realm_default_streams, but
now we do lookups on whether a stream is a default stream
by using a Dict indexed by stream_id.
We are also careful to update that during live updates.
This fixes a flaw that we weren't updating the list of realms
correctly for events that remove a default stream.
This never made sense to be a flag on the UserMessage table, since
it's not per-user state. And in fact it doesn't need to be in a
database at all, since it's easily computed from content anyway.
Fixes#1099.
Apparently, local rendering of previews had broken sometime in the
last few months in a refactoring that resulted in us passing a string,
rather than an object, into markdown.js.
Previously, we didn't check the organization-level settings when
rendering a message list; instead, we only checked it when putting
messages into the message_store. That resulted in the state being
stale in the event that the setting controlling whether one can edit
messages was changed.
We remove some node tests, because revidving the node test for their
new home in message_list_view would be more work than we probably want
to do with an upcoming release. We basically need to be better about
exporting functions like populate_group_from_message_container and
set_topic_edit_properties, so we can do fine grained testing.
When we get around to the node tests, rather than exporting these
functions, it might make sense to create a new module with a name
like message_container.js, which would have all of these
last-second type of data manipulations on message objects. This
would be nice to split out of message_list_view.js. MLV is our
biggest module, and it's mostly cohesive, but it's real job
should be about assembling messages into a DOM list, which is
probably 80% of the code now. The 20% that I'd want to consider
splitting out is actually closer in spirit to message_store.js.
Thanks to Steve Howell for helping with the node tests.
In both cases, `args` is a local variable that goes out of scope
immediately after the assignment. Since the variable isn't captured by
a closure either, the assignment has no effect.
This fixes a confusing bug where administrators would be offered the
convenient topic-edit pencil even if message editing was actually
disabled.
This doesn't yet fix the real-time sync issues of changing the setting
without reloading.
Fixes#5946.
Normally the "n" key skips over muted streams, but if we
are currently narrowed inside a muted stream, it will now
go to the next topics within that stream.
For me the use case was that I have a stream I check up on
about once a day, and "n" would be super useful for me to
clear out unread counts while still skimming some content,
and without having to temporarily unmute the stream.
We now use similar code for A/D hotkeys as we do for the "n"
key.
The old code was using jQuery operations that got tripped up
by our splitters between active and inactive streams.
Fixes#4569
This allows us to traverse a list backwards, cycling to the
bottom as needed.
This code is going to be used for the "A" key that cycles
upward in the stream sidebar. It's probably overkill for
that use case, but it does give us O(1) behavior and avoids
the pitfall of accidentally mutating a list when reversing it.
This is the first part of a larger migration to convert Zulip's
reactions storage to something based on the codepoint, not the emoji
name that the user typed in, so that we don't need to worry about
changes in the names we're using breaking the emoji storage.
Here are the functions in top_left_corner:
get_global_filter_li: pure code move
update_count_in_dom: simplifed copy of similar function in stream_list.js
update_dom_with_unread_counts: pure code move, split out from function
of same name in stream_list.js
delselect_top_left_corner_items: pure code move
handle_narrow_activated: pure code move + rename
handle_narrow_deactivated: pure code move, split out from from function
of smae name in stream_list.js
Until we have an easy way to consistently determine whether a
stream has more topics than have been loaded already, we err
on the side of showing a "more topics" link. This in some ways
leads to a more consistent experience where you can zoom in on
any stream, even one that's really new.
This fix simplifies how we re-render topic lists when we
re-narrow or zoom out from a topic list.
* The topic_list.zoom_out() no longer gets called as
part of re-narrowing, and we eliminate the clear_topics
option.
* For all situations where we narrow to a filter that does
not have a topic, we simply call the new function
clear_topics().
* The stream_list code no longer calls remove_expanded_topics()
in cases where the new narrow has a topic. This allows us
to optimize away scroll/flicker churn a little more easily.
As part of this, we rename maybe_activate_stream_item() to
update_stream_sidebar_for_narrow(), since the function clears
stuff as well as turning stuff on.
We have code that can automatically scroll an element into "view"
in its container. We use this for stream sidebar rows inside the
stream list.
Generally the stream sidebar rows are small enough to fit into
the container, and the prior algorithm worked correctly for that
scenario.
If you have lots of topics, however, and a short screen, the
algorithm was being too aggressive. For example, if the top
wasn't showing, it would scroll the top into view, but at the
cost of scrolling the bottom out of view.
This fix makes the general scrolling algorithm more tame.
Part of the user-facing problem is that the element we pass
into the scrolling code for the stream sidebar rows is bigger
than the part of the row that actually should be shown on
screen. Nevertheless, it makes sense here to make the general
algorithm more robust.
If you read a message, then got a topic edit for it, we were
adding the message to our data structure of unread stream/topic
messages.
Now we guard against this in unread.update_unread_topics. I
no longer expose an update() method in unread_topic_counter,
since we really want to do the unread check at a higher level
to keep other data structures consistent.
We no longer use real jQuery to test topic_list. This changes
the nature of the tests to be higher level checks on how the DOM
is constructed. The actual details of how templates get
rendered should be in templates.js.
This code adds 'read' to message.flags and sets message.unread
to false.
It's not clear that the boolean message.unread is used in any
meaningful way, but we set it to false to avoid confusion. The
bankruptcy code was not doing this before.
Another quirk that existed before was that you could get two
'read' flags in a message when you declared bankruptcy. It's
also plausible that this could happen if you marked a message
as read via two different ways. It probably did not cause
user-facing bugs, but it would be confusing for troubleshooting.
Fixes#5032.
The new method borrows some code from the event loop
and unread_ops.mark_messages_as_read, and it is now
flexible about message_ids being marked as unread
even when there is no corresponding message in the
message store. For that scenario we still want to
update our data structures, which wasn't happening
before this change. (Generally, this was a non-issue
up until now, but it will become a bigger issue when
we start loading unread message ids from the server.)
This function allows us to see whether unread.js thinks a message
id is unread (as opposed to looking at the message itself). This
method is useful when we get notifications from the server that a
message has been read. In the future, we may not actually have
a local copy of an unread message, but we'll still know that it is
unread based on page_params. We'll want to update the data in that
case.
Going forward, we'll want to deprecate message.flags for most use
cases and just use the unread.js data structures to track unread
messages.
The prior implementation was needlessly complex. Both del() and
add() are cheap and idempotent.
With this change we no longer bother to delete a topic from a
dictionary when its last message is mark as read, since it doesn't
really help performance. We add a line to the tests to maintain
100% line coverage.
It's not always clear whether user_ids are strings or integers, so
we explicitly convert them to integers for sorting when creating
keys for PMs.
To keep the tests passing, this commit removes some unneeded
defensive code in message_store.js that only applies to contrived
test input.
This commit extract send_messages.js to clean up code related
to the following things:
* sending data to /json/report_send_time
* restarting the event loop if events don't arrive on time
The code related to /json/report changes the following ways:
* We track the state almost completely in the new
send_messages.js module, with other modules just
making one-line calls.
* We no longer send "displayed" times to the servers, since
we were kind of lying about them anyway.
* We now explicitly track the state of each single sent
message in its own object.
* We now look up data related to the messages by local_id,
instead of message_id. The problem with message_id was
that is was mutable. Now we use local_id, and we extend
the local_id concept to messages that don't get rendered
client side. We no longer need to react to the
'message_id_changed' event to change our hash key.
* The code used to live in many places:
* various big chunks were scattered among compose.js,
and those were all moved or reduced to one-line
calls into the new module
* echo.js continues to make basically one-line calls,
but it no longer calls compose.report_as_received(),
nor does it set the "start" time.
* message_util.js used to report received events, but
only when they finally got drawn in the home view;
this code is gone now
The code related to restarting the event loop if events don't arrive
changes as follows:
* The timer now gets set up from within
send_messages.message_state.report_server_ack,
where we can easily inspect the current state of the
possibly-still-in-flight message.
* The code to confirm that an event was received happens now
in server_events.js, rather than later, so that we don't
falsely blame the event loop for a downstream bug. (Plus
it's easier to just do it one place.)
This change removes a fair amount of code from our node tests. Some
of the removal is good stuff related to us completing killing off
unnecessary code. Other removals are more expediency-driven, and
we should make another sweep at ramping up our coverage on compose.js,
with possibly a little more mocking of the new `send_messages` code
layer, since it's now abstracted better.
There is also some minor cleanup to echo.resend_message() in this
commit.
See #5968 for a detailed breakdown of the changes.
Prior to this we were also performing highlighting inside HTML tags
which was wrong and causing weird behavior. Like, for example, if
someone added `emoji` as an alert word then any message containing
both emoji and alert word was rendered with a jumbo emoji.
Fixes: #4357.
A realm filter should match only after the start of a line, whitespace
or opening delimiters. But markdown was not configured to respect those
rules which was causing some weird rendering behavior. This commit fixes
the regex used for matching realm filters. On the backend we are using
regex with negative lookbehind to perform matches but since javascript
regex don't support lookbehind we are using a workaround on the frontend
using `contains_backend_only_syntax()` function which detects if a realm
filter can be rendered correctly by backend only and if so it stops the
message from getting echoed locally.
Fixes: #5154.
While we do have some known cases where syntax diverges intentionally,
this change should make it a lot easier to maintain
markdown.contains_backend_only_syntax over time.
It appears that a regression introduced in
3f60074c33 caused undefined to be passed
as the subject to the recent_senders library much more often; this
fixing that, and makes the library handle such cases reasonably
without an exception regardless.
This was causing a huge number of "Tried to call a Dict method with an
undefined key." exceptions.
This mostly moves code, and it also removes some unnecessary
coupling to stream_data.js. The topic_data code purely
works in the stream_id space, so there's no need to set up
actual stream data for it.
We now call topic_data.add_message() and
topic_data.remove_message() when we get info about
incoming messages. The old way of passing in a boolean
made the calling code hard to read and added unncessary
conditional logic to the codepath.
We also have vague plans to change how we handle
removing topics, since increment/decrement logic is now
kind of fragile, so making the "remove" path more explicit
prepares us to something smarter in the future, like just
figure out when the last topic has been removed by calling
a filter function or something outside of topic_data.js.
Another thing to note here is that the code changed here
in echo.js is dead code, since we've disabled
message editing for locally edited messages. I considered
removing this code in a preparatory commit, but there's
other PR activity related to local echo that I don't want
to conflict with.
One nice aspect of removing process_message() is that
the new topic_data.js module does not refer to the legacy
field "subject" any more, nor do its node tests.
This commit introduces a per-stream topic_history class
inside of topic_data.js to better encapsulate how we store topic
history.
To the callers, nothing changes here. (Some of our non-black-box
node tests change their way of setting up data, though, since the
internal data structures are different.)
The new class has the following improvements:
* We use message_id instead of timestamp as our sorting key.
(We could have done this in a prep commit, but it wouldn't
have made the diff much cleaner here.)
* We use a dictionary instead of a sorted list to store the
data, so that writes are O(1) instead of O(NlogN). Reads
now do sorts, so they're O(NlogN) instead of O(N), but reads
are fairly infrequent. (The main goal here isn't actually
performance, but instead it just simplifies the
implementation.)
* We isolate `topic_history` from the format of the messages.
This prepares us for upcoming changes where updates to the
data structure may come from topic history queries as well
as messages.
* We split out the message-add path from the message-remove
path. This prepares us to eventually get rid of the "count"
mechanism that is kind of fragile and which has to be
bypassed for historical topics.
This new module tracks the recent topic names for any given
stream.
The code was pulled over almost verbatim from stream_data.js,
with minor renames to the function names.
We introduced a minor one-line function called stream_has_topics.
We now have all of our callers into recent_topics code just
receive a list of topic names from get_recent_topic_names().
This is more encapsulated than handing off tiny little
structures to the three callers, two of whom immediately
mapped the objects to names, and one of whom needlessly
used the now defunct name canon_subject field.
The consolidation here removes some "subject" references, and
now all lookup are by stream id, not stream name.
The diff here is a bit daunting, but it's mostly simplification
of tests and calling code. Two of the callers now need to look
up stream ids, but they are otherwise streamlined.
The main change here is to stream_data.js, and we replace the
`canon_subject` and `subject` fields with `name`.
We use multiple casings of "lunch" as a topic in our tests, so
that we verify that unread counts respect that topics are
not case sensitive.
We also eliminate an obsolete stub.
Modified timerender.js absolute_time() to include the year
in the returned string when the supplied timestamp is in
an older year. This included adding an optional second
argument to specify the current date to facilitate unit
tests.
Fixes#5737.
This commit specifically addresses the issue when in preview mode,
while "enter sends" is enabled. Previously the messages were just
sent, now they must pass validation.
Fixes#5574.
This allows us to reliably parse the error in code, rather than
attempt to parse the error text. Because the error text gets
translated into the user's language, this error-handling path
wasn't functioning at all for users using Zulip in any of the
seven non-English languages for which we had a translation for
this string.
Together with 709c3b50f which fixed a similar issue in a
different error-handling path, this fixes#5598.
This function no longer sets properties to false, so the supported
way of doing this is to instead use prop(foo, false). Some tests
had to be fixed to accommodate this.
In case the user was not allowed to upload an emoji, we were displaying
two different but sematically same tips. This commit merges them and
also updates `update_custom_emoji_ui()` function in settings_emoji.js
to live update tooltip.
Our logic for editing failed messages is broken in various ways,
so we are removing the codepath for editing for now. We will
try to restore these features as part of #5841.
Because of local echo, message ids can change in message rows.
Having reactions use markup to indicate their message id just
creates more moving parts, since we would need to handle
message_id_changed events.
Now our handlers just call row.get_message_id() as needed.
We no longer do the message_store piece of reifying ids
via a trigger. We now make an explicit call to an
ordinary function.
This has several benefits:
- no more initialize() function
- no more scary comments about garbage collection
- the function has a real name now
- the function is less indented
- we can easily see when the message_store step happens
- simpler node tests
- simpler tracebacks (no jQuery cruft)
This commit removes all code related to headers because
(1) we don't need the code and (2) it splits #**stream**
as a paragraph, which we don't want. This commit also
fixes the inconsistency when #**stream** is on a new line.
Fixes#4678.
We eliminate `.get(0)` calls in buld_stream_list.
The easy case is that we stop building jQuery objects
for the splitters only to pull out the DOM immediately.
The more subtle case is that we also don't do `.get(0)` calls
to get DOM out of our individual list items. By passing
in full jQuery objects to `append()`, we should prevent ourself
from orphaning the old objects, which may in the future have
things like tooltip logic attached to them.
The user mention regex was checking for multiple lines,
so it broke when the user mention was on a new line.
This changes the regex AND adds a couple tests to
test inline markdown regexes.
Specifically, this checks to make sure that if you
surround an operand with quotes, having spaces inside
is permitted. Also, an extra space after the operator is
also permitted.
I deleted a test case that involved a highlighted stream, but
the query was empty. This produces kind of a weird result with
typeahead_helper.highlight_with_escaping, but this function already
has coverage in node_tests/typeahead_helper.js, so the check here
was essentially redundant anyway. Specifically, the highlighter
wraps every character individually with <strong>, and looks really
messy in html.
I pushed a bunch of commits that attempted to introduce
the concept of `client_message_id` into our server, as
part of cleaning up our codepaths related to messages you
sent (both for the locally echoed case and for the host
case).
When we deployed this, we had some strange failures involving
double-echoed messages and issues advancing the pointer that appeared
related to #5779. We didn't get to the bottom of exactly why the PR
caused havoc, but I decided there was a cleaner approach, anyway.
This change has us tracking messages as soon as we start
sending the message to the server. The next step is to
reconfigure the timeouts a bit to deal with the server not
responding.
We now use a client-side message id to track the state of our
sent messages. This sets up future commits to start tracking
state earlier in the message's life cycle.
It also avoids ugly reify logic where we capture an event to
update our data structure to key on the server's message id
instead of the local id. That eliminates the node test as well.
Another node test gets deleted here, just because it's not
worth the trouble with upcoming refactorings.
This mostly sets the stage for a subsequent commit to start
using client_message_id as the key into sent_messages.
It has the nice side effect of making it more explicit that
certain things should always happen when transmit_message()
succeeds.
This commit does regress our node test coverage a bit.
This commit starts to decouple client_message_id from local_id.
We don't really take advantage of the decoupling in this
commit--in fact, it's a bit of a pain at first. But this should
be a fully working checkpoint commit.
This is mostly straightforward moving of code out of compose.js.
The code that was moved currently supports sending time
reports for sent messages, but we intend to grow out the new
module to track more state about sent messages.
The following function names in this commit are new, but their
code was basically pulled over verbatim:
process_success (was process_send_time)
set_timer_for_restarting_event_loop
clear
initialize
All the code in the new module is covered by previous tests that
had been written for compose.js. This commit only modifies
a few things to keep those tests.
The new module has 100% node coverage, so we updated `enforce_fully_covered`.
We are deprecating local_id/local_message_id on the Python server.
Instead of the server knowing about the client's implementation of
local id, with the message id = 9999.01 scheme, we just send the
server an opaque id to send back to us.
This commit changes the name from local_id -> client_message_id,
but it doesn't change the actual values passed yet.
The goal for client_key in future commits will be to:
* Have it for all messages, not just locally rendered messages
* Not have it overlap with server-side message ids.
The history behind local_id having numbers like 9999.01 is that
they are actually interim message ids and the numerical value is
used for rendering the message list when we do client-side rendering.
In typeahead_helper.js, added a compare function to first sort by
subscription, then by pm partners and lastly based on recency in the
current topic. Altered function sort_for_at_mention to take topic data
and sort using the above function. Also altered node tests for
typeahead_helper.js to test for the above added functionality.
Fixes: #4249
There is no reason to render the template for compose mention
warnings if the user is already in the widget.
This commit also restructures the unit test significantly to more
carefully exercise each case, particularly in regard to when
templates get rendered.
This commit add $.create(), which allows you to create a
jQuery object that just has a name to identify it, as opposed
to some selector or HTML fragment. It's useful for things that
are really used as stubs.
This also fixes a bunch of the existing tests to use $.create().
Before this fix, you could actually just do $('some-stub'), but
now we enforce that the input to $() looks like a valid selector
or HTML fragment, and we make some exceptions for things like
window-stub and document-stub.
Hopefully this will make it more explicit that zjquery does
not truly simulate DOM, but it instead allows you to dynamically
set what you want the results of $('foo').find(some_selector)
to be.
Before this commit, we were erroneously setting up parents
as part of add_child() calls, but it's not necessarily the
case that those children are immediate children, and therefore
the first object is not necessarily the immediate parent.
Our current workflow for creating a new stream allows the user to
invite as many other users as they like but since there can be
mistakes in doing so, we now open a modal with a warning if the
number of invites are more than 100 just to confirm that user indeed
wanted to do this.
Fixes: #1663.
This system hasn't been in active use for several years, and had some
problems with it's design. So it makes sense to just remove it to declutter
the codebase.
Fixes#5655.
Fixes#5612. What this specifically does is that if you are
typing a group PM, this logic iterates through the possible
search suggestions for the next autocomplete. If that suggestion
contains a group PM that already exists, then prioritize it with
the most recent one on top.
This test verifies the following line of code:
$(document).trigger($.Event('subscription_remove_done.zulip', {sub: sub}));
Before this change, the mocking mechanism used `$(document).on(...)`
to set the function that gets called on trigger, but it didn't clear
any of the other handlers.
Since all we care about is making sure that the event gets triggered,
we now just override `$(document).trigger`.
This function was removed in favor of loading everything in
ui_init.js. The asynchronous nature of jQuery 3 document-ready
events may cause an undesirable order in which these are executed.
Unicode emojis when rendered should display canonical short name.
Similarly, the alt text should be of the format `:<short_name>:`.
For both of these we currently display the actual unicode symbol.
As some systems don't have the fonts necessary for displaying them
properly, they are rendered as empty square blocks. This commit also
ensures that the markup generated for emoji generated by canonical
name and by an unicode emoji is same.
Fixes: #5555.
The dispatch.js tests now no longer go through server_events.js,
so the tests are isolated from some of the setup you have to
do for the main event loop. They now directly call into
server_events_dispatch.js.
Instead of having a custom (duplicate) matching function in
search suggestion, it was refactored to use the function in
people.js. This also gets the diacritic-ignoring feature
of the function in people.js.
Fixes#5315.
Having get_full_time produce a date string non-compliant with RFC2822 or
ISO 8601 caused problems when showing edition timestamps on a message's
edit history.
Now it returns an ISO 8601 date string (1978-10-31T13:37:42Z).
Flaskbotrc is a file containing config of all active
outgoing webhook bots. It is used to provide configuration
of all active outgoing webhook bots to zulip-bot-server.
The node tests have purged modules from cache that were
included via things like set_global(), but calling require
directly would leak modules into the next test, which made
a couple tests only work when you ran the whole suite. I
fixed those tests to work standalone. And then I now make
dependencies explicitly clear the require cache before we
require them in namespace.js.
For bots and users who have not logged in for a long time the presence information is not known. For the these users make the presence indicator hidden.
Added a dropdown in the organization settings page with a search-box and
required styles. Also added an element to disable it. Added a method to
populate the dropdown using list_rendering.js. Also altered response to
the event of deletion of the notifications stream on the frontend. On
selection of a new stream or on clicking 'Disable', a patch request is
made with stream-id to /json/realm.
Fixes: #3708.
This involves updating filter.js, mostly. The
tests were updated appropriately for this change,
which also involved changing a caspar test for
narrowing.
This was never a feature in the old search_suggestions
version, so a new helper function for it was added.
Relevant tests were also added, maintaining 100% coverage.
The get_person_suggestions and get_group_suggestions functions
were updated to the new system. Support for negation is also
added in the new system.
Relevant tests were also updated. Also, note that the function
get_private_suggestions was removed, as it was rendered
obsolete by these updates.
Special filter was updated to work even when it is not the first
token in a search query. Furthermore, the default query was
moved around to work with the changes to come for the new
suggestion system.
A test also had to be modified to work with the new system.
Add `remove_alert_word()` function which uses the correct data flow
while removing an alert word.
`alert_words_ui.js` was structured differently from most of the other
settings. It was not using the triggers from the server for running
the success/failure handlers.
Rationale: For the more off-to-the-side edit history view, changes
are easier to digest by highlighting deleted content in red followed
immediately by added and changed content in green.
TODO: Toggle for showing the edited messages without highlighting;
deleted content would not be shown in this view.
The floating_recipient_bar is cloned from recipient_bar elements.
The cloning created elements in the DOM with duplicate id
attributes, specifically <span id="timerender{id}">, which
contains the date of the message stream. The timerender span
will now use class="timerender{id}" instead.
Fixes#4997.
Fixes#5128.
Previously, if we had both a date and a subscribe bookend, they would
appear in one order after new messages were sent (bookend_bottom of
the top group), and another after a reload (bookend_top of the bottom
group). This makes the experience consistently a bookend_top.
Added new file to test stream sort. Specifically,
it tests the `sort_group` function's ability to put
streams into the corect pinned/normal/dormant category,
filter them based on keyword, and sort alphabetically.
We use zjquery now for testing stream_list.js, which runs faster
than the real jQuery and allows some test isolation. The nature
of the test is basically the same, but we don't actually render
templates. Instead of making assertions about the DOM, we are
now making assertions about how the stream lists get constructed
from other elements.
In pm_conversations.js, added function to make a user a PM partner and
another function to check if a user is a PM partner. A PM partner is
someone with whom the user has been in a PM with.
In recent_senders module, added a data structure to hold timestamps of
users' latest message in a topic. Also added a function to compare 2
users based on above timestamp. Added a function to process messages for
the data structure and a call in add_message_metadata. Also added node
tests for insertion of data into recent_senders.senders.
This covers all blueslip errors and warnings
in people.js. These do not need to be tested
to rigorously and just need to be covered to
get people.js to 100% coverage.
We now stub templates.render() to see what data gets passed in
to the template, rather than using jQuery to inspect the DOM that
gets created. This changes the nature of the test to be less about
integration with the templating layer and more about how we pass
data into the template.
To compensate, we add more assertions to the relevant test
in templates.js.
This moves all the code dealing with emoji_picker
navigation and click/enter events to emoji_picker.js.
Some of the code still delegates back to reactions.js
in some way.
The navigate() code really does nothing reaction-specific,
nor does filter_emojis(), nor do some of their helpers.
This was mostly moving code, but I also did some
s/reaction// or s/reaction/emoji/ in names.
This change sets us up to de-duplicate some code. It
changes behavior for the edge case situation where
you had the reaction menu open but then decide to
click on one of the existing reactions. This change
closes the emoji popover, which is probably the
correct behavior.
timerender.js render_now() will always include older
years when rendering the date stamp on the recipient bar
and the date rows above messages.
Fixes#4843.
This reverts commit c7f710b8d4.
Because the back end still stores muted topics fundamentally using
stream name as a key, trying to cut over the client to use stream
id was just making things more brittle. Mutes would work after
renaming the stream, which was progress in the change that we
revert here, but only until page load. The other problem, which
is more severe, is that the order of page loading functions would
cause no mutes to happen at page load time. This could be fixed
to some degree, but we should do a deeper fix on the back end.
This commit changes the key for recent_topics to be a
stream id. For streams that have been renamed, we will now
get accurate data on recent topics and active streams as
long as stream_data.get_stream_id(stream_name) returns a
valid value.
This commit changes stream_data.in_home_view() to
take a stream_id parameter, which will make it more
robust to stream name changes.
This fixes a bug. Now when an admin renames a stream
you are looking at, it will correctly show itself to
be un-muted. (Even with this fix, though, the stream
appears to be inactive.)
Some callers still do lookups by name, and they will
call name_in_home_view() for now, which we can
hopefully deprecate over time.
Rather than having get_stream_li() look up stream id using
stream name, we force the callers to pass in the stream id.
This adds an extra line to most of the callers for now, but
this will eventually change as we fix some of the callers to
have their callers pass in stream_id.
In places where we now call stream_data.get_stream_id() to
get the stream id, we will be more resilient toward stream
renamings, at least until the next reload, since
stream_data.get_stream_id() can resolve old names that
are stored when we process stream-rename events.
We now use stream ids to filter messages in narrowing
situations, instead of doing stream name comparisons.
This partially fixes certain stream-renaming scenarios, since
we will be able to match the stream id for an out-of-date
stream operand, but it doesn't fix some other stuff, such
as the query that the server gets.
This is not a user-facing change, but it starts us down the
path to having the JS client be able to look up old stream
names for situations like people clicking old external links
or for live-update scenarios.
This adds the current_user_has_reacted_to_emoji() helper.
This new helper is easier to use and slightly more efficient
than calling get_user_list_for_message_reaction() and then
indexOf().
This also replaces one call to get_user_list_for_message_reaction()
with a list of user_ids that we already had locally.
The node tests were improved a bit here, including a minor
whitespace fixup.
We used to render the subscriptions_settings template for every
stream when you loaded "Manage Streams," which can be very slow
for a big realm. Now we only render the right pane on demand.
The function modals.is_active() can see if modals are open
without having to look at the DOM. This should make it snappier
to type in the compose box. Even if the speedup is pretty minor,
not having to worry about jQuery slowness should make it easier
to diagnose future compose box issues.
The new function gets used in other places, too, where performance
isn't so much an issue.
This focuses the body content of the informational overlay after
going to it from "?" so that you can use up and down arrows to then
scroll the content easily.
Fixes: #4480.
This removes the old compose emoji picker in its entirety, changing
the few callbacks needed to launch the reactions-style emoji picker
instead and hook it up properly.
Callbacks for reactions and composing messages are distinguished by
selecting for, respectively, the .reaction and .composition classes.
Fixes#4122.
We used to have code scattered in multiple places to
calculate things like admin options, preview urls,
subscriber counts, and rendered descriptions for
streams before we rendered templates in the "Manage
Stream" code.
These are all consolidated into a new function
called stream_data.update_calculated_fields().
This is mostly code cleanup, but it also fixes a bug where
the "View Stream" button would not work for a newly created
stream.
Modified composebox_typeahead.js to recognize the triple backtick
and tilde for code blocks, and added appropriate typeahead functions
in that file and in typeahead_helper.js.
Additionally, a new file pygments_data.js contains a dictionary of
the supported languages, mapping to relative popularity
rankings. These rankings determine the order of sort of the
languages in the typeahead.
This JavaScript file is actually in static/generated/pygments_data.js, as it
is generated by a Python script, tools/build_pymgents_data.py. This is
so that if Pygments adds support for new languages, the JavaScript file
will be updated appropriately. This python script uses a set of popularity
rankings defined in lang.json.
Corresponding unit tests were also added.
Fixes#4111.
When you subscribe to a stream, we now set a newly_subscribed
flag on the object, and we return true during the is_active()
call.
This solves the problem that immediately after you subscribe, you
don't have any messages in the stream, so it would appear active
by our old criteria.
This is still something of a workaround, as once you reload, the
stream will become inactive again, unless other messages come in.
A more permanent solution here would be to have the backend
indicate newly subscribed streams to us (apart from the initial
event), but we may not really need that in practice.
It turns out the check to make sure that "social" filtered to
the bottom could give a false positive, since it was already
alphabetically at the end of the list.
So, I call the stream "cars" now instead, so that it only comes
after "Denmark" if the is_active flag gets respected.
I also check for the divider tags now.
The new logic has 4 tiers of priority:
* Whether a match is found in the name, start of description, middle
of description, etc.
* Importance to the user / activity -- more specifically, the order
used in the left sidebar. This means pinned streams first, active
streams, then inactive streams.
* Subscriber count: How big is the stream? Bigger is better.
* Alphabetical ordering is a final tiebreak.
Fixes#4508.
Despite the length of this commit, it is a very straightforward
moving of code from narrow.js -> narrow_state.js, and then
everything else is just s/narrow.foo()/narrow_state.foo()/
(with a few tiny cleanups to remove some code duplication
in certain callers).
The only new functions are simple setter/getters that
encapsulate the current_filter variable:
narrow_state.reset_current_filter()
narrow_state.set_current_filter()
narrow_state.get_current_filter()
We removed narrow.predicate() as part of this, since it was dead
code.
Also, we removed the shim for narrow_state.set_compose_defaults(),
and since that was the last shim, we removed shim.js from the app.
We now only call compose_state.composing() in a boolean context,
where we simply care whether or not the compose box is open. The
function now also returns true/false.
Callers who need to know the actual message type (e.g. "stream" or
"private") now call compose_state.get_message_type().
We now use "map" to have our inner generator of topics be
mapped to objects with both the stream and topic. Thanks to
Mahim Goyal for helping with this design.
Before this change, we would move "dormant" streams to the bottom
of your stream sidebar, but only if you had 40+ streams.
Now we do this in all cases to be more consistent.
This commit also changes the redraw strategy when we remove rows.
Before this change, we were doing incremental updates, but now we
call build_stream_list to do a complete rebuild. This was partly
motivated by adding the new divider, which would have complicated
the incrememental approach when you removed the last remaining
dormant stream.
This is mostly just moving methods out of compose.js.
The variable `is_composing_message`, which isn't a boolean, has
been renamed to `message_type`, and there are new functions
set_message_type() and get_message_type() that wrap it.
This commit removes some shims related to the global variable
`compose_state`; now, `compose_state` is a typical global
variable with a 1:1 relationship with the module by the same
name.
The new module has 100% line coverage, most of it coming
via the tests on compose_actions.js. (The methods here are
super simple, so it's a good thing that the tests are somewhat
integrated with a higher layer.)
* reset the emoji popover in case of an event
regarding update of realm_emoji.
* test-node-with-js: Add dependency - popovers module;
In dispath.js to support popovers object.
This changes the layout of "organization settings" for
non-administrators such that they can view "Filter settings".
("Actions" column and form to add a new filter are not available).
Fixes: #3636
This changes the layout of "organization settings" for
non-administrators such that they can view "Default streams" ("Actions"
and the form to add new default stream is not visible).
This moves respond_to_mention() and reply_with_mention() to
compose_actions.js. These methods are basically thin layers
on top of compose_actions.start().
This module extracts these two functions that get called by
several other modules:
start()
cancel()
It is a little bit arbitrary which functions got pulled over
with them, but it's generally functions that would have only
been called via start/cancel.
There are two goals for splitting out this code. The first
goal is simply to make `compose.js` have fewer responsibilities.
The second goal is to help break up circular dependencies.
The extraction of this module does more to clarify
dependencies than actually break them. The methods start()
and cancel() had actually been shimmed in an earlier commit,
and now they no longer have a shim.
Besides start/cancel, most of the functions here are only
exported to facilitate test stubbing. An exception is
decorate_stream_bar(), which is currently called from
ui_init.js. We probably should move the "blur" handler out
of there, but cleaning up ui_init.js is a project for another
day.
It may seem slightly odd that this commit doesn't pull over
finish() into this module, but finish() would bring in the
whole send-message codepath. You can think of it like this:
* compose_actions basically just populates the compose box
* compose.finish() makes the compose box do its real job,
which is to send a message
Before this fix, if you scrolled back in your PM history for a
person that you've had recent conversations with, then we would
backdate the record of their most recent conversation, and this
would make the sort ordering under the "Private messages"
section incorrect.
This commit fixes this error by re-writing the function
message_store.insert_recent_private_message() to check any
prior timestamps for that user. It also optimizes the function
a bit to short-circuit in O(1) time for cases where a recipient
already has a more recent timestamp, by having a Dict keyed
on user_ids_string.
We had never-enabled code to allow users to set default
streams for their bots (for event registration, default sending, etc.).
This commit removes the code.
We've had this kind of hacky setting called message_view_only for
a long time in the hotkeys code, and it originally helped optimize
the code a bit. It wasn't well maintained, and people started
adding non-message-view behavior to the arrow keys without flipping
that flag to false. This change finally flips the flag to false,
which simplifies some of our logic.
We now explicitly return true from process_hotkey() when we
handle up/down/backspace for the drafts modal. Also, we no longer
call preventDefault() from drafts.draft_handle_events(), since the
caller does that, and we no longer return `true`, since we were
never inspecting the return value anyway.
The up/down arrows now navigate the left pane of the settings menu.
The code here was originally implemented as part of our settings
redesign, but the code was added in a place that became unreachable
after we fixed a bug with home_tab_obscured(). This commit
resurrects the code and places the guts of it in settings.js. It
is possible that we want to clean this code up eventually to deal
better with hidden blocks.
The code here used to live in hotkey.js. Its complicated calling
protocol made it difficult to unit test. We are also trying to
slim down hotkey.js.
Our arrow navigation for things like `#stream_filters` has always
been kind of awkward, since it's difficult to get the focus to
their list items. This commit does nothing to fix that yet.
For small-ish realms (<= 250 users), we ensure that the presence
info includes all realm users the front end knows about, even in
cases where the server sends down a slimmed version of presence
data. We make the users "offline" by default, of course.
This commit sets us up to optimize larger realms without concerns
of breaking small realms. Small realms may want to continue to
show all users, even users who may have been offline several weeks,
since it doesn't clutter their API as much as it would for big
realms.
Most of this code was simply moved from activity.js with some
minor renaming of functions like set_presence_info -> set_info.
Some functions were slightly nontrivial extractions:
is_not_offline:
came from activity.huddle_fraction_present
get_status/get_mobile:
simple getters
set_user_status:
partial extraction from activity.set_user_status
last_active_date:
pulled out of admin.js code
We also fixed activity.filter_and_sort to take user_ids.
* Change the classes and ids of different widgets and modals
and make suitable changes in `admin.js`.
* Remove any other occurrences of `alias` or `realm_alias`
from admin.js.
We remove the jquery dependency here and just search for strings
in the text. It turns out the test was leaking jquery into
message_edit, so now we explicitly stub jquery in message_edit.
Our unread.js code basically silently treats empty recipient
strings or unknown streams as having zero unread messages,
which is probably the correct behavior. We now have tests
that cover this. This commit also gets us to 100% line
coverage on the module (but not yet 100% branch coverage).
Previously drafts called compose.snapshot_message which would then
get the message object from compose.create_message_object. This method often
checked for the validity of stream/user recipients which would often cause tracebacks.
The new method in drafts.snapshot message just gets the data from the fields and
stores them in the draft model without any additional checking.
The addDraft and editDraft tests were copying objects by reference
which meant the methods weren't tested properly. Due to this, a bug with
stubTimestamp was also discovered where the method wasn't getting stubbed
* 'd' in message view opens drafts.
This also adds hotkeys within the drafts UI:
* Up/down arrow keys navigate the drafts.
* Pressing enter edits the selected draft.
* Pressing backspace deletes the selected draft.
Some variable names tweaked by tabbott.
If we get reactions for deactivated users, or otherwise missing
users, we only issue a blueslip warning now. The function
get_message_reactions() was indirectly causing blueslip errors
before this fix, but we can downgrade to warnings now that this
function has better unit tests around it.
We eventually want to track deactivated users on the client.
Fixes#4289
We now track our inbound timing events using code in
typing_data.js.
This code may be a little more robust with variations on how
recipients are represented in events, although there are no known
bugs here.
This change moves most of the logic related to starting and
stopping outbound typing indicators to a new module called
typing_status.js that is heavily unit tested.
While this was in some sense a rewrite, the logic was mostly
inspired by the existing code.
This change does fix one known bug, which is that when we
were changing recipients before (while typing was active), we
were not stopping and starting typing indicators. This was
a fairly minor bug, since usually users leave the compose
box to change recipients, and we would do stop/start under
that scenario. Now we also handle the case where the user
does not leave the compose box to change recipients.
If a url is present in stream description, it will be
rendered as a clickable link under /streams page.
Tweaked by tabbott to use the separate rendered_description element to
avoid duplicate rendering and to live-update.
Fixes#1435.
Instead of passing in a hash to template whose keys are a
mixture of records and strings, we now pass in an
array of records. This also removes a spurious if condition
in the template that was a result of the janky data structure.
This adds an image feed that you can scroll through with hotkeys
in the lightbox.
The left and right arrow keys along with the left and right arrows
will go to the prev/next image, and clicking on an image will also
take a user to that image.
Send typing notification events when user types in the compose box.
Listen for these events and display a notification.
Sending notifications: Notifications are throttled, so that start
notifications are sent every 10 seconds of active typing, and stop
notifications are sent 5 seconds after active typing stops or when the
compose box is closed.
Displaying notifications:
When a typing notification is received, if the current narrow is private
messages or is: pm-with and the user is not the sender,
"Othello is typing..." is displayed underneath the last message. This notification is
removed after 15 seconds. If another notification is received during this period, the
expiration is extended. When a stop notification is received the notification is removed.
Internally, a list of users currently typing is maintained for each
conversation (in a dict). When an event is received the list (for the appropriate
conversation) is updated and the notifications template is re-rendered
based on the narrow information. This template is also re-rendered when
the narrow changes.
Significantly modified by tabbott for clarity.
Fixes#150.
Stub the blueslip module to print a nicely formatted traceback.
Earlier the traceback used to be only a `ReferenceError` because
blueslip was not stubbed.
Fixes: #4021.
We simplify hotkey mappings by using different hashes for
keydown and keypress events. There are browser bugs (iOS, for
example) where keypress events have the wrong keyCode values.
This led us, under iOS, to interpret "!" as "page up."
This fix also helps us disinguish escape from shift-escape.
Brock Whittaker helped on figuring out the keypress/keydown
issues that are addressed in this commit.
Fixes#4019
The initial version of the tests cover most normal keys, but they
do not cover special keys like enter/tab/escape or arrow keys
or home/end/page-down/page-up yet.
The function with_overrides() uses the logic from the old
run() function in dispatch.js to allow you to call a test
function and override parts of the global namespace only
for the duration of when test_function runs.
We now pass in function names as 'foo.bar', which is a bit
easier to type/read/grep, rather than passing the module name
and function name individually.
This adds a button to #subsciption page called "View Stream"
that narrows the user to that particular stream.
This fix involves typical changes to JS/CSS to add new features,
and we also add a "preview_url" field to the sub object in
stream_data.js.
Fixes#3878
It's easier to reason about the activity.js code if we just
make it clear that presence_info is a global singleton. Going
forward, functions that use that data will explicitly refer to
exports.presence_info.
This change makes some tests slightly more awkward to set up, but
with the actual code you now don't have to question whether there
are multiple copies of presence_info to maintain.
The diff for compare_function is a bit confusing to read, but it's
basically just de-dented since we don't need to parameterize the
compare function any more.
This refactors the .message_controls to stop relying on absolute
positioning and strange CSS, and throws them inline.
This also restyles so they hang to the right of the time which is now
always present.
Fixes: #3761.
We pass in sub instead of stream_name, to support callers that
already do lookups by stream id.
And then we make the second optional argument be subscribers, since
that is all we were using from the old `attrs` argument.
- Remove `handlebars.runtime.js` from static/third and fetch it from npm
- Upgrade `handlebars` to 3.0.3.
I change the test since there is a patch about line, written in
handlebars'
v2.0.0-beta.1 release note:
"Lines containing only block statements and whitespace are now removed."
Fixes part of #1709.
If we get invalid events related to stream subscribers, we now
exit earlier to prevent ugly tracebacks. We may eventually
want to upgrade some of these warnings to errors, once we fix some
of our live-update bugs. In particular, we don't yet live-update
users when streams go from private to public, so if you add/remove
subscribers to a newly-public stream that a user still thinks is
private, they will not be able to handle the event through no
fault of the codepath that happens during the add/remove.
This currently only supports this in emoji reactions, not in actual
emoji in message bodies, but it's a great start for people who want a
text-only view.
Tweaked to update the text by tabbott.
Fixes#3169.
I noticed while reviewing #3807 that we still haven't fixed this;
because timestamps are primarily displayed in the message view, fixing
this is trivial.
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.
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.
* 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.
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.
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
(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.)
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.
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).
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.
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
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
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.
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.
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.
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).
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.
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.
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.
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.
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 `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
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.)
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.
The fix works by having build_stream_sidebar_row()
automatically update its own unread count when we
build a sidebar row. Currently we rebuild sidebar
rows when we pin/unpin rows.
As an aside, we currently don't really need to rebuild
the sidebar row when we pin, since we're only moving
the DOM, not altering it. But this may change in the
future, so I decided to leave that code path in place.
We may decide to do things in the future like showing
pinned streams with bolder fonts or special icons or
whatever.
Fixes#2902
Merged two tests since they both use the same test data. The file name
of `presence_list_performance.js` also causes confusion as it is no longer
use for performance testing.
Stream descriptions are now displayed along with the name. The
autocomplete results include streams with matches in the stream
descriptions. Added styling for description in compose.css.
Fixes#2398.
When somebody changes their name, we will now update
the buddy list right away. The old code was trying
to do this through a code path that was designed for
true presence updates, but it was also passing in an
empty array, instead of undefined, which caused it to
fail to invoke the intended part of the codepath to
redraw the buddy list.
Now we just call the new activity.redraw() function,
which does the right thing for the buddy list.
The group PM list was live-updating before this change,
and it continues to live-update as part of the new
activity.redraw() function.
This commit replaces the placeholder "clipboard" button with a reaction button.
This is done on any message that can't be edited. Also, on messages sent by
the user the actions popover (toggled by the down chevron icon) contains
an option to add a reaction.
When clicked, a popover with a search bar and a list of emojis is displayed.
If the right sidebar is collapsed (the viewport is small), the popover is placed
to the left of the button.
Focus is set to the search bar. Typing in the search bar filters emojis.
Emojis with which the user has reacted to this message are highlighted.
Clicking them sends an API request to remove that reaction.
Clicking on non-highlighted emojis sends an API request to add a reaction.
When the popover loses focus it is closed.
The frontend listens for reaction events. When an add-reaction event is
received, the emoji is displayed at the bottom of the message with a
count initialized to 1. If there was an existing reaction to the message with
the same emoji, the count is incremented.
Old messages fetched from the server contain reactions.
They are displayed (along with title and count) at the bottom
of each message.
When clicking the emoji reaction at the bottom of the message, if the
user has already reacted with that emoji to this message, the reaction
is removed and the count is decremented. Otherwise, a reaction is added
and the count is incremented.
Hovering over the emoji reaction at the bottom of the message displays
a list of users who have reacted with this emoji along with the
emoji name.
Hovering over the emoji reactions at the bottom of the message displays
a button to add a reaction.
Fixes#541.
An exception in the webapp was trown when an empty mention was sent.
Examples of problematic messages are "@" or "@****".
In order to fix this, the regex that identifies mentions has been
modified, so it now requires the mention to have a "content" (by
replacing the ? quantifier by +).
A test case has been added to `frontend_tests/node_tests/echo.js` to
check that this works properly in the future.
* Doesn't pop up the warning until you actually try to send the message
* Eliminates the red warning.
* Changes confirm text to "Yes, send".
* Adds a stream size threshhold of 15 people; smaller streams don't
prompt about this.
Fixes#2257.
This commit changes people.remove() to be people.deactivate(),
and it fixes a bug where deactivating users was causing tracebacks
in the PM list if somebody had PM'ed the deactivated user
recently.
We need this for node tests, so that you don't have to explicitly
remove every user between tests. (Also, people.remove() is about
to have different semantics.)
Updated `get_editable()` so that organization admins only see their
own bots in their personal settings page; this removes a lot of
unnecessary clutter.
Fixes#2657.
This change introduces an unread_topic_counter object
that manages unread counts for streams and topics. Consolidating
all the logic into a single class will set us up to add
logic for dealing with topic counts that includes provisional
counts of unread messages from the server. It also makes
the current code a little easier to reason about.
Most of this change was simply extracting functions, but
I also removed a few unnecessary and inconsistent calls to
`stream_data.canonicalized_name` that preceded our use of
Dict with a fold_case argument.
This is a major change to the /#subscriptions page, converting it to
by a side-by-side list of streams and their settings in an overlay.
There are no new features added/removed, but it's a huge changeset,
because it replaces the old navigation logic and moves the stream
creation modal to appear in the right side of this overlay.
Added new option to download .zuliprc file directly from settings
page. This should help reduce friction when setting up new
bots/integrations. This new feature is available in the bot cards and
the 'show your API key' section. One caveat is that the filename is
automatically set to 'zuliprc' instead of '.zuliprc', since as most
browsers do not allow filenames to start with a dot.
Fixes#2327.
* In most cases, eslint --fix with the right comma-dangle settings was
able to update the code correctly.
* The exceptions were cases where the parser incorrectly treated the
arguments to functions like `assert_equal` as arguments; we fixed
these manually. Since this is test code, we can be reasonably
confident that just fixing the failures suffices to correct any bugs
introduced by making changes automatically.
We now sort lists of users ids deterministically, and we also
sort list of emails deterministically and without regard to case.
This probably fixes the bug #2343, although I never got a great
repro on that.
When we filtered buddy lists, a recent change introduced some
bugs related to case-insensitive emails. We now circumvent the
bug by indexing presence_info with user_ids.
We now use comma-delimited lists of user_ids for the following
data structures in unread.js:
- unread_privates[<user_ids_string>]
- get_counts.pm_count[<user_ids_string>]
Previously, this would incorrectly include a user with name and email
"" in the recipients list shown in the local echo code path.
We fix this and add a test for the issue.
We used to have hacky code where various functions would call
build_stream_sidebar_row() to get a jQuery object, and then they
would attach the jQuery object to the "sub" object from stream_data.js.
Now build_stream_sidebar_row() localizes the hack of attaching
a UI object to the "sub" object to just one function (and we can
clean this up in a follow-up commit).
Also, the UI object is now a JS object that can close on some useful
state information like the stream name and encapsulate how we
toggle the inactive_stream class.
Finally, we don't have build_stream_sidebar_row() needlessly append
list items to $('#stream_filters') when we know that our callers are
going to re-build the list anyway.
It used to be the case that you would get new messages for a
huddle, but the huddle wouldn't show up on your buddy list until
the every-50-seconds mass update of the buddy list.
Now we make sure to work with non-stale jQuery objects, and,
more importantly, we resize ourselves if we add new huddles.
(The resize issue arises due to some complicated heuristics
where we don't want group PMs to take up too much of the buddy
list for users who don't have many in their history.)
* Fixes handling of multiple stream links and invalid stream names.
* Fixes text regex so it handle hash sign the right way.
* Adds tests for these stream link cases.
The widget that gets built in topic_list.build_widget()
now knows how to add itself to its parent element and expose
an interface to retrieve the parent.
This moves one method over from stream_list.js. There's still a
lot of boilerplate here, unfortunately, as topic lists have a lot
of dependencies on other parts of the system--narrowing state,
muting state, jQuery, handlebars, etc.
We now use stream_id as our key to rename streams, which
should prevent a few race conditions long term. (We are
still possibly contending with other events that use
stream_name as a key, so this is not perfect.)
Now we just have two methods of importance:
compile_template
render_template
The compile_template() function will automatically
(and recursively) compile any partials it depends
on and mark those as compiled.
If I try to send a message to an unknown user (which is possible
for some types of realms), then I simply ignore them during the
send codepath, so that I don't later need to patch up their attributes.
We no longer store pm_recipient_count on person objects, but we
instead use a Dict to store them. Then the new API is this:
people.get_recipient_count()
people.incr_recipient_count()
When the render function is run now, it uses the partial_finder
function to search recursively through files for partials and add them
so that test writers don’t have to.
This means that we no longer have to do any manual work to maintain
the templates.js check that all handlebars templates are rendered by
the node tests.
This replaces add_stream_to_sidebar(), which was kind of a misleading
name, and it also adds a couple lines of code that were always
called right after calling add_stream_to_sidebar().
This function will make it easier to unit test upcoming
changes related to stream counts.
This was mostly moving code, but one change is that we
don't call create_subs() in subs.js any more (which would
have been kind of circular dependency), since the only thing
that it did besides calling a more appropriate function
in stream_data.js was to generate a trigger that was
subsequently ignored and possibly a UI trap, as we don't
want to be messing with the stream sidebar when we go into
the stream settings page.
We now simply call exports.create_sub_from_server_data() for
newly encountered unsubscribed streams (which don't belong in
the sidebar anyway.)
This function used to live in subs.js. It's mostly a code move,
but I simplified the logic to determine whether it's subscribed
not to do a lookup into the same data structure that the sub
already came from.
I also added some tests.
Previously, URLs were being incorrectly treated as unknown search
operators (since they had exactly one ":" in them, just like foo:bar
for an invalid choice of foo).
Fixes#1743.
- Expand a box full of emojis into the
compose window for users to graphically select emojis.
- Append an emoji to the end of the message when a user
clicks the emoji in the emoji box.
- Trap the escape key to always close the emoji box
before closing anything else if the box is open.
- Fixes: #147.
This separates the display settings module from the
settings_table.handlebars template.
Additionally, it fixes the node tests to search in the
static/templates/settings directory and initialize any templates in there
while running tests on the settings templates.
In HTML, the line break immediately following a start tag is ignored
(see: https://www.w3.org/TR/html4/appendix/notes.html#h-B.3.1). An
extra span tag has been introduced in the upstream Pygments
HtmlFormatter in order to preserve the first new line. The Bugdown
Tests as well as our fenced_code.js frontend markdown processor have
been updated to reflect this new behavior.
From the popups that appear when clicking the down-arrow in the left
column's streams, you can now unsubscribe from that particular
channel. This runs on the same function that unsubscribes you from
streams in the "Subscriptions" tab.
Fixes: #1554.
[tweaked by tabbott to fix some errors]
This makes sure we are explicit about partials in
individual test modules. Eventually, we should figure
out a way to make partials automatically compile as
part of the node tests.
These tests would work as part of the whole suite, but
not standalone, because they were getting objects out
of node's require cache that a previous test had cleaned up.
Now they should work standalone as well, and the tests
are more explicit about their dependencies.
In templates.js we want to enforce outputting just
one output file per template, and we also keep the source
alphabetical by template name. This isn't a permanent
decision, but it makes organizing the ouput a little
easier for now.
This reverts commit be93b6ea28.
Unfortunately, the newer jquery comes with a huge performance
regression affecting the hotkeys code, which has the effect of making
typing super slow.
Fixes: #1449.
* The warning contains a count of the number of people in the stream.
* An error appears if the warning is ignored and the user tries to
send the message anyway.
* The message cannot be sent until the warning is acknowledged or @all
/ @everyone is removed.
* This only applies to stream messages and not private messages.
Fixes#853.
Previously, we were checking if a particular user was the current user
in dozens of places in the codebase, and correct case-insensitive
checks were not used consistently, leading to bugs like #502.
Now that we're doing presence updates in a performant fashion, we
don't need to throttle processing these events, and in fact the
throttling of these events created a correctness problem, since we're
now doing incremental updates rather than just rerendering everything
after each event.
Whenever a user became active, this triggers an immediate presence
update event (to show that user as active). The implementation for
that event (running on the browsers of all other users in the realm)
would fully rerender the presence list, which can be an expensive
operation in a large realm, just to update the status for that one
user. This fixes that case to just remove the user from the list and
then re-insert it at the appropriate index.
[Commit message expanded with more details by Tim Abbott]
Like the Stream Subject lists, Private messages are now shown
when the user clicks on the "Private message" link. User can drill in
to get more than 5 conversations. Selecting PMs from the user or group
PM lists on the right sidebar also opens the list & highlights the
selected conversation.
[Edited by tabbott@mit.edu to fix some small bugs.]
The node packages 'jQuery' and 'jquery' are different--'jQuery' is the
legacy support package that is needed for Zulip so the require statements
in the tests were updated.
Travis uses node 4.0 by default and we are using 0.10, so the command to
install the correct version had to be added to the .travis.yml file.