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 specifically wait for the length to decrease by one. This seems
like a more deterministic condition to wait on.
Previously we were waiting till the id of the deleted message remained
visible; intuitively, this should have worked but it seems that there
is some race condition that was causing the test to fail sporadically.
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 makes it possible for Zulip administrators to delete messages.
This is primarily intended for use in deleting early test messages,
but it can solve other problems as well.
Later we'll want to play with the permissions model for this, but for
now, the goal is just to integrate the feature.
Note that it saves the deleted messages for some time using the same
approach as Zulip's message retention policy feature.
Fixes#135.
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.
- Add file_name field to `RealmEmoji` model and migration.
- Add emoji upload supporting to Upload backends.
- Add uploaded file processing to emoji views.
- Use emoji source url as based for display url.
- Change emoji form for image uploading.
- Fix back-end tests.
- Fix front-end tests.
- Add tests for emoji uploading.
Fixes#1134
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.
Fixes bugs of when multiple messages are being edited simultaneously.
Specifically, typeahead is no longer broken, copying messages to clipboard
is less buggy, and resizing is no longer
broken when multiple messages are being edited.
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.
This completes a major redesign of the Zulip login and registration
pages, making them look much more slick and modern.
Major features include:
* Display of the realm name, description and icon on the login page
and registration pages in the subdomains case.
* Much slicker looking buttons and input fields.
* A new overall style for the exterior of these portico pages.
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 fixes the fact that our test suites would have trouble connecting
to the other parts of the Zulip service when run with a proxy
configuration (e.g. trying to send requests to localhost through the
proxy!).
Thanks for Vishnu Ks for his work on this.
Fixes#971.
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.
This better sets expectatations for the fact that in Zulip, the
Organization settings UI is available read-only to non-administrator
users.
Tweaked by tabbott to update some additional references.
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.