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.
In a subsequent commit, we may have unread counts for
deactivated users. There is no reason to fail hard on these
scenarios; if there is no list item for a user_ids_string,
updating the unread count should be a noop.
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 is a redesign of the features landing page from the current style
that includes the new sections in a grid format as well as some new
high-quality sections.
Main reasons:
* Shouldn't be hardcoding welcome bot
* compose_actions.cancel() was not closing the compose box, for some
reason. It was working fine before commit a few up from here ("tutorial:
Remove rest of tutorial."), but I think possibly due to the fact that one
had to click a button to exit the tutorial (that could be wrong, it was
hard to pinpoint why it was working before that commit and not after.)
This code should be going away anyway once #5816 is resolved.
* .screen is no longer being changed by other parts of the tutorial
* first_run_message we don't need, since we're guaranteed to have a message.
* Changing to #home and narrow.deactivate are not needed since we're
immediately narrowing to PM with welcome-bot.
These have been replaced by the initial stream messages and PMs.
The two pieces of information that exist here and not in the initial stream
messages are a link to /integrations, and a demonstration of image
uploading/pasting.
I think the current information presented is already a lot, though probably
it would be good to work in integrations somehow. Image pasting should just
be done in a separate Zulip that demonstrates the many different formatting
features.
The overflow was set to "hidden". I'm unsure of how this was even
working on desktop, but the #user-presences div certainly would
not scroll on mobile. This enables mobile scrolling.
When a user clicks on the `.player-container` node and the click
target is actually that (and not the YT video iFrame within), then
hide the lightbox – they likely mean to exit out of the lightbox.
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.
This makes the canvas zoom and pan feature cross-browser compatible in
a few ways:
1. Replace deprecated `mousewheel` event in favor of the similar and
cross-browser event `wheel`.
2. Create approximate substitute for `e.movementX` and `e.movementY`
values that are missing in Safari.
This completes the major endpoint migrations to eliminate legacy API
endpoints from Zulip.
There's a few other things that will happen naturally, so I believe
this fixes#611.
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.
This class is mostly a thin layer over the dictionary, but it
consolidates all the logic to create lookup keys, which have
to follow the convention of being comma-separated, numerically
sorted user_ids.
interface_type select menu will be used to choose the interface
for outgoing webhooks. It will be displayed only when the selected
bot type is OUTGOING WEBHOOK type. The default value is GENERIC
interface type (1).
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.
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.
The var in question is indexed by stream_id, so stream_dict seems
like a good name for it. We want to distinguish per-stream data
structures from the stream-level entry points.
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`.
This is an issue where in jQuery v3 the result of outerHeight on a node
that doesn’t exist is now “undefined” rather than “null”, which means
it will no longer cast to a Number but rather NaN. For this, we create
the safeOuterHeight and safeOuterWidth functions to safely return a
result (or 0).
This is a better solution than manually going to each instance and
ORing it with 0 for type safety.
https://stackoverflow.com/questions/41454285/jquery-outerheight-returns-
undefined-instead-of-null
This removes the `no-new` rule which is relatively detrimental to
code cleanliness in our codebase because third-party libraries may
utilize data structures that don't fly well with our linting rules.
This also fixes abstractions that were created due to the limitations
and impositions of this lint rule.
Before the user profile bounding box width was not set so it
would overflow the 240px and there would be grey space next to
the avatar. Now the width is always maintained and long text
is cut into multiple lines.
This changes a typo where a function was attempting to execute the
scope of the parent's "this" by using `function () {}.on()`, rather
than using the `Function.prototype.bind` built-in.
The ES6 backticks in /static/js/portico/landing-page.js were causing
the server to trip up. This was fixed by switching from JS string
interpolation to string concatenation (ES5).
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.
It's hinted in the registation process, and as long as one person in the
realm does it, everyone else will know. The tooltip also draws too much
visual attention.
This fixes the original issue that #5598 was the root cause of; when
the user returns to a Zulip browser tab after they've been idle past
the timeout (10 min, per IDLE_EVENT_QUEUE_TIMEOUT_SECS), we now
correctly reload the page even if they're using Zulip in German or
another non-English language where we have a translation for the
relevant error message.
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 code to edit messages that were echoed locally but failed
by the server was broken. We just disable it for now.
We have opened #5841 to try to restore this functionality.
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)
While demoing Zulip at PyCon, I learned that it is hard to
distinguish topics from streams in our left sidebar.
Indenting them by a few pixel seems to make it more clear
that topics belong to a stream.
We used to generate a file at this path in the static build,
but since 3f5d0e69f the corresponding output goes into
static/webpack-bundles instead. Clear the now-dead path
from our gitignore files.
Also add a comment explaining an important non-obvious wrinkle in how
paths in the format are interpreted, and adjust some paths to a
consistent style.
If you use the escape key to close a message edit, we need
to blur out the text fields. Otherwise, hotkeys.js thinks
we are still editing the text. This bug would disable the
use of things like arrow keys until the user subsequently
focused another field.
We probably eventually want hotkeys.js to be smarter about
ignoring hidden fields that still have the focus, but there's
also no reason not to blur the fields here, and this is a more
local, less risky fix.
Currently when hovering over the external link icon generated when a topic contains a
realm filter, an underline appears. This commit removes that underline.
This commit renames possibly_notify_new_messages_outside_viewport()
to the more concise name notify_local_mixes().
We really only need to call this function in one place, so we
have the caller check the `local_id` condition. We can eventually
upstream this code even further so that it's completely
obvious that it's only ever called from the local-echo codepath.
We were calling maybe_add_narrowed_messages() in a place
where local_id is guaranteed to be undefined, since
we always set local_id to undefined when
can_apply_locally() fails.
In turn maybe_add_narrowed_messages() was calling
possibly_notify_new_messages_outside_viewport(), which
requires a local_id to do anything meaningful.
This removes all the associated dead code--passing in
a parameter that we know always was undefined and
calling a function that we know always would no-op.
Not only does this simplify the code a bit, but it avoids
us stepping on the toes of the alternative code path that
deals with non-locally-echoed messages.
This commit early-exits before our loop when local_id is none,
and it tries to more clearly indicate that the callers will
generally be just calling this with messages sent on the
local-echo path.
We now make it so that get_next_local_id() only returns up
to 5 local ids relative to any given max id.
For example, if your pointer is at message 999, we'd give out
999.01, 999.02, ..., 999.05.
We also avoid giving out the same local id twice. This prevents
a bug where if you had aborted a previously failed locally echoed
message, a subsequent local echo would get into a funny state.
In order to to prevent false alarms on using the same local id
twice, we call get_next_local_id() later in the try_deliver_locally()
function.
We had code that would try to re-render locally echoed messages
that were rendered right before a browser restart. This code
has gotten buggy over time, so we are removing it for now.
We will try to re-solve the problem as part of #5825, but
possibly with a different strategy.
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.
This allow the webbpack dev server to properly reload JavaScript modules
while running in dev without restarting the server. We need to connect
to webpack-dev-server directly because SockJS doesn't support more than
one connection on the same host/port.
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.
This either removes aria-hidden=true assignments from buttons with
text, or adds a span to only hide the 'x' symbol rather than the
button for closing buttons.
There is a "user-select: none" (cross-browser) that was put on
the #bottom_whitespace div, but the div doesn't actually have any
content that can be selected, and it also makes it difficult to
deselect selected text because when clicked over it will save the
current selection.
This makes the avatar portion more responsive and efficient on many
screen settings and also fixes some of the design incongruences present
on the page.
This changes the markdown section and sidebar to be the correct
height on mobile along with correcting the broken footer to always
appear below the content.
Fixes: #5798.
This new setting controls whether or not users are allowed to see the
edit history in a Zulip organization. It controls access through 2
key mechanisms:
* For long-ago edited messages, get_messages removes the edit history
content from messages it sends to clients.
* For newly edited messages, clients are responsible for checking the
setting and not saving the edit history data. Since the webapp was
the only client displaying it before this change, this just required
some changes in message_events.js.
Significantly modified by tabbott to fix some logic bugs and add a
test.
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.
Fixes#3496. This was just a simple regex addition to filter
to accept the format `operand:"foo bar"` as a token. Also,
it will now accept an additional space after the separating colon.
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.
Add a line of text stating that there are no active or inactive bots.
This is for better understanding of the user, as blank screen that
used to appear in case of no bots being present might seem broken
to some.
Tweaked by tabbott to improve the English.
The old translation copies in localStorage were not being removed
when they were no longer needed, so we can free up the storage
by deleting them.
This was accidentally not merged months ago when originally
implemented, but it was written to fix#4443 and in fact does so.
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.
Prior to this commit, 7 megabytes of images (through 253 individual requests)
were heavily slowing down the initial load. With this commit, we load only the
logos (60 or so images).
Documentation and images for the individual integration sub-pages is requested
separately using the /integrations/doc/ endpoint, which returns HTML.
This redesigns the /help/ page sets to be a single page app that uses
history.pushState to work the same as the old app.
The big new feature is that now we have the index in a nicely designed
left sidebar.
`add_emoji_by_admins_only` backend setting is represented by page_param's
`realm_add_emoji_by_admins_only` attribute. When this setting was changed
we were wrongly updating the `add_emoji_by_admins_only` attribute which
doesn't exist.
Prior to this, when the setting for controlling whether can admins only
upload an emoji was set to true, we were not displaying upload emoji form
even for admins and as a result they were locked out.
The piece of code is dead since there can be no instance where
email === ''. This is ensured by util.extract_pm_recipients
by filtering for empty strings in the pm_recipients list.
This piece was dead because exports.send_times_data[message_id]
cannot be undefined since the only place this function is called
from is exports.report_as_received() and that function has a call
to mark_end_to_end_receive_time() before a call is made to the
function in question for dead code. The function call to
mark_end_to_end_receive_time results in
exports.send_times_data[message_id] = {} if this was not defined
already. So there can be no instance where we end up the code
being removed.
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.
Creating a new bot (by filling out the bots related fields and clicking
"Create bot" button) changes tab from "Add a new bot" to "Active bots".
This is done to make users know/confirm that the bot has been created and
the user can view it in this tab.
Fixes: #5731
This is to make viewing bots easy from user's perspective. As the
most used tab in "Active bots", "Inactive bots" and "Add a new bot"
would be the first one.
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.
These are some strings I spotted in English when playing around a bit
with the UI set to German, where our translations are near complete.
It'd be great to have a more systematic way of spotting this kind of
omission. Probably a fairly simple linter could catch a lot of cases.
Without this, the "Since you were last here" text got rendered in
English for me every time when I tested in German, both in dev
and on chat.zulip.org.
This brings us to 9 places we invoke `ensure_i18n`. That seems
like a sign that there may well be more places we're still
missing, and that we should probably find a more systematic way
to make sure all our frontend UI rendering waits for translation
to be ready. Anyway, for now, fix this one.
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.
On /integrations.
For scalability and people who type fast, update_integrations is
debounced; the function will postpone its execution until after
50 milliseconds after it was last invoked.
"Add a new bot" UI used to be common in "Active bots" and
"Inactive bots". "Add a new bot" UI was below the list of all
active/inactive bots.
If there were more than a few bots was more than four, then the user
had to scroll down the entire list of bots to "Add a new bot", which
was annoying. This new model makes the UI look cleaner as well.
Eventually, we'll want to support unreacting to deactivated realm
emoji, but for now the issues around name conflicts mean we can't
really support that.
Deactivated emojis should not appear at any of the following places for
use:
1: Emoji pickers.
2: Composebox autocomplete.
3: Custom emoji settings page.
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.
The product page JS detects the page to run small bundle functions
but does not work correctly with language prefixes in the pathname,
such as /es/apps, so this properly detects that.
Fixes#5635.
This old third party library added support
for a "mousewheel" event to detect scrolling.
However, it is not compatible with jQuery 3
and is obsolete now that there is a standard
"wheel" event that accomplishes the same thing.
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.
In this commit we remove a small piece of dead code from
check_stream_for_send() function and also rename it to
check_unsubscribed_stream_for_send() which makes more sense.