This makes the "more topics" option which appears below the list of
known topics in the left sidebar appear only when it's possible there
are actually more topics to be displayed. Two specific cases it
resolves completely include:
* Newly created realms; this widget was a common source of confusion
for new organization administrators.
* Newly created streams.
There are still some corner cases this doesn't handle, e.g. if you
just joined a private stream with protected history, but there isn't
as easy a fix for those.
Essentially rewritten by tabbott to fix code duplication and comment
extensively.
Fixes#10265.
We recently added a feature to warn users that they
may need to scroll down to view messages that they
just sent, but it was broken due to various complexities
in the rendering code path.
Now we compute it a bit more rigorously.
It requires us to pass some info about rendering up
and down the stack, which is why it's kind of a long
commit, but the bulk of the logic is in these JS files:
* message_list_view.js
* notifications.js
I choose to pass structs around instead of booleans,
because I anticipate we may eventually add more metadata
about rendering to it, plus bools are just kinda brittle.
(The exceptions are that `_maybe_autoscroll`, which
is at the bottom of the stack, just passes back a simple
boolean, and `notify_local_mixes`, also at the bottom
of the stack, just accepts a simple boolean.)
This errs on the side of warning the user, even if the
new message is partially visible.
Fixes#11138
This avoids a bunch of potential confusion around users trying to
interact with these UI in situations that don't make sense.
(E.g. showing a menu to start editing the message when the menu is
already open).
Fixes#3802.
Guest users can't subscribe themselves to streams, so we shouldn't
display the subscription button at end of stream message view.
Fixes part of #10749.
This commit prepares the frontend code to be consumed by webpack.
It is a hack: In theory, modules should be declaring and importing the
modules they depend on and the globals they expose directly.
However, that requires significant per-module work, which we don't
really want to block moving our toolchain to webpack on.
So we expose the modules by setting window.varName = varName; as
needed in the js files.
We used to have positional parameters for table_name
and filter, but we don't use them for message_list.all
and we're about to replace filter in some cases.
Passing everything in on opts is more consistent and
self-documenting in the calling code, plus lots of
unit tests can get away with passing in `{}` now
for situations where table_name does not matter.
All of our callers pass in muting_enabled, so we
remove the default value for it. And then the
collapse_messages variable doesn't have to live on
`this` as it's only being passed through down to the
view.
Before this change, the way to add messages had a lot
of ping-pong-ing between MessageList and MessageListData,
where first the data got triaged, but not actually
inserted into data structures, and then subsequent
calls would add the data and get filtered results.
Now we have a simple API for MessageListData.add_messages
that does all the data stuff up front. Having a fully
function MLD.add_messages not only makes the ML.add_messages
function about four lines shorter, it also sets us up
to easily build standalone MLD objects before making
the heavier ML objects.
This is preparation for enabling an eslint indentation configuration.
90% of these changes are just fixes for indentation errors that have
snuck into the codebase over the years; the others are more
significant reformatting to make eslint happy (that are not otherwise
actually improvements).
The one area that we do not attempt to work on here is the
"switch/case" indentation.
Most of this was straightforward.
Most functions that were grabbed verbatim and whole from
the original class still have one-line wrappers.
Many functions are just-the-data versions of functions that
remain in MessageList: see add, append, prepend, remove as
examples. In a typical pattern the MessageList code becomes
super simple:
prepend: function MessageList_prepend(messages) {
var viewable_messages = this.data.prepend(messages);
this.view.prepend(viewable_messages);
},
Two large functions had some minor surgery:
triage_messages =
top half of add_messages +
API to pass three lists back
change_message_id =
original version +
two simple callbacks to list
For the function update_muting_and_rerender(), we continue
to early-exit if this.muting_enabled is false, and we copied
that same defensive check to the new function
named update_items_for_muting(), even though it's technically
hidden from that codepath by the caller.
We had a recent regression that had kind of a funny symptom.
If somebody else edited a topic while you were in a topic
narrow, even if wasn't your topic, then your narrow would
mysteriously go empty upon the event coming to you.
The root cause of this is that when topic names change,
we often want to rerender a lot of the world due to muting.
But we want to suppress the re-render for topic narrows that
don't support the internal data structures.
This commit restores a simple guard condition that got lost
in a recent refactoring:
see 3f736c9b06
From tabbott: This is not the correct ultimate place to end up,
because if a topic-edit moves messages in or out of a topic, the new
behavior is wrong. But the bug this fixes is a lot worse than that,
and no super local change would do the right thing here.
This was only called from two places in one function, and we can just
check muting_enabled in the caller.
This refactor is important, because we might need to update muting
after other changes (specifically, message editing to move a topic to
be muted/non-muted).
If muting, topic editing, or deletion causes a narrow loses its last
message, we should show the empty-narrow notice; similarly, if
un-muting adds the first message, we should hide the notice.
We do this in `rerender()` since that's the common code path for
re-rendering the message list after events that might change this.
This has likely been broken since the very first muting
and topic editing implementations.
This reverts commit bcdd12773e.
We need to do some improvements in handling FetchStatus for initial
narrows before this will be safe to deploy in production.
If individual messages arrive before we get the latest
messages from the server, they can create gaps in rendering,
and would often be offscreen anyway, so we just ignore them.
Also adds a custom rule to eslint. Since the recommended way of extending
eslint is to create plugins as standalone npm packages, the separate rule
is published as 'eslint-plugins-empty-returns'.
Fixes#8669.
We now attach a fetch_status to message lists, so that they
can track their fetch status individually. When you go
back in a narrow and get all the older messages, we turn
off future fetches.
The narrow.js code no longer needs to orchestrate anything
here. The "home" message list won't have as many redundant
fetches after this commit, because we don't need to reset
flags every time we do `narrow.deactivate`.
And then actual narrows get a new message list every time
you narrow, so their fetch status gets reset implicitly
as part of constructing the MessageList object.
The issue has a lot of extra details, but in short, if several
messages were sent at very close to the same time, it's possible that
the event queues will receive the "new message" events out-of-order.
This, in turn, could cause `get_events` to return an incorrectly
sorted block of messages. These would then be passed into
`message_list.add_messages`, which doesn't handle that sort of
unsorted situation correctly (in short, the `self.first.id()`
comparison checks are not accurate for that situation, since we don't
update the boundaries after the first messages is processed).
The end result of this bug was that it was possible for the message
list to be out-of-order, which in turn would cause exceptions when
scrolling with the mouse.
Fixes#6948.
This refactor will facilitate making it possible to set CSS properties
on this controls span; in particular, we're hoping to disable user
selection of the whitespace in this region.
The main side effect of this refactor is that we need to add JS code
to also hide the icon-vector-pencil element, since it's now in a new
span.
This old third party library added support
for a "mousewheel" event to detect scrolling.
However, it is not compatible with jQuery 3
and is obsolete now that there is a standard
"wheel" event that accomplishes the same thing.
For the pencil icon to appear, message_unhover has to be called before
message_hover (both in ui_init.js). This happens when the mouseleave
event is triggered on a row. But, when clicking the save button and
the edit box is hidden, the mouseleave event is not triggered and
hence message_unhover not called.
Fix this with a manual mouseleave event.
Fixes: #4287.
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.
This fixes the /me elements to be display inline-block and inline
rather than display block with top and left properties.
This also fixes an unrelated issue with emoji reactions not being
able to be clicked on with /me messages.
Fixes: #4218.
We no longer let the left arrow put you into the message edit
UI for a message where you can only edit topics, since that is
just confusing to most users.
This change also improves error handling a bit, and it removes
an unnecessary call to rows.id().
Finally, it moves some logic out of message_list.js, so that we
don't have a circular dependency for this codepath.
Fixes#4259
This fixes the mobile web experience for Chrome on iOS.
Apparently, Chrome-on-iOS silently has a `viewport` module that
overrides and user-defined module by that name, causing all of our
code that accesses the viewport module to not work on that platform.
We fix this by renaming it.
We now sweep all active messages for avatar changes and update
the message items and re-render, rather than patching the
DOM. This avoids some quirks that happen when subsequent messages
get sent and we re-render previous messages out of the message
store.
Our approach here is similar to how we do full-name updates.
Note that this only works for people who are currently logged in.
Folks that log in after you may pick up the old full name from
the message. (I'll address this in a separate commit.)
When we change a stream name, we now use the stream id as the
key to find messages we need to live update. This eliminates
some possible race conditions from two users renaming a stream.
This commit introduces message_live_update.js.
The new call stack is this:
subs.update_subscription_properties
subs.update_stream_name
message_live_update.update_stream_name
message_list.update_stream_name
We should hide the empty narrow message message whenever the narrow is
not empty, but we should only select a message if non are currently
selected.
(imported from commit 22f6b0827dc84ed587a83b5d713b12c1d5d4c0a0)
Now that we no longer use tables for our message list, we can
more logically group messages together.
(imported from commit 9923a092f91a45fe3ef06f2f00e23e4e3fb62a37)
This experiment has been disabled for everyone for a while: if we
bring something like this back, it is not likely to be exactly the same,
and will be different enough to require a different implementation.
As it is, the summarization code was making a few code paths (rendering
especially) more complex, and is worth removing for simplicity's sake.
(imported from commit 6ac8cdc9f7077a5a1da01ab4268aba3db0bc43f8)
Leo and I were looking over this code and I couldn't remember what it
was doing. So after I re-derived its purpose, we figured that an
explanatory comment was in order.
(imported from commit ce984362e2b504b40f3d3586777bd73691ad5ea7)