Prettier would do this anyway, but it’s separated out for a more
reviewable diff. Generated by ESLint.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
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 is mostly just moving code from the `activity.js`
tests, but I also now explicitly cover the "100%"
use case (i.e. all four folks in the huddle are present).
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.
This exists in all versions of the desktop app that we still support,
and will eventually let us delete a bit of annoying compatibility code
from the desktop app’s injected JavaScript.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
This flag was used to delay unread count updates while the bankruptcy
modal was visible. Now that bankrupcty is no longer a modal, we don't
need this flag at all.
We had this API:
people.add_in_realm = full-fledged user
people.add = not necessarily in realm
Now the API is this:
people.add = full-fledged user
people._add_user = internal API for cross-realm bots
and deactivated users
I think in most of our tests the distinction between
people.add() and people.add_in_realm() was just an
accident of history and didn't reflect any real intention.
And if I had to guess the intention in 99% of the cases,
folks probably thought they were just creating ordinary,
active users in the current realm.
In places where the distinction was obviously important
(because a test failed), I deactivated the user via
`people.deactivate`.
For the 'basics' test in the people test suite, I clean
up the test setup for Isaac. Before this commit I was
adding him first as a non-realm user then as a full-fledged
user, but this was contrived and confusing, and we
didn't really need it for test coverage purposes.
Explicitly stubbing i18n in 48 different files
is mostly busy work at this point, and it doesn't
provide much signal, since often it's invoked
only to satisfy transitive dependencies.
We now treat util like a leaf module and
use "require" to import it everywhere it's used.
An earlier version of this commit moved
util into our "shared" library, but we
decided to wait on that. Once we're ready
to do that, we should only need to do a
simple search/replace on various
require/zrequire statements plus a small
tweak to one of the custom linter checks.
It turns out we don't really need util.js
for our most immediate code-sharing goal,
which is to reuse our markdown code on
mobile. There's a little bit of cleanup
still remaining to break the dependency,
but it's minor.
The util module still calls the global
blueslip module in one place, but that
code is about to be removed in the next
few commits.
I am pretty confident that once we start
sharing things like the typeahead code
more aggressively, we'll start having
dependencies on util. The module is barely
more than 300 lines long, so we'll probably
just move the whole thing into shared
rather than break it apart. Also, we
can continue to nibble away at the
cruftier parts of the module.
We had a plan at some point to use this to display a phone icon or
something for users who would receive push notifications if you
messaged them. IT's not clear that feature was a good idea in any
case, but it certainly shouldn't be synced as presence data; it would
change >100x less often than the rest of presence and so should likely
be synced differently, maybe as a property on user. So it's best to
delete this prototype.
This required lots of manual testing:
- search/navigate user presence
- send PM and mention user
- pay attention to compose fade
- send stream msg and mention user
- open Private Messages in top-left and click
- test unread counts
- invite user who already has account
- search for users in search bar
- check user settings
- User Groups
- Users
- Deactivated Users
- Bots
- create a bot
- mention user groups
- send group PM then click on lower right
- view/edit/create streams
If there are still pieces of code that don't convert
ids to ints, the code should still work but report
blueslip errors.
I try to mostly convert user_ids to ints in the callers,
since often the callers are dealing with small amounts
of data, like user ids from huddles.
We now require the actual tests to explicitly
to zrequire Dict, rather than magically adding this.
In one case, the use of Dict was clearly just for
the test (not the app), so I converted that an ordinary
JS object (see timerender.js).
The compose_state.recipient field was only actually the recipient for
the message if it was a private_message_recipient (in the sense of
other code); we store the stream in compose_state.stream instead.
As a result, the name was quite confusing, resulting in the
possibility of problematic correctness bugs where code assumes this
field has a valid value for stream messages. Fix this by changing it
to compose_state.private_message_recipient for clarity.
This commit was originally automatically generated using `tools/lint
--only=eslint --fix`. It was then modified by tabbott to contain only
changes to a set of files that are unlikely to result in significant
merge conflicts with any open pull request, excluding about 20 files.
His plan is to merge the remaining changes with more precise care,
potentially involving merging parts of conflicting pull requests
before running the `eslint --fix` operation.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
The count_span element is parented by a .selectable_sidebar_block element
which is parented by the li element that the class is supposed to be added
to. Thus, use the parents() jQuery method for locating the li parent so
that the class gets added to the correct element.
Combined with work in the desktop app, this makes it possible for the
desktop app to clearly indicate to other users whether the current
user is active on the system and thus would see a desktop
notification, not just whether they are active in the current Zulip
window.
Essentially rewritten by tabbott to add unit tests and consider the
desktop app data authoritative.
After migration to an ES6 module, `suppress_unread_counts` would no
longer be mutable from outside the module.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
With perfectScrollbar, we needed to call a function from JavaScript to
enable a scrollbar on a new element, but simplebar has a much simpler
default API one can do by using data-simplebar attributes in the HTML.
So we can delete all the scrollbar creation/deletion code.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
perfect-scrollbar replaces both the appearance and the behavior of the
scrollbar, and its emulated behavior will never feel native on most
platforms. SimpleBar customizes the appearance while preserving the
native behavior.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
We no longer store handlers as an array of functions,
and instead we assume that code will only ever set up
one handler per sel/event or sel/event/child. This is
almost always a sane policy for the app itself.
We also try to improve error handling when devs write
incorrect tests.
The only tests that required changes here are the
activity tests, which were a little careless about how
data got reset between tests.
Adds possibility for users to use | as an OR-operator (besides ,)
when searching for other users.
This is a thing reasonable folks might try, and | in the thing to
search for isn't a realisitic possibility, so there's no real downside
to adding this.
Fixes#4109.
This is mostly adding markup, calling some convenient
functions in buddy_data.js, and adjusting CSS.
To make the circles update dynamically, I mostly
orchestrate this though activity.js for now. It's
possible we'll want to adjust that eventually to
happen through something like a `presence_events`
dispatcher, but that's essentially what
a good part of `activity.js` does now.
We now have a function get_user_circle_class
that returns one of these values:
"user_circle_green"
"user_circle_orange"
"user_circle_empty"
And we put that in the templates.
And then CSS renders the circle of the appropriate
color.
The unit tests now explicitly capture whether
we are rendering the correct kind of circle.
In small screen sizes, when the user presses shortcut `w` to search
for another user, the hide_all function calls in the search code path
would hide the right sidebar, immediately after opening it, making the
hotkey basically unusable.
We fix this by extracting a separate hide method that hides all true
popovers, but not the user list sidebar.
Fixes#11463.
The name `insert_user_into_list` is sort of misleading,
since we are often just redrawing the user's existing
item in the buddy list.
I chose `redraw_user` over `update_user` to emphasize
that we're just going to redraw it with whatever data
has been updated by the callers.
We are trying to carve room for a more specific
"user_status" concept, which refers to statuses
that users specifically set, like "I'm away".
So we call this function "update_presence_info",
which reflects that it's more about actual
"presence"--i.e. the user really is present
in the browser, even though the actual human
may not want to be disturbed.
For many years we have been excluding the current user
from the buddy list, since their presence is kind
of implicit, and it saves a line of real estate.
This commit removes various user-is-me checks
and puts the user back for the following reasons:
* explicit is better
* newbies will be less confused when they
can see they're actually online
* even long-time users like myself will
feel more comfortable if it's just there
* having yourself in the buddy list facilitates
things like checking your presence or sending
yourself a message
* showing "me" reinforces the meaning of the
green circle (if my circle is green and I'm
active, then others with green circles must
be active too)
* If you're literally the first user in the
realm, you can now see what the buddy list
looks like and try out the chevron menu.
The biggest tradeoff here is the opportunity cost.
For an org with more people than fit on the screen,
we put the Nth person below the fold to show "me".
I think that's fine--users can still scroll or
search.
This commit doesn't do anything special with the
current user in terms of sorting them higher in the
list or giving specific styling.
Fixes#10476
This is part of work to break some of our
nastier circular dependencies in preparation
for our es6 migration.
This commit should facilitate loading leaf-like
modules such as people.js before all of the things
that reload.js depends on.
We add a padded div to our container for the buddy
list to give scrolling the illusion that we've
rendered every list item, while still letting
the browser do the heavy lifting instead of trying
to fake it out too much.
This version of progressive scrolling lazily
renders buddy list items, but it doesn't
provide the browser with any notion of upcoming
list items, so as you scroll down and the size
of the rendered list grows, the scrollbar shows
you being too close to the bottom.
This maintains 100% coverage on buddy_list.js.
We now keep track of keys in buddy_list.js, so that
when we insert/remove items, we no longer need to
traverse all the DOM. Instead, we just find out
which position in the list we need to insert the
key in (where "key" is "user_id") and then find
the relevant DOM node directly and insert the new
HTML before that node. (And of course we still
account for the "append" case.)
There's a little more bookkeeping to make this
happen, but it should help reduce some code in
upcoming commits and pave the way toward
progressive rendering optimizations.
This commit should produce a minor speedup
for activity-related events that go through
buddy_list.insert_or_move(), since we are
not traversing the DOM to find insertion points
any more.
This is preparation for our migration of our JS pipeline to webpack,
which includes as part of the process a hack of exporting globals via
the window object.
This run_test helper sets up a convention that allows
us to give really short tracebacks for errors, and
eventually we can have more control over running
individual tests. (The latter goal has some
complications, since we often intentionally leak
setup in tests.)
When we populate the buddy list or update it for activity, we now
have buddy_data set a faded flag that is rendered in the template.
This avoids some re-rendering overhead and is on the eventual path
to having our widget be more data-oriented (and all rendering happens
"behind" the widget).
We still do direct DOM updates when the compose state changes or
when we get peer subscription events.
This introduces a generic class called list_cursor to handle the
main details of navigating the buddy list and wires it into
activity.js. It replaces some fairly complicated code that
was coupled to stream_list and used lots of jQuery.
The new code interacts with the buddy_list API instead of jQuery
directly. It also persists the key across redraws, so we don't
lose our place when a focus ping happens or we type more characters.
Note that we no longer cycle to the top when we hit the bottom, or
vice versa. Cycling can be kind of an anti-feature when you want to
just lay on the arrow keys until they hit the end.
The changes to stream_list.js here do not affect the left sidebar;
they only remove code that was used for the right sidebar.
In this cleanup I make it so that all jQuery selector references
are toward the top of the module, and we do all finds relative
to the container ('#user_presences').
This will make it easier to make a better list abstraction for
the buddy list, for things like progressive rendering.
This was a bit more than moving code. I extracted the
following things:
$widget (and three helper methods)
$input
text()
empty()
expand_column
close_widget
activity.clear_highlight
There was a minor bug before this commit, where we were inconsistent
about trimming spaces. The introduction of text() and empty() should
prevent bugs where users type the space bar into search.
This does a few things:
* removes some unnecessary setup
* puts some jQuery setup closer to where it's needed
* renames some variables
* adds an assertion about highlighting
We never make an actionable distinction between the "unknown"
presence status and the "offline" status, so we now
just use "offline" as the status for persons who don't
have recent presence records that the client knows about.
(Usually, users without presence rows have never been online,
or they have been deactivated, or they have been offline so long
that they don't show up in our date-limited queries.)
We sometimes get blueslip errors from browsers that are clearly still
attempting to reload long after they should have. These browsers can
produce a lot of unnecessary presence update exceptions.
To solve that, we start checking reload_in_progress in the presence
code path.
While we're at it, we also add some blueslip logging for the reload
code path, in case it becomes useful when debugging future issues.
This function was extracted from build_user_sidebar(). We
also slightly streamlined it to not unnecessarily call
filter() when the filter text was blank. This extraction
also eliminated the need for us to have the two-line
filter_and_sort() function.
Also, we get to 100% coverage in this commit.
We now intialize user-list-filter within activity.initialize(),
which gives us more control to set the module variable
`meta.$user_list_filter` before we build the user sidebar,
while setting up its handlers after we build the sidebar.
This adds the perfectScrollbar to the right side and theoretically
updates it any time a piece of code interacts with the sidebar and
updates the counts of users displayed in it.
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.
This commit add $.create(), which allows you to create a
jQuery object that just has a name to identify it, as opposed
to some selector or HTML fragment. It's useful for things that
are really used as stubs.
This also fixes a bunch of the existing tests to use $.create().
Before this fix, you could actually just do $('some-stub'), but
now we enforce that the input to $() looks like a valid selector
or HTML fragment, and we make some exceptions for things like
window-stub and document-stub.
Hopefully this will make it more explicit that zjquery does
not truly simulate DOM, but it instead allows you to dynamically
set what you want the results of $('foo').find(some_selector)
to be.
Before this commit, we were erroneously setting up parents
as part of add_child() calls, but it's not necessarily the
case that those children are immediate children, and therefore
the first object is not necessarily the immediate parent.