The streams:all advertisement notice in search should only appear
after all results have been fetched to indicate we've gotten to the
beginning of the target feed.
The notice gets hidden at the start of `narrow.activate` and is
shown just after we've fetched an older batch of messages if the
"oldest" message has been found.
Previously it would get displayed after the first fetch which
takes place from `narrow.activate`. Thus we move this logic to
`notifications.hide_or_show_history_limit_message` which gets
called after a successful message fetch.
Since the home message view contains all the messages we are not
required to display this notice. However if it is already shown
we hide it as a part of `handle_post_narrow_deactivate_processes`.
To accomplish this we need to add `has_found_oldest` key to the
`fetch_status` API.
We also removed the `pre_scroll_cont` parameter as this was it's
only use case and is now redundant.
On update_message events, we were changing narrow before we
locally updated the data, this resulted in a weird mismatch
between locally available data and that fetched from the server.
Ideally, we should not be requesting any data from the server
in most scenarios since the messages for new narrow is
locally available.
As a result, the new narrow didn't have any messages other than
a breadcrumb message. To fix this, we change narrow post
locally updating the data.
The original bug was not exactly reproduced, but a similar version
of it was simulated and was found to be fixed.
Tweaked by tabbott to preserve an optimization.
This ensures that we do this fetch, which is intended to get data on
the pre-event state, before we start perturbing the message list data
structures via rerendering.
Apparently iamcal/emoji-data has a dedicated category for flag emojis.
And get_all_emoji_categories() in emoji_picker.js doesn't return the
Flags category, because we haven't declared that category in our emoji
data logic.
Note that the category looks quite sparse because it lacks country
flags, since we don't yet support emojis combined with a Zero Width
Joiner (ZWJ) (see #992 & #11767).
Fixes#15303.
In the very common event that one ends up looking at not the home view
while the browser is catching the home view up, this ended up
resulting in loading indicators being displayed at the bottom of
whatever narrowed view one was looking at incorrectly.
A proper fix for this will involve making these loading indicators
conditional on what view one is looking at. Since one can change
views rapidly from a narrowed message list to the home view (and in
the future, between narrows), probably the best approach would be to
move the state in `message_scroll.js` the state for whether a loading
indicator is expected to be shown into the `fetch_status` data
structures, and then make all decisions about whether to show/hide a
loading indicator be calls to a function with a name like:
current_msg_list.data.fetch_status.update_newer_loading_indicator()
At least, that's probably what we should call in places like
`narrow.deactivate()`.
Before 77a26d41ae, there was only one
loading indicator (at the top of the page), so the if/else logic for
hiding loading indicators was correct, if confusing. Since we've now
added a new bottom-of-page loading indicator, it's important to have
the logic correctly reset the state to hide all existing loading
indicators on narrowing, and then just render the ones needed/desired
by the current view.
Combined with similar code in `narrow.deactivate`, this achieves the
goal that we correctly update loading indicator state when switcing
views.
This deduplication helps with readability.
Pass get_topic_key in recent_topic_row instead of
computing it in DOM.
Fix broken test_update_unread_count
after this change. This was a regression
which went unnoticed.
We extract stream_edit.rerender to make
the live-update code easier to follow.
The function should eventually be inlined,
but I want to clean up some other stuff first.
These are basically shims for some deeper refactorings.
I basically just try to make the code express the
problems more clearly:
- use stream_name instead of sub
- make early-exit more explicit
- make it clear that add_subscriber needlessly
requires a name
- make it clear we have an unnecessary loop
I also fixed some phony data in the test.
We are trying to phase out the trigger-event way
of telling modules to do something.
In this case we not only remove the indirection
of the event handler, but we also get to remove
`compose_fade` from the `ui_init` startup sequence.
This also has us update `compose_fade` outside
the loop, although that's only a theoretical
improvement, since I don't think `peer_add` events
every actually include multiple streams.
To make the dispatch tests a little flatter, I
added a one-line change to zjsunit to add
`make_stub` to `global`.
To manually test:
* have Aaron reply to Denmark (keep compose box open)
* have Iago add Hamlet to Denmark
* have Hamlet unsubscribe
Previously, the navbar failed at managing the searchbox text state in
cases where, eg, the user performs navigation by browser history.
This commit resolves the issue by ensuring that the searchbox text is
only (and always) set when the searchbox is made visible, and as such
there is no "state" to manage and we will always display the correct
text.
It also adds a test in `search_legacy.js` to make sure that the search
text is placed as intended.
Fixes: #14771.
The navbar currently fails at managing the searchbox text state in
cases where, eg, the user performs navigation by browser history.
This is a prep commit that will help resolve the bug.
I tried to make the most minimal change here
possible, since I don't really know this module
well. Possible alternatives were:
* $('#tab_bar') everywhere
* elem
* tab_bar_elem
I don't feel strongly.
Long term I believe we intend to change the name
of this module to something more like `navbar.js`???
When we call functions inside our own modules that use
the `window.foo = exports` pattern, we have always had
a pretty strong preference to call `exports.internal_function`
instead of `foo.internal_functions`.
The stragglers here weren't violating this convention
for any intentional reason. Some of the places here
probably were part of code moves where somebody
(probably me) moved functions into the modules to avoid
unnecessary indirection, and I missed a spot where I
could change from `presence` to `exports` (or whatever).
And other places are probably just kinda arbitrary
decisions by the original developer, and we just haven't
bothered to clean it up until now.
This combines `upload_realm_logo` and `upload_realm_icon` into single
function called `upload_realm_logo_or_icon`. The functions wer near
duplicates.
Additional refactoring should be able to deduplicate the logic further.
Part of #14730.
We can remove a {{theme_mode}}-settings class on the upload button
and access day/night from `.closest("realm-logo-section")`
so that only the outer ID differs between the two widgets.
Part of #14730.
Previously, renaming the stream would cause `colorize_tab_bar` to fail
because the search filter would provide it the old stream name and the
look up for the stream color would fail.
A quirk of how this system currently works makes it so that even
though the filter is set to the old stream name (and so becomes
inconsistent with the stream_data state) the `_stream_params` object
is maintained to be consistent with stream_data and as such can be
relied upon to find the correct color of the icon.
Previously the navbar did not live update the stream name correctly.
The correct behaviour was blocked on the `_stream_name` prop on the
filter object. The original purpose for maintaining this prop was
convenience, to reduce calls to `subs`, however, it would become
inconsistent with the value from `subs` on stream rename.
In this commit we add a call to `filter.fix_stream_params` in
`subs.update_stream_name`. This fixes live rerendering in the navbar,
despite the fact that searchbox in the nav (and the filter object via
`filter.operands("stream")[0]`) will still have the old name.
This is a slightly hacky way of masking some of the problems in the
Filter object. However, it should make do until we migrate to a stream
ID based state there.
Fixes: #14728.
Prior to this commit the icon in the navbar didn't live update to
reflect changes in stream privacy.
Here, we add a call to `tab_bar.render_title_area` in
`subs.update_stream_privacy()`, to enable live updates on the icon.
Fixes#14728.
The navbar currently does not live update the stream icon correctly
for changes in stream privacy.
One place where the correct behaviour gets blocked is on the
`_is_stream_private` prop in the filter object. We keep props such as
this for convenience, to reduce calls to `subs`, however, this prop
becomes inconsistent with the value we get from `subs` when the stream
privacy is updated.
In this commit we add a call to `filter.fix_stream_params` in
`subs.update_stream_privacy`. This change does not fix the live
rerendering in the navbar because we don't call redraw yet, but
it's a prep commit to towards that goal
The navbar currently does not live update the stream name or the icon
for stream privacy correctly.
One place where the correct behaviour gets blocked is on the
`_stream_name` and `_is_stream_private` props on the filter object.
We keep these props for convenience, to reduce calls to `subs`,
however, these props become inconsistent with the values from `subs`
when the stream is renamed or stream privacy is changed.
This refactor extracts out `get_stream_params` and `fix_stream_params`
methods as a prep commit towards correcting the problem, but does not
make any behavioural changes.
This is a prep commit for solving #14728.
A comment about the difficulties relating to live updating stream
names in the navbar was incorrectly placed within the function for
live updating stream descriptions in
023187b3f1.
This moves the comment to the right place.
We store the relevant data to hide/show a topic in the row itself,
and use jquery to hide/show it on filter change.
This also fixes search breaking the set filters.
This fixes the bug that message was undefined since we used to store
locally echoed message id and were not updating it after new message
id for the same message was received from the server.
We remove all trace of the old topic and reprocess all the new
messages in old and new topics.
process_topic_edit function was moved since it needs to be below
get_topic_row function.
We reuse the existing logic for displaying and updating stream color
from the stream left sidebar.
Tests fixtures were extracted and updated for this commit.
The approach that supposed to use this data was not implemented
and hence this data will no longer be used.
If this feature is implemented in future,
this data will still not be used since we would depend upon
starred_messages.js library to provide us the required information.
* Add action to mute topics.
* We don't need to store muted data per topic as previously planned.
* Moved launch topic test to the top so that they run on non-modified
data.
* Show an empty overlay of recent topics.
* Register click event to open recent topics.
* Launch recent topics on "t" keypress.
This is based on the draft overlay.
This is part of a refactor that aimed to remove /json/users calls,
as we can get all the information needed on people API.
Now, the list render for $users_table and $deactivated_users_table
uses user_ids instead of user objects, as the people API give us
a filtered list of active_user_ids and non_active_user_ids.
The populate_users function doesn't need to sort the list of
active and non-active users, because the list_render is called
specifying to sort users by their full_name.
Author: Clara Moraes Dantas <clara.moraesd@gmail.com>
As part of a refactoring, we are now able to remove the
/json/users calls and get all the information needed on people.js.
To do this, now the populate_users uses the people api to get
all the active and non active human users.
This is part of a refactoring aimed to eliminate /json/users calls,
as we can have all the information needed on people.js.
Now, human_info() will call is_person_active() because the person
object it will receive won't have is_active field anymore, as
we'll use the people api to get a set of filtered active/non active
users.
Author: Clara Moraes Dantas <clara.moraesd@gmail.com>
This was previously hardcoded with agreement between the Zulip backend
and frontend as 86400 seconds (1 day). Now, it's still hardcoded in
the backend, but arranged in a way where we could add a setting
without any changes to the mobile and terminal apps to update logic.
Fixes#15278.
I don't believe it's actually been possible for this to be shown in
Zulip in several years; and we just made it more obviously so
(resulting in a linter error).
We now trigger realm day/night logo upload by clicking on realm
day/night logo element itself rather than having a big upload button
and to match our user avatar UI. Added new spinner over the logo
element itself to show while uploading realm logo for both day and
night logos.
Change user avatar spinner implementation to match
realm icon spinner implementation and have common css class
since similar implementation between similar widgets may help
in future deduplication.
The orig_initial_pointer variable was part of the implementation for
ensuring server-initiated reloads preserve the user's selected message
and scroll position (so that they are not disruptive). Previously,
the logic did some unnecessary contortions to ensure the two goals:
* The `pointer.js` logic knows what the server thinks the pointer is.
* The `message_fetch.js` logic knows what anchor to use to center it's
home view fetch.
It's a lot cleaner to do this by not mutating page_params.pointer.
In the past, the anchor message has always been the same as the
pointer, but we're about to change that as part of removing the
pointer entirely.
Using the anchor is logically what we meant, anyway, since we always
want to select a message that's actually within the range we just
fetched.
This was implemented in 2012 to avoid showing a loading indicator for
fetching messages for users with no message history. However, the
Zulip onboarding UI always creates some message history, and fetching
history is fast, so this is likely clutter more than a useful
optimization.
We're migrating to using the cleaner zulip.com domain, which involves
changing all of our links from ReadTheDocs and other places to point
to the cleaner URL.
Previously, the edit history modal did not respect the time format
setting (whether to show times in 12-hour or 24-hour format) when
displaying message edit times (#15171).
This commit fixes that by passing the edit times to
timerender.stringify_time(), which takes that setting into account,
instead of just doing a static string formatting operation.
This bug has existed since February 2017, when the edit history UI
was first added in 1a697b6e02.
Fixes#15171.
Currently, the edit history modal does not respect the time format
setting (whether to show times in 12-hour or 24-hour format) when
displaying message edit times (#15171).
This commit refactors how fetch_and_render_message_history() handles
times in order to make fixing that issue in a reasonable way easier.
It will be fixed in a following commit.
Previously, the show_date_row flag for the first entry in the edit
history modal was directly set to `true`, while in all other entries
it was calculated with identical code. Though show_date_row for the
first entry should indeed always be true, there's no need for it to be
a special case.
In preparation for factoring out the calculation of show_date_row,
this commit nominally calculates the first entry's show_date_row with
the same code that is used to calculate show_date_row for all other
entries. Nominally, because it will still always end up being true.
Previously, the logic for when to add a date row to an edit history
entry was checking against the date of the original message (which is
always the first entry in the message history), not the date of the
previous edit. This caused every edit not made on the date of the
original message to show a date row, even if it wasn't the first edit
on that date.
This commit fixes that bug by updating prev_timestamp after processing
each message history entry, whereas before it was only updated after
processing the first one — the original message.
This bug has existed since June 2017, when
84e5fe733c changed how date rows worked;
from only showing one at the top labeled "Earliest" to each entry
having a possibilty of showing one.
Previously it was impossible for a topic-only edit to show a date row
in any circumstance; the code that handles topic-only edits didn't
even attempt to set show_date_row, the flag that determines whether a
date row should be rendered. Now a topic-only edit will show a date row
in the same circumstances as any other edit[1].
This bug has existed since March 2019, when rendering of topic-only
edits was first added in 38be5ea743.
[1] Currently, "the same circumstances as any other edit" means
there'll be a date row on the original message, and then on every edit
not made on the same date as the original message, even if it was't
the first edit on the date it was made. This is a bug that will be
fixed in a following commit. This commit is being made first since
it's fixing a lack-of-information bug, whereas the other bug is a
somewhat less important repeating-information bug.
The `wildcard_mentions_notify` key was missing from the initial
sub data when a new stream was created. Thus `wildcard_mentions_notify`
was undefined and `wildcard_mentions_notify_display` was false.
(This key is used to render the data in the templates)
This caused a bug where the wildcard notifications was unchecked
in the stream personal settings and the newly created stream was
displayed in the stream specific notifications table.
Prior to commit 8b7e70ac27 this system
would simply just .hide() forms when they were closed and
.empty().append() every time it needed to "show_edit". This was not a
very clean way of handling the action of canceling an edit, so
8b7e70ac27 introduced a change that had
the "show_edit" function append the form and the "hide" function
.empty() the form.
However, we overlooked the fact that the user could use browser
history to navigate away and back to the form and use "e" or
"left arrow key" to successfully append another form and get to an
ugly, broken state.
This commit does not revert 8b7e70ac27
as it is still accurate to .empty() when hiding the form, but we add
an early exit if a form already exists, to avoid bugs like the above.
Using an early exit instead of eg .empty().append() ensures that the
user doesn't accidentally lose the entire content of an edit, if they
deselect the input box and press `e`.
Fixes: #15045.
Fix a bug where the color picker reverted the custom color to the
previous one after clicking outside the popover. The bug occurred
because although there is a confirm button, the 'clickoutFiresChanges'
option was set as true, which made the frontend always send two POST
request to edit the stream and, for a reason I wasn't able to discover,
if you hit the confirm button and click outside fast enough, the change
fired by the clickout event sent the old color to the server. It was
fixed by setting the 'clickoutFiresChanges' option to false.
Fixes#15101
If typeahead is used, this adds comma separated search queries
so that multiple search pills don't get combined as one and the
search behaviour remains same as search_pills_enabled = False case.
If typeahead is not used, this prevent the typing of a single comma
after the pill gets created.
This commit removes the 'get_active_user_for_email' function
from people.js. We have removed the use of this function
in the previous commits, which changed the functions using
'get_active_user_for_email' to use user_ids instead of emails.
This commit changes the would_receive_message to use user_id
instead of emails.
This change is done because user_ids are immutable and using
user_ids is the correct way of uniquely identifying user.
The change in 'would_receive_message' also leads to change
in util.is_pm_recipient to use a string of user_ids instead
of emails.
We also know that user_ids passed to 'would_receive_message'
are active user_ids, since we get them from buddy_list.
So we don't need to check whether the user is active, which
was previously being checked by get_active_user_for_email.
This commit changes the needs_subscribe_warning function to
use user_id instead of emails.
This change is done because user_ids are immutable and using
user_ids is the correct way to uniquely identify a user.
We already know that user_ids being passed in this function are
active user_ids, since they come from typeaheads.
So, we only need to call 'people.get_by_user_id', to get the user
object from user_id and do not need to check the active status of
user, which was done previously using 'get_active_user_for_email'.
Option to disable breadcrumb messages were given in both message edit
form and topic edit stream popover.
User now has the option to select which stream to send the notification
of stream edit of a topic via checkboxes in the UI.
It's safer and cleaner to simply just rerender the entire navbar for
small updates like these since they're rare events. Given that we're
not doing anything unique in such updates, it's best if we just call
".render_tab_bar" wherever required instead of having several
functions in tab_bar.js which do exactly that. This also sets a good
precedence of what to do for stream privacy and subscriber count live
update.
However, we can't easily fix the "subs.update_stream_name" code path
because of how the Filter objects represent the stream by name, not be
ID. Given that the above would be out of scope for this change, it's
left as a TODO.
It's best to separate these in order to simplify the "build_tab_bar"
function. We also correct a comment about the "search_exit" click
handler being for the searchbar.
This commit changes the compose_invite_users template to use
data-user-id as property intead of data-useremail.
This is changed to maintain consistency with other parts of the
code where user_ids are used for referring to users.
This also helps in removing some of the checks for the case of
undefined emails.
We now send user_ids to the backend API for subscribing/unsubscribing
users to a stream instead of emails.
This change is done now because we have just migrated the backend API to
support sending user_ids in 2187c84, so it wasn't possible before.
This change is helpful because sending user_ids is more robust, as those
are an immutable reference to a user, rather than something that can
change with time.
Unable to upload a realm logo once we encounter file input error bug
was fixed by clearing `get_file_input()` after file input error
with `get_file_input().val('')`.
The previous .clone() logic was preserved over many years but
apparently was also just wrong.
Fixes#15198
The get_active_humans and get_non_active_humans functions used
to return a list of user objects. The get_active_humans is used
on settings_users.js and settings_bots.js, and in both places the
only attributes needed of the person object are the user_id and
full_name.
To make the function return smaller, instead of a list of active
humans, we are returning a list of active human ids, saving memory.
With the ids we can call the people API to get the full_name attribute.
This reimplements our Zoom video call integration to use an OAuth
application. In addition to providing a cleaner setup experience,
especially on zulipchat.com where the server administrators can have
done the app registration already, it also fixes the limitation of the
previous integration that it could only have one call active at a time
when set up with typical Zoom API keys.
Fixes#11672.
Co-authored-by: Marco Burstein <marco@marco.how>
Co-authored-by: Tim Abbott <tabbott@zulipchat.com>
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
This commit fixes the bug for subscribing the user from mention
warning which was introduced in e52b544.
This is fixed by changing email to be passed as list to
'invite_user_to_stream'.
The reason for this change is that, this is where `Filter` and
actual tracking of what messages are contiguous lives. This
will be beneficial when we will to move to a model where we
cache `MessageListData` objects for a large number of views.
This commit changes the stream settings UI for adding subscribers to
use our standard user pills in the input box, rather than just
plain-text email addresses. This is important progress towards
removing display email addresses from the Zulip UI.
It also allows subscribing multiple users at the same time, which is a
nice improvement.
Previously, the unsubscribe logic just called
exports.show_subs_pane.nothing_selected() if one had been viewing the
edit UI for a stream that the user just unsubscribed from, which
clears the selection, but didn't update the hash or do other cleanup
logic.
We should instead be calling stream_edit.open_edit_panel_empty(),
which is the appropriate function for this purpose (and has
exports.show_subs_pane.nothing_selected as a subroutine).
There's no reason to send data beyond the user `id` of the uploader,
and reason not to, as the previous model was both awkward when
`author=None` and resulted in unecessary parsing complexity for
clients.
Modified by tabbott to add the frontend changes and API documentation.
Fixes#15115.
This commit changes the person dict in event sent by do_change_user_role
to send role instead of is_admin or is_guest.
This makes things much more straightforward for our upcoming primary
owners feature.
This commit changes the update user API endpoint to accept role
as parameter instead of the bool parameters is_guest and is_admin.
User role dropdown in user info modal is also modified to use
"dropdown_options_widget".
Modified by tabbott to document the API change.
This reverts commit 9f5725d265.
I was trying to fix how we size the buddy list in
narrow mode, which was off by 10px, but my fix worsened
things for regular mode.
Also, somebody reported a traceback related to my fix.
I didn't fully research the traceback,
but I suspect it was related to some media-query settings
for small screens or due to a put-buddy-list-in-left-pane
setting. (Basically, `$('#right-sidebar').position()` may
be undefined in some cases, and I wasn't handling that.)
After reverting this, we still have the original
off-by-10px bug that I was trying to fix, but I will
attempt to do that more cleanly in a separate commit.
This should make it so that in normal situations where
the buddy list is in the right sidebar, we will be
able to see the "Invite more users" link again.
I am still a little puzzled how I didn't catch this in
testing, but it was toward the end of a long PR, so
it could easily just be simple human error.
Fortunally, this regression was only on master for a
couple days, and users could still invite users via
the gear menu.
Restored old behavior accidentally removed in
1ae07b93d8 (diff-e353fab8bea58b8746ec68c83aa39b36L48)
The server only remembers the most recent presence status update per
device. Meaning that, for instance, if the user only uses one client and
that client's last status update was IDLE, then the server only knows
that, doesn't know anything about the user's last ACTIVE time. Thus the
"active_timestamp" the server will serve about this user to the webapp
will be "undefined".
The old behavior was that for the sake of the "Last active: x ago"
status in buddy list popover, the latest status timestamp was used,
whether IDLE or ACTIVE.
The change linked about changed that to only pay attention to
ACTIVE. Thus, if the server doesn't remember any ACTIVE statuses, webapp
would show "Last active: More than 2 weeks ago", which was incorrect.
We restore the old behavior and further improvements can be made on top
of this.
Previously, we had to fiddle with the generated HTML to update
individual values. Now, we can simply ask the widget to rerender
the row that we updated.
This is done by passing an html_selector function that returns
a selector for the rendered item.
If:
- we do not provide html_selector function
- item is not currently rendered
- new html is not a string.
then the render_item() call is a noop.
We do not shift much of the validation logic here just
yet. This function has been declared at the top of the
file to act as usage docs for the widget as well, in
terms of what combinations of opts are valid and what
are not.
We remove the "GROUP PMs" section that used
to be in the lower right sidebar.
Most of this is straightforward code removal.
A couple quick notes:
- The message fetching code now just
calls `huddle_data.process_loaded_messages`,
which we still need for search suggestions.
We removed `activity.process_loaded_messages`.
- The `huddle_data.process_loaded_messages`
function no longer needs to return `need_resize`.
- In `resize.js` we now just calculate
`res.buddy_list_wrapper_max_height` directly
from `usable_height`.
This fixes the calculation for how far from the
top of the viewport we think #right_sidebar's
top is. To fully explain this commit requires
some background info.
Normally `#right-sidebar` has 50px of top margin
and 0px of top padding. And our `resize.js`
calculations have been accurate for the normal
case.
But when you are in the so-called `.expanded` mode
(i.e. when you're in a narrow window) we split up the
50px as follows:
- 40px margin
- 10px padding
Why don't I make the CSS just be more consistent here?
- If you go to 50px in the "expanded" mode
you mostly cover up the right scrollbar,
except for the 10px gutter that is below
the 40px-tall `.header` section. To fully
cover it we apparently want the padding;
otherwise you see a small, unusable remnant
of the scrollbar which just looks funny.
- If we were to make the "regular" right sidebar
just always have the 40/10 split, then we
would start to diverge from the left sidebar,
which is currently 50/0 as well.
- If we went to make both the left and the right
sidebars 40/10 split, well, that's just an
even riskier change.
So instead I fix the resize calculation:
I just calculate the actual `top` position.
Is any of this actually user-facing?
Yes. Now if a user is a narrow window and
they open the buddy list, we will make
the buddy list 10px smaller to account for
the padding. This makes it less likely for
the invite link to get squeezed out.
We'll use this in the next commit.
Note that there's a minor change in the order
in which we apply new heights--we now
do sidebars before bottom whitespace.
We had a bunch of places where we
were calling `resize.resize_bottom_whitespace`
with no arguments, which has been a no-op
since the below commit that removed support
for our `autoscroll_forever` option:
fa44d2ea69
With the `autoscroll_forever` options things
like opening/closing the compose box could
alter how much bottom whitespace you'd want,
but we stopped supporting that feature in
2017.
Since then bottom_whitespace has just always
been 40% of the viewport size. So we only need
to change it on actual resize events.
It's worth noting that we still call
`resize_bottom_whitespace` indirectly in many
places, via `resize_page_components`, and
the latter actually causes
`resize_bottom_whitespace` to do real work,
but that work is redundant for most of those
codepaths, since they're not triggered by
changes to the viewport. So there are other
opportunities for cleanup.
The `buddy_list_wrapper` has zeros margins, so it's
just noise in the current calculations. You can
verify this pretty easily with console statements,
as well as looking at the code. I tried it with
various permutations of narrow windows and display
settings.
Trigger realm icon upload by clicking on realm icon element itself
rather than having a big upload button and to match our user avatar UI.
Added new spinner over the icon element itself to show while
uploading realm icon.
Computed indexes into these raw objects should be guarded with
Object.prototype.hasOwnProperty; make our accessors do this
automatically and use them consistently.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This is a prep commit which combines the previous `#searchbox`
block with the newly updated `#searchbox_legacy` block which
contains the modifications related to the new navbar display.
This only consists of changes to `#searchbox` and is still broken.
But it integrates the searchbox with the new tab_bar changes so that
only one searchbox is shown (instead of two, previously).
This is helpful because if the user pastes multiple queries in the
searchbox and there are invalid search operators, then it is visible
through the typeahead.
The main reasoning for this change is as follows:
* When the search bar contains multiple search queries
but no search results, the last search operand does
not get displayed.
This happens due to the fact that filter object
contained 2 terms having the operator key value as
"search" instead of a single term where operator is
"search" and operand is a single string containing
the space seperated search queries. This condition
occurs for search_pills_enabled case only because
we used to Filter.parse the query twice
(once for the `base_operators` and once for the
`suggestion_operator instead of doing both at once).
Thus the `search_query` value inside the
`narrow.show_search_query` function which only
selected the operands of the first term displayed
an incomplete result.
* Another benefit of this commit is to display the narrow
operators in the URL fragment the same way as when
search_pills_enabled = False.
For example, On entering the queries in the mentioned
order -> 'is: starred', 'abc', 'def', 'is: private',
'ghi'. This is the URL:
Previously:
/#narrow/is/starred/is/private/search/abc.20def/search/ghi
Now (same as pills disabled case):
/#narrow/is/starred/is/private/search/abc.20def.20ghi
* We are also able to de-duplicate the non-typeahead search
query code path.
As mentioned in the comment for `KEY.BACKSPACE` event
in `input_pills.js`, we do normal character deletion
if there is input present. However this wasn't the case
if spaces were present. Also the input wasn't cleared
after the last pill was removed.
Thus `trim()` is removed from the input length check and
the new pill is still created from the trimmed value.
We can remove the typeahead by clicking outside the search box
after we have entered the search string to be filtered and then
focus on the searchbox and press enter or just by pressing enter
on an empty string.
Previously, the narrow would just deactivate for the above condition
as the searchbox value which was passed as the raw_operators parameter
to the narrow.activate function was empty.
This happened because we called the activate function on pressing
enter for the keyup event, while the keydown event in the parent
container made a pill from the text and cleared the input. (as
mentioned in the comment for `KEY.ENTER` case in `input_pill.js`)
The people.js tests were using _add_user function to add
cross realm bots. The problem is that _add_user function
doesn't properly simulates the adding process as it doesn't
add the user in cross_realm_dict as well.
To solve this and eliminate the need of calling
people.initialize(), which means the params obj needs to be
defined, we extracted the whole logic of adding a cross realm
user into a separete function, add_cross_realm_user.
This makes it so that search_suggestion.js
does not depend on activity.js.
That dependency hasn't really been "elegant"
for quite some time, but it will become particularly
unnecessary when we go to remove the "Group PMs"
section from the right sidebar.
This commit introduces a temporary wart
where we have these two functions with the
same name in a sort of unnecessarily
complicated code stack:
activity.process_loaded_messages
huddle_data.process_loaded_messages
But we will eliminate the former function
very soon, and our message-related codepaths
will just call the `huddle_data` version
directly.
TESTING NOTES:
Now that `huddle_data` is a tiny leaf
module, it's super easy to just use the
real implementation of what was formerly
called `activity.get_huddles()` (and is
now in `huddle_data`).
When I first wrote this commit, introducing
the real implementation of `get_huddles` exposed
some bugs that I fixed in the immediately
prior commits to this.
When the tests were originally written,
I believe `activity.js` had some annoying
`jQuery` dependencies that made it hard
to unit test against. We've slimmed it over
time to be mostly just a "controller" module.
But even in its current state it would have
been a bit of a bloated dependency.
The other friction for using the actual
version of `get_huddles` was setting up
the message data, but that's pretty minor.
If you have a group PM where some users have
three-digit user_ids and some with four-digit
user_ids (or similar), a huddle could effectively
be ignored when determining the order of
search search suggestions.
Basically, we need a way to canonically sort
user_ids in "huddle" strings, and it's somewhat
arbitrary whether you sort lexically or sort
numerically, but you do need to be consistent
about it.
And JS is not exactly helpful here:
> [99, 101].sort()
[ 101, 99 ]
This is a pretty obscure bug with pretty low
user-facing consequences, and it was never
reported to us as far as I know, but the fix
here is pretty straightforward.
We have had similar bugs of slightly more consequence
in the past. The reason this bug has shown
up multiple times in our codebase is that every
component that deals with huddles has slightly
different forces that determine how it wants
to serialize the huddle. It's just one of those
annoying things. Plus, bugs with group PMs
do tend to escape detection, since most people
spend most of their time either on streams
or in 1:1 PMs.
This is a pure code extraction. The current
code is buggy with respect to user_ids with
different lengths of digits, i.e. it does
a naive lexical sort instead of a numerical
sort. We'll fix that in the next commit.
We already have a loading indicator for fetching older
messages. Thus it makes sense to implement the same
for displaying newer messages.
We set the display of `bottom-messages-logo` to none,
to prevent displaying two loading indicators during
the initial message load.
Fixes#15060.
`loading_more_messages_indicator` is renamed to
`loading_older_messages_indicator`.
This is a prep commit to introduce
`loading_newer_messages_indicator`.
This commit replaces fa-file-text-o with fa-file-code-o which is a
better signal for the "view source" action. It also deletes a single
line comment that had suggested the change once we moved into font
awesome 4, which Aditya Bansal <adi.bansal241996@gmail.com> helped
out in doing, first via
91962aa6ab and most recently via
75ae94e459 with several commits in
between.
This commit adds code to live update the message edit history.
Message edit history is fetched and rendered again if the edit
history modal is open.
This also adds 'data-message-id' attribute to 'message-history'
when opening history modal element which is used for checking
whether the history modal opened is of the message which is
edited.
Fixes#15051.
"Saving" widget was working for all personal stream settings but "Mute
notifications". This was because the change to the "Mute" property follows
a slightly different path.
This code generates the timestamp string to be shown to the user
from the given timestamp in unix format using moment.js.
We also render the timestamp in a pill.
Previously, we handled this code only in message_list_view.js.
Now we support rendering stream descriptions and some dynamic
elements can be rendered in them, so we extract this new module
and use it in both the places.
We now parse tex and latex as regular languages, highlighting them
with pygments. We only allow 'math' to trigger latex rendering,
which is in line with the documentation.
This commit shifts our timestamp syntax to be of the form:
<span class="timestamp data-timestamp="123456"></span>
since value is not a valid attribute of span elements.
This adds support for syntax like: !time(Jun 7 2017, 6:30 PM) so that
everyone sees the time in their own local timezone. This can be used
when scheduling online meetings, etc.
This adds some hardcoded values for timezones, because of there
being no sureshot way of determining the timezone easily. However,
since the main way of using the feature should be a typeahead for
entering the time, this shouldn't be cause of much concern.
Fixes#5176.
We wrap the [reset] anchor tag in a button so that we can set 'disabled'
attribute on it. We change the styles to hide the [reset] button and the
pencil icon when the widget is disabled.
We also need to call `e.preventDefault()` in the event handler since now
the anchor tag behaves as a button.
Add methods to extract recent topics from received messages.
Process new messages as they are received.
Use new messages received from the server to extract recent_topics.
Node tests added.
Previously, we tried to read the value from page_params, which was just
a hack to make the calling code look cleaner. We now remove that hack
and thus, our dependency on page_params existing. Now, if the caller
does not specify a default value, we'll use the null-value.
This also creates a new init() function to cleanly wrap the code that
makes changes to the opts passed to the widget.
Change in stream color occurs very rarely, and the palette is taking a lot of space in the popover.
This commit will hide the palette in default view of stream popover.
This commit allows non admins to set stream post policy while creating
streams.
Restriction was there to prevent user from creating a stream in which
the user cannot post himself but this will be taken care of with
stream admin feature.
We had removed this function from the codebase when we switched to
using dropdown_list_widget. This was accidentally left as it is when
making that change.
This significantly reduces the time required to handle events like
stream & topic name edit for topics.
Verified using the Chrome Profiler for a topic with 100 messages:
With this commit: 0.64s to move the topic to a different stream.
Without this commit: 5.5s.
Before we used a selector to check whether the "Subscribed" tab
is active or not. The problem is that if a new sibling of the tab
switcher is inserted in the DOM and uses the same classes as the
"Subscribed" and "All Streams" button do, the selector can get
the sibling element instead the tab button.
To avoid that, we are using a variable that tracks the current
active tab instead of using the selector.
* Stream bar color logic is borrwoed from compose stream bar.
* Use flex containers to align elements and automatically set their
height to be same, them automatically filling the stream color bar
height to be the height of the select box.
* Use flex-wrap to wrap the propagate selector when out of space.
* To make sure stream select box and stream color box are closest possible,
select box has been moved under stream color box.
Fix a bug where the compose box didn't collapse when sending a message
from the preview area by hitting the send button. The bug ocurred because
the preview area wasn't being properly cleared when this flow was executed.
This was fixed by moving the clear_preview_area function call for a place
that will be reached by both the enter and button flow.
Fixes: #14889
Previously, we handled these updates in server_events_dispatch
and could accidentally call widget.render() before initializing
the widget.
Original report: https://chat.zulip.org/#narrow/near/875608.
The sync_realm_settings function ensures that if the settings are
not open, any updates are a noop.
If you were on "All Streams" tab and unsubscribed to a private
stream, that stream row would momentarily disappear. If you
click again on "All Streams" button, it would appear again.
The problem was that the selector was finding two elements
instead of just the tab element. To solve this we used a more
specific selector to make sure we are getting the Subscribed
tab only.
This commit fixes the bug of incorrectly showing/hiding the
realm logo delete button by using realm_night_logo_source for
checking the source of night mode logo instead of previously
used realm_logo_source for both day and night logos.
When a user changes its avatar image, the user's avatar in popovers
wasn't being correctly updated, because of browser caching of the
avatar image. We added a version on the request to get the image in
the same format we use elsewhere, so the browser knows when to use the
cached image or to make a new request to the server.
Edited by Tim to preserve/fix sort orders in some tests, and update
zulip_feature_level.
Fixes: #14290
* Remove old topic and reprocess both old and new topic to ensure
that we are correctly storing the last_msg_id of users in the
topic. Also, Handle topic's stream (& topic) edit updates.
* Add function to get all messages in a topic in message_utils.js.
* Send topic edit event to recent_senders.
* Add func get sorted list of recent_senders to topic.
The function will be useful to handle topic edits in Recent Topic UI.
This commits improves how we handle <a> tags within the navbar
description. The code previously overlaid click regions on top of each
other, which was messy and probably somehow buggy.
It is cleaner if we just check if the click was on an <a> tag or not.
* This feature is currently only visible to admins.
* Locally echoed messages are also updated.
* Add UI for editing stream if user is admin.
* Show propagate mode selector if either stream or topic changed.
We use this new widget in bot settings panels
(personal and org). It lets you re-assign a
bot to a new human user.
Ideally we can improve this code to use
our existing list widgets to make it more
performant for realms with lots of users.
We no longer use `/json/users` in the codepath
for bot settings (admin side).
We also specifically don't load human users when
we load bots, so you no longer have to pay for
the server round trip as a side effect of loading
bots. Instead, there is a dedicated `set_up_bots`
entry point.
We also get the bot ids directly from `bot_data` now.
This commit, to some degree, builds on the prior commit
that had us hydrate data from `people.js` instead
of the payload from `/json/users`.
Our `list_render` list widget gives us the
option to use ids as our "list" and then
hydrate that list on-demand with an
`opts.get_item` function.
We now use that for the bots list, passing
in `bot_info` as that option.
And, importantly, we are now actually
hydrating the bot data from `bot_data.js`
data structures, and not `/json/bots`.
Using the `get_item` scheme has a couple
benefits:
- Our sort functions are based on the
actual items that we use to build the
template, so there's a bit less
code duplication. (Generally, the
data that we pass in to the template
is "finalized" in some sense, such
as the bot owner name.)
- We are less likely to display stale
data.
- We are less likely to wire up filters
to intermediate data elements that are
not actually displayed to users (think
of email vs. delivery_email).
We do rely on `get_item` (i.e. `bot_info`)
to be inexpensive, which it should be.
Note that we haven't completely decoupled
ourselves from `/json/bots`, which we still
use as our source for bot user_ids. We will
fix that in the next commit.
We want to move toward having list consumers
pass us in a list of ids that we hydrate later
in the process. This should help live-update
scenarios. The next commit will describe the
benefits in a bit more detail, using the
concrete example of our bot settings table
in the org settings.
A slightly longer-term goal here is to be
able to ask `list_render` to re-render a particular
id, and this moves us closer to that. But even
before that, this change should eliminate a class
of bugs dealing with stale data, such as when
you manually patch a list (with direct jQuery
hacks) but then later go to sort/filter the rows.
We will now re-hydrate the items in those scenarios.
We don't really need to know whether we've loaded
the user-related panels, since we only used `meta.loaded`
for a tiny optimization to avoid a jQuery lookup.
We rely mostly on the list widgets from `list_render`,
and they are smart enough to repopulate themselves
when they're called subsequent times.
For the below payloads we want `owner_id` instead
of `owner`, which we should deprecate. (The
`owner` field is actually an email, which is
not a stable key.)
page_params.realm_bots
realm_bot/add
realm_bot/update
IMPORTANT NOTE: Some of the data served in
these payloads is cached with the key
`bot_dicts_in_realm_cache_key`.
For page_params, we get the new field
via `get_owned_bot_dicts`.
For realm_bot/add, we modified
`created_bot_event`.
For realm_bot/update, we modified
`do_change_bot_owner`.
On the JS side, we no longer
look up the bot's owner directly in
`server_events_dispatch` when we get
a realm_bot/update event. Instead, we
delegate that job to `bot_data.js`.
I modified the tests accordingly.
This fixes the fact that we update the bot table
with the owner's email instead of a name, but as
the TODO indicates, this is not a full fix, since
I don't linkify the owner name.
To do the full fix properly, I want to make it
so that the `list_render` widgets can just be given
an id of a row to update, and that's coming soon,
hopefully. If I get sidetracked, the ugly ways to
do this are one of the following:
- just duplicate what the template does in
jQuery
- extract a partial to draw the bot owner link
The full solution here should fix ALL the live
update code in `update_user_data`, which is why
I'm hesitant to add any interim complexity.
This is just a lexical change. We are going
to use some shared code soon that we don't want
to export, and if `update_user_data()` is
declared too early in the file, then the function
we extract will either need to be exported (to
satisy the linter) or placed far away from its
most natural siblings.
We will use this for a patch to the live-update
code, and it also de-clutters `bot_info`.
This function could plausibly live in `people.js`,
but it's not worth the indirection at this time,
and, also, one of the upcoming callers to the
function will only temporarily need it.
There's a little bit of a chicken/egg problem
going on:
- It's hard to have nice system-wide
APIs related to bots while bot settings
are still in flux.
- It's hard to clean up the bot settings
code while the system-wide API is still
kinda messy.
But I'm making slow progress on that front.