We want to avoid doing too much setup for the info overlay widget
during initialization, since we don't really need it, and side
effects like focusing a modal can cause hard-to-detect
glitches for other features.
In our toggler component (the thing that handles tabs in things
like our markdown/search help, settings/org, etc.), we have
a callback mechanism when you switch to the tab. We were
being tricky and only calling it when the tab changed.
It turns out it's better to just always call the callback,
since these things are often in modals that open and close,
and if you open a modal for the second time, you want to do
the callback task for whichever setting you're going to.
There was actually kind of a nasty bug with this, where the
keyboard handling in the keyboard-help modal worked fine the
first time you opened it, but then it didn't work the second
time (if you focused some other element in the interim), and
it was due to not re-setting the focus to the inner modal
because we weren't calling the callback.
Of course, there are pitfalls in calling the same callbacks
twice, but our callbacks should generally be idempotent
for other reasons.
We want the Botserver to not only work with the
botserverrc, but also with a zuliprc of an outgoing
webhook. Because the Botserver uses the outgoing
webhook token for authentication, we need to include
it in the zuliprc for outgoing webhooks.
This is preparation for an upcoming refactoring where we pass a bot
ID, not the email/api_key, into the zuliprc generation functions in
the bots code path.
`format_as_suggestion` formats a list of operators into a
suggestion using the Filter.describe and Filter.unparse methods.
This change aims to increase readability.
In admin UI for creating new choice type of custom field, the behavior
of trash icon for removing choice field is buggy.
When admin clicks on trash icon it disappears, but the row does not
and admin end up being unable to create the field.
Fix this by selecting proper element to find and delete choice row.
These two slash commands now use zcommand to talk to
the server, so we have no Message overhead, and if you're
on a stream, you no longer spam people by accident.
The commands now also give reasonable messages
if you are already in the mode you ask for.
It should be noted that by moving these commands out of
widget.py, they are no longer behind the ALLOW_SUB_MESSAGES
setting guard.
This adds a /ping command that will be useful for users
to see what the round trip to the Zulip server is (including
only a tiny bit of actual server time to basically give a
200).
It also introduce the "/zcommand" endpoint and zcommand.js
module.
We had a significant amount of code for handling what seemed to be 2
cases, but which were really just a single case (if we are trying to
narrow to a specific message ID, and we end up landing on it, restore
the previous offset; with the special case that the previous offset
might be passed in from the previous call).
This cleanup also fixes a very minor bug, where our background
auto-reload (`reload.initiate({immediate: true});` in the JS console)
would incorrectly reset the pointer position to match the a near:
message ID if that was present in the narrow.
This commit fixes a couple regression related to narrowing.
For a long time we've had bugs where we too aggressively
preserve the currrent selection on topic -> stream
re-narrows ("s" key) even when the wider narrow may
have unread messages before the selection.
Also, we recently introduced a bug so that when you used
a link from the "copy link to conversation" (aka a "near"
query), it would advance you to your first unread message
despite the near:999 specifier. (The code would work for
subsequent "near" queries once you had fetched some of
your original messages).
This commit introduces a new data structure called id_info (replacing
the select_strategy data structure) in various functions and uses that
to track all the ids of relevance.
Significantly rewritten by tabbott to handle a few extra corner cases,
and add a ton of comments explaining why it works the way it does.
Fixes#2091.
Fixes#9606.
When admin user create new private stream, widget for changing privacy
of stream doesn't render. Because we render subscription-settings
template partially on subscription-add event, so this case wasn't
handled.
Fixes#9469
Previously weren't registering modal properly, which gets fixed by
using open_modal. It further fixes closing of modal by using escape
and positioning of modal.
Fixes: #9590.
This directly prevents a traceback when submessage events
arrive in the wrong order. This was probably a symptom
of not updating message.submessages for not-yet-widgeted
messages, which was fixed in an earlier commit, but we
want defensive code in case of races or other glitches, and
it's not the end of the world is somebody sees partial
survey results due to some corner case.
The "if" condition that was removed in this commit
is no longer needed, since the called code now
handles the cannot-apply-locally use case. (We
wanted the called functions to be defensive, so
they already were effectively handling the conditions
anyway, and recent commits has them returning
appropriate values and doing the right things.)
This commit makes it so that any query for
which we do a local filter leads to us
examining the full list of unread message
ids in our cache to find a potentially
unread message that passes the filter. This
can often allow us to more immediately
jump to a new narrow with an appropriately
selected message.
Fixes#9319
We want to be able to call get_first_unread_info() even
if we cannot apply a search locally. It was returning
the correct value before, but this change removes a
blueslip warning that will allow our callers to remove
some guard code in a subsequent commit.
These styles aren't great, but they're hopefully
better than none at all and inspire a follow up
commit from somebody else (so it starts to look
like a "real" feature instead of feeling completely
proof-of-concept).
We want to update message.submessages for new events, even
though our couple of widgets (poll/tictactoe) that can process
"update" events currently just apply events as "deltas"
to their current data.
This does fix a subtle issue where you may get incoming
events for a message that the client knows about but which
it hasn't yet activated as a widget. Up until now,
we've rarely seen the bug that's fixed here, since it's
usually the case that as soon as we receive a message, we
widgetize it right away.
The user can now specify the value while creating a stream.
An admin can later change it via `Change stream permissions`
modal. Add is_announcement_only to subscription type text.
For some reason in my original version I was sending both
content and data to the client for submessage events,
where data === JSON.parse(content). There's no reason
to not just let the client parse it, since the client
already does it for data that comes on the original
message, and since we might eventually have non-JSON
payloads.
The server still continues to validate that the payload
is JSON, and the client will blueslip if the server
regressses and sends bad JSON for some reason.
With this commit, we change how we deal with translation for strings.
Previously we used to fetch the translations data after loading which
created a lot of unpleasant race bugs.
So we changed this to use the `translation_data` sent in `page_params`
which is available at load time. The previous fetching can be useful if
we want to change the string to the changed language without reloading
the page but since we ask the user to reload the page after changing
the default language so fetching after loading isn't useful for us and
hence we can add resource only once.
Ultimately, we can remove the i18next plugins too. We leave the logic
for clearing local storage, patched to fully clear it.
Fixes: #9087.
Fixes#3380.
The blueslip warning mentioned in #3380 were from paths ending at
people.email_list_to_user_ids_string. Some additional blueslip warnings
were raised after using that function.
Although we can put a validation check somewhere in the call stack of
people.email_list_to_user_ids_string, this function itself is used to
validate the operand by the higher order functions, so it wouldn't make
sense to put a validation check before that. Instead, removing the
blueslip warning altogether was chosen.
people.email_list_to_user_ids_string was replaced by
people.reply_to_to_user_ids_string which is a blueslip-free version
of the same. Other blueslip warnings were removed.
In 1f72647a5a I accidentally
flipped a condition that made the down key "recenter" on
the "normal" case, not in the "is-at-end" case.
This commit undoes that regression, which probably only
affected czo for a weekend, and makes the logic a bit
more clear.
If atleast one of the private_message_recipients is invalid, compose
box will not be opened.
Thanks to Aastha Gupta <aastha.gupta4104@gmail.com> for some preliminary
work on this.
First, it's silly that these weren't in common.css in the first place,
since that meant these were a bunch of duplicated code, but
additionally, that meant that these weren't available on the
`/activity` page (or other pages that don't include the portico styles).
Fixes#9561.
In user profile popover, date type of custom fields values are
not showing in correct format as "date_joined" value.
Fix this using moment.js to render date type of fields
in correct format.
We've had rare and hard-to-track-down glitches with our
old implementation for going up and down in the message
list, which was using jQuery selectors.
We now just use MessageListData under the hood to find
our next id.
The Botserver uses section headers in the flaskbotrc to
determine which bot to run. Silently setting the section
headers to a bot's username is confusing and makes it
harder for Botserver users to figure out how to get the
Botserver to run the bots they want. This commit empties
all flaskbotrc section headers and thus makes the assignment
of bots explicit and mandatory.
Previously, the Botserver determined which bot to run for an
outgoing webhook by dispatching on a different URL endpoint
for each bot. Now, instead, the Botserver determines which bot
to run by the section header of the bot in the flaskbotrc.
This commit makes the frontend provide the new flaskbotrc
and updates the setup steps for the Botserver in the docs.
Fixes#6515.
New suggestions for `sender:King ha` will respect spaces and the new
suggestion will be `Sent by King Hamlet <email>` instead of `Sent by King,
search for ha`. But if first term of sender operand is a valid user email,
tokens will be seperated by spaces. e.g `sender:hamlet@zulip.com abc`
will show `Sent by King Hamlet <email>, search for abc`.
We had debug code that was reaching into msg_list._items when
it could use msg_list.all_messages() instead.
When we split out MessageListData, using _items started
breaking this code.
This should make it easier for us to iterate on a less-dense Zulip.
We create two classes on body, less_dense_mode and more_dense_mode, so
that it's easy as we refactor to separate the two concepts from things
like colors that are independent.
A "zform" knows how to render data that follows our
schema for widget messages with form elements like
buttons and choices.
This code won't be triggered until a subsequent
server-side commit takes widget_content from
API callers such as the trivial chat bot and
creates submessages for us.
This starts the concept of a schema checker, similar to
zerver/lib/validator.py on the server. We can use this
to validate incoming data. Our server should filter most
of our incoming data, but it's useful to have client-side
checking to defend against things like upgrade
regressions (i.e. what if we change the name of the field
on the server side without updating all client uses).
We should probably have a try/catch in MessageListView itself
too, for post-processing kind of stuff, but we want to make
this new module defensive in its own right.
This is a trial to have the first reply hotspot in the bottom
whitespace (and stick there until "Got it!" is pressed).
Tweaked by tabbott to clean it up a bit. Still needs more work on the
visuals.
This should significantly improve the user experience for creating
additional accounts on zulipchat.com.
Currently, disabled in production pending some work on visual styling.
We can have this scenario:
- somebody else creates a widget-ready message
- message arrives in storage
- (message is not yet in view, so no message.widget)
- new submessage event arrives
We want to just ignore submessage events in that case.
(There's a more complete fix coming for this scenario, where
we at least update message.submessages for the eventuality
that we do render the message later.)
This commit improves the output that blueslip produces while
showing error stack traces on the front-end. This is done by
using a library called error-stack-parser to format the stack
traces.
This commit also edits the webpack config to use a different
devtool setting since the previous one did not support sourcemaps
within stack traces. It also removes a plugin that was obviated
by this change.
Fixes#9492.
`is` operator uses predefined categories. This commit
displays an invalid operand message if the operand does not fall into
any of these categories and the `is` operator is not at the last.
e.g. `is:abc sender:abc@zulipchat.com` will have `invalid abc operand
for has operator, sent by abc@zulipchat.com` as a prefix for all its
suggestions.
Fixes#9492.
Default suggestion e.g `abc messages` as a suggestion for `is:abc`
is not shown in a new suggestion. But if the is operator is already
present before any other operator, the default message text will be
used. e.g `is:abc sender:abc@zulipchat.com` will have all the suggestions
with the prefix `abc messages, sent by abc@zulipchat.com`.
`get_containing_suggestions` was used to get the operand suggestions
for the `has` operator. `get_special_filter_suggestions` is now used
to get both the operand and operator suggestions for `has`.
Partially fixes#9461.
Negated suggestion for both operand and operators are handle in
get_special_filter_suggestions. A bug is get_operator_suggestions
causing the removal of `-` symbol from the operand was also fixed.
Now that we've moved it into a bulleted set of options inside a modal,
there's no good reason to have separate variables for the corner cases
around who can manage a stream.
Our logic for stream_has_topics never accounted for
us creating essentially "empty" stream buckets that
don't have topics, but we recently added some code
related to unread counts that violated the original
assumptions of the code.
Now we check deeper into the stream bucket to find
actual topics.
This bug manifested in the left sidebar where users
were seeing streams as recently active just because
some muted topics had unread counts, when in fact
the stream was inactive for practical purposes.
Having submessages will become common enough that the
info message here is too spammy, and there are other
ways to observe incoming submessages if you're doing dev
debugging, which this was originally written for.
We could get submessage events for messages that weren't
in our message store if somebody played with a widget
that was on an "old" message for somebody else.
Dropdown element for outgoing interface type was not showing correct
value, cause the way default value was set to dropdown was incorrect
(it should have been setting the selected parameter on the selected
option if it were going to be selected via the template code).
Fixes#9419.
This adds a tour of Zulip to the bottom of the homepage.
In order to get the carousel nave, we use Bootstrap 2 from a CDN on
this page; this isn't ideal in the medium term, but upgrading
Bootstrap across the project is too much work for now.
It also updated all the svg to be optmized per new version.
This new version, since the last version contains bug fixes and improvement.
Refs: https://github.com/svg/svgo/releases
We ask our users to enable Snapshot notifications in Zulip via
Slack! But our Slack integration isn't exactly super robust and
I checked and our librato implementation isn't super smart about
handling snapshot payloads that come in via Slack.
Overall, this seems like a very poor solution, asking the user
to set up Slack in order to get the notifications in Zulip. So, I
thought we should get rid of at least the docs that suggest doing
this.
I also read librato/view.py and it wasn't clear to me how Slack
is supposed to act as an intermediate service here in a reliable
manner, which is another reason to not advertise this.
Fixes#9373.
`not_subscribed` warning is not shown for bots on either private or public
streams. Some of the bots have an interface such that they receive the
message mentioning them even if on a private stream where they are not
subscribed.
We use "Everyone" for the button labels already.
Soon we'll support "Everyone" meaning either the installation or the realm,
depending on the URL route used to access the stats.
When suggesting operators to chose, category wise suggestions are
shown instead of a single default suggestion. e.g suggestions for
all the categories of has operator will be show instead of `Messages
with one or more` suggestion which did not make sense.
`has` operator uses predefined categories. This commit displays an
invalid operand message if the operand does not fall in to any of
these categories and the `has` operator is not at the last.
e.g. `has:abc sender:abc@zulipchat.com` will have `invalid abc
operand for has operator, sent by abc@zulipchat.com` as a prefix for
all its suggestions.
Fixes#9384.
Default suggestion e.g `messages with one or more abc` as a suggestion
for `has:abc` is not shown in a new suggestion. But if the has operator
is already present before any other operator, the default message text
will be used. e.g `has:abc sender:abc@zulipchat.com` will have all the
suggestions with the prefix `messages with one or more abc, sent by
abc@zulipchat.com`.
This commit lays the foundation to handle submessages for
plugin widgets. Right now it just logs events, but subsequent
commits will add widget functionality.
Partially fixes#4708.
Implements a first version (v1) for the feature. The next step would be
to allow admins to toggle `is_announcement_only` in the UI.
Fixes#9182. Adds a link to the keyboard shortcuts popup at the
bottom-right corner of the right sidebar. A tooltip saying
`Keyboard Shortcuts(?)` has been added to the icon. The icon is
positioned using `position: fixed`.
We now initialize most modules in ui_init.js, which
isn't the perfect place to do it, but at least now
we have a mostly consolidated entry point.
All the new foo.initialize() methods introduced in
this module run the same order relative to each
other as before this commit. (I did some console
logging with a hacked version of the program to
get the order right.) They happen a bit later than
before, though.
A couple modules still have the `$(function() {`
idiom for miscellaneous reasons:
archive - is a different bundle
common - used elsewhere
list_render - non-standard code style
scroll_bar - no exports
setup - probably special?
socket - $(function () is nested!
transmit - coupled to socket
translations - i18n is a bigger problem
ui_init - this bootstraps everything
We now work with MessageListData objects while populating
data from local narrows, before actually making the
wrapper MessageList object.
This change will simplify unit testing (less view stuff
to fake out) in certain situations.
It will also allow us to eliminate the delay_render flag.
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.
We now only preserve the offset for the previous
selection (pre-narrow) if that is still the id
we want selected after calling maybe_add_local_messages.
Right not this does not change any behavior, but
upcoming changes to maybe_add_local_messages will
change the selected id to the first unread message
in certain circumstances, in which case preserving
the offset will possibly be confusing, since you're
not on the same message.
We will need this for cases where the topic names in
unread.js are a superset of the names we got from messages.
It's important to pass in a dict of existing dicts to avoid
expensive max() calls to get the max ids of topics (otherwise
the plan would have been to merge the lists in the caller).
Whenever custom fields templates get rendered within user account
settings, on-change event listener wasn't get created. Cause
event listener wasn't set properly.
When org admin tries to change only bots name of no-owner-bot,
It update bots name but returns error, "No such bot owner".
Cause frontend pass `null` value in `bot-owner`.
Template was rendering undefined value of `bot_id` instead of
`user_id`.
Fix this by replacing `bot_id` with `user_id` and changing
template data variable to `data-user-id` to avoid
future confusion.
Fixes#9305.
Empty operators are not allowed while parsing narrowing URLs.
`parse_narrow` stops parsing further if it encounters an empty string
operator.
If we find unread messages for a sender, we will
try to render locally narrow for sender searches.
Note that our current implementation brute forces
through all the unread ids. We can improve this,
although it's not really a bottleneck until we
also support buckets for general filtering.
We now try harder to find the first unread message in an
upcoming narrow, which has the user-visible effect that we
select the unread message before waiting for search results.
Before this change, we only applied this logic to searches
that were things like exactly stream/topic or exactly is-private.
Now we will also handle things like stream/topic/sender. For
the stream/topic piece we look up candidate unread ids using
the steam/topic buckets in unread.js, but then we still filter
those messages by stream/topic/sender as we look for the first
unread id.
I renamed get_unread_ids() to _possible_unread_message_ids().
The name is deliberately verbose, since we're about
to make it have kind of unusual semantics that only make sense
for its one caller.
The outside code will continue to call get_first_unread_info().
In the tests I wrap this function in a wrapper with the more
pleasant name of "candidate_ids", since in the test there's
less worry about unwittingly exposing a kind of janky function.
This is setting up for a subsequent commit to have a smaller
diff. The current ordering of the code blocks doesn't matter,
since only one of the conditions will be true, so this won't
change any behavior. (Later commits will make the order matter.)
We don't reference this anymore (it was only ever used by the Dropbox
integration, which was hardcoded-off for years before being removed in
e6833b6427)
We will use this to find the first id from a list of
message ids that matches a filter. (This will help us
during narrowing to determine whether we have at least
one good message locally, so that we can render something
useful before waiting for the server.)
This new API replaces some more specific functions that were
only recently introduced:
is_stream_only
is_stream_topic_only
is_pm_with_only
is_for_only
We use the deterministically sorted "term_type" values for
matching. (Notably "stream" will come before "topic".)
This uses scss mixins, this are functions you can pass parameter in it and
return css/scss. It made repeating vendored transistion, and user-select property
more easier to use with less repetation. This also includes a scss file called reuseable_components.scss
which can be used anywhere else.
The app icons (web/mobile/desktop) got all squished together when
they broke to a new line in smaller windows. They now have better
spacing and all break at the same time.
The integration widgets on the homepage had a weird-looking white
border. That border has now been updated to match the better-
looking border on the integrations page.
The "Short/Long Text" option for custom profile fields wasn't properly
capitalized (i.e. "Text" should have been all lowercase), and also
wasn't properly tagged for translation.
For the sake of consistency, the change to proper capitalization has
also been applied to the models and any tests involving this feature.
Due to a bug in Django, it complained about the models having changed
and thus not being consistent with the migrations. That isn't actually
true (since the database stores the numeric values for each key), but
the migrations have been modified to avoid this error. This does not
affect the migrations' behaviour in any way.
This works for other text boxes as well, but compose is the main one
that one would want to do a search from.
It's possible we'll find after doing this that "getting back into
compose" becomes a problem, but I guess we can handle that when the
time comes.
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.
This makes a few important cleanup changes:
* Using the more standard data-field-id name for the ID value.
* Using $(e.target).closest() rather than `.parent`, which is more
robust to future changes in markup.
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.
For a commit that was just merged I had the "back-out" case
at the wrong nesting level. It was a pretty obscure failure
scenario that never came up in practice, but basically if you
were starting at a message that was not in your narrow, but
we did have some messages in your narrow, we would try to
go near the old message instead of talking to the server to
find the next unread message in that narrow.
Barring a few minor edge cases, when we now do a narrow
that is based on a sidebar-like search (e.g. stream/topic,
no extra conditions), we now go directly to either the
first unread message we know about locally or the last
message if we're all caught up.
We of course used to do this in master until recently; this behavior
was broken by Tim's narrowing refactor branch (ending with
26ac1d237b) which moved us to always
using the select_first_unread flag, by default (fixing issues where if
you clicked around while your pointer was behind, you'd land in the
wrong place).
We now have arguably the best of both worlds:
* The pointer is not considered when computing narrowing positioning
* We only go to the server for sidebar clicks if the data isn't
available in the browser.
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.
We now do real-time sync to update the attachments UI when new
attachments are uploaded/deleted.
While we're at it, we fix the UI for the delete option to not do a
weird local echo thing.
This completes the work of a couple issues. There's still useful
performance work to do here (see the TODO), but it's a minor issue in
a rarely-used screen.
Fixes#6731.
Fixes#3710.
We send add events on upload, update events when sending a message
referencing it, and delete updates on removal.
This should make it possible to do real-time sync for the attachments
UI.
Based in part on work by Aastha Gupta.
We only use this data in a rarely-used settings screen, and it can be
large after years of posting screenshots.
So optimize the performance of / by just loading these data when we
actually visit the page.
This saves about 300ms of runtime for loading the home view for my
user account on chat.zulip.org.
This commit moves the stylesheets under the archive bundle in
the Django pipeline to being compiled by webpack instead. It
also removes a remaining call to a portico stylesheet that no
longer exists.
This commit transitions landing-page.css from the Django pipeline
to being compiled by webpack as landing-page.scss under the
'landing-page' and 'integration' bundles.
Even though starred messages are never unread, it's useful
for us to have helper functions for them.
This change makes it so that clicking on "Starred Messages"
takes you to the last read message immediately, without a
server delay.
This fixes some minor glitches with buttons:
* Movement of the organization-settings-parent block on the
appearance of widgets.
* Large and odd look of save button.
* Use of fadeIn and fadeOut rather than changing opacity as
opacity don't actually remove them.
If notifications_stream is private and the current user has never been
subscribed, then we would throw an exception when trying to look up
notifications_stream. In this situation, we should just treat it like
the stream doesn't exist for the purposes of this user.
This is purely to make it easier to read narrow.activate()
without having to page past lots of unnecessary detail when
you're trying to understand things like how we set the
selection.
The maybe_select_closest helper, when first introduced, was
tiny and close to its callers.
As it's grown, it's become kind of a big hurdle to reading
narrow.activate(), because it's out of chronological order
and it's hard to tell at a glance which variables it's closing
on.
Now we just move it out to module scope.
It's mostly moving code, with these minor changes:
* we pass in opts for the old closure vars
* we rename then_select_offset -> select_offset
* we early-exit on empty lists
We replace these variables in narrow.activate:
then_select_id (int w/-1 as a sentinel)
select_first_unread (boolean)
The main goal here is to get away from the boolean, since
we are about to introduce a third select strategy.
The new var is select_strategy and it has a union
type with these flavors:
"exact" (was select_first_unread === false)
"first_unread" (was select_first_unread === true)
The new flavor will be something like "last_id".
Eliminating then_select_id is also nice, since the -1
sentinel value could be a pitfall, and it's semantically
cleaner to encapsulate behind a check for
select_strategy.flavor.
We use an IIFE (immediately invoked function expression)
to fetch messages. This will allow us to introduce some
local vars in a subsequent commit without creating an ugly
diff and without cluttering an already crowded namespace.
This cleans up a subsequent diff. Within the context of
`maybe_select_closest`, there's only one `msg_id` we care about,
so the more convoluted name `then_select_id` makes much less
sense than it does in the enclosing scope, and it will make
even less sense after some future changes.
There's also some cosmetic cleanup here.
When we are deciding whether to preserve scroll position, we
mainly care that then_select_offset is set to a value. If
we had no intention of preserving scroll offset, we would have
never bothered to set it. The check for !select_first_unread
is always redundant, as verified by lots of clicking around
with some print debugging. And it's a brittle check,
because it couples the decision of scrolling destination to
the mechanism by which we decide our selection. While those
things are closely related, it's possible in the future that
we'll decide to advance to an unread message and still want
to set then_select_offset, but we might forget to mutate
select_first_unread.
Long story short, the code is simpler and safer now.
We move the var declaration of then_select_offset closer to
where it gets calculated, and we avoid code duplication in
calling current_msg_list.get_row().
Even when then_select_id has the sentinel value of -1, we were
trying to look it up in our message_list.all object. This would
have returned undefined, which is fine, but it's more explicit
to just bypass the check.
This commit transitions all styles in app.css in the Django pipeline
to being compiled by webpack in an app-styles bundle, and renames the
various files to now be processed as SCSS.
To implement this transition, we move the old CSS file refernces in
settings.py and replace them with a bundle declared in
`webpack.assets.json` and includedn in the index.html template
Tweaked by tabbott to keep the list of files in `app.css` in
`webpack.assets.json`, and to preserve the ordering from the old
`settings.py`.
This is done because the current column-left and column-right were
actually just floating left and right and making use of float-left
and float-right makes more sense. This also helps with the upcoming
public archives feature which will try to include portico content
with main app content.
This mostly sets up the next commit. The two conditions here
are both inexpensive to check, but we want to bypass an upcoming
expensive operation if can_apply_locally() returns false.
With past logic, on fast upload progress bar don't appears because
uploadFinished is called as soon as upload is finished so
progress bar get disappeared. To make these hiding of progress bar
smooth we set setTimeout for every hiding of progress bar as well
as complete status element.
Here `file.lastModified` is unique for each upload so it is used
to track each upload individually.
Also, we have used `uploadStarted` function because it is
called for each file during an upload.
Fixes: #9068.
Previous logic was little buggy, as many time there can be considerable
difference between uploadFinished and progressUpdated as progressUpdated
can finish much earlier(on a slow connection) and the "uploaded file"
markdown text is inserted with some delay.
It is also a preliminary commit for making each progress bar independent
as currently progressUpdated may close upload_bar even after only
one file out of many files is uploaded.
We were missing it but it is added in the upstream, so just added it
at the appropriate place in plugin code(in the upstream there is some
code refactoring but this seems to be the most appropriate place).
This commit removes the need for portico.css to be generated
by the Django pipeline and makes the error page use the css
file compiled by webpack instead.
This takes advantage of the new function narrow_state.stream_id().
We now assume the incoming stream_id is a valid stream_id, so we
no longer need to test some of the error checking. (It's possible that
the incoming stream_id may no longer be for a stream you subscribe
to, but the nice benefit of working more in "id space" is that if
it doesn't match the narrow's stream id, we know false is a safe
return value.)
After adding a newly created stream to the top of the stream list,
call to actually_filter_streams in stream_events.mark_subscribed
rerendered the filter_table and the stream list was refreshed. The
call to actually_filter streams was introduced to rerender the
subscriber list but stream_edit.rerender_subscribers_list takes care
of it already.
Fixes#9033.
Currently when admin add/remove/update custom fields, changes
are not reflected in user settings page, if settings tab
is already open. This might be rare case, but it looks like
an error when admin go to user settings page just after
updating custom fields in org settings.
Fix this by re-rendering custom fields in user settings
on custom_profile_fields event.