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.
In a refactor last fall, we changed `set_message_booleans` to mutate
state (specifically, destroying msg.flags in favor of setting
properties like `msg.unread`). This was fine for most code paths, but
the maybe_add_narrowed_messages code path called
`message_store.add_message_metadata` twice (once after talking to the
server to find out whether the messages go into the current narrow),
and so when we extracted set_message_booleans from that, the second
call didn't properly short-circuit.
We fix this by just removing the second call, and also add a comment
warning about the add_message_metadata call there as being dangerous.
Fixes#8184.
Instead of treating false differently from undefined, our
function is now a regular boolean function, and we limit our
code comments to the one corner case where the true/false
decision is kind of arbitrary and possibly confusing.
The buddy list never includes yourself nor bots, so we
remove the special case handling for those situations.
If we were to put bots or the current user back in the list,
I'm not convinced the old logic was what we'd want in either
case going forward.
For example, we might want to fade bots that aren't subscribed
to public streams, since they might otherwise confuse people,
but then again they would receive messages. And then "yourself"
is a recipient in the technical sense but they're kinda
not and either way it doesn't provide much signal either way.
We don't need to special-case the stream cog handler when we
handle the click event for the surrounding header. The browser
will fire the event for the cog first, which stops propagation.
The new list_cursor class is more generic and saves the state
of your cursor across redraws.
Note that we no longer cycle from bottom to top or vice versa.
The node test code that was removed here was kind of complex
and didn't actually assert useful things after calling methods.
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.
The blur_search() function was removed in this commit:
See da06832837
We now no longer attempt to call it. It's not completely clear
to me what this did before, but we are rewriting a lot of the
keyboard navigation for search anyway.
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.
A recent change filtered out offline users from the buddy list
whenever the list size would otherwise exceed 600.
This commit reverts half that change--we can now show 600+ users
again, but only when searching.
This is because we cover the case of `realm_allow_message_editing` by
`realm_msg_edit_limit_setting` after the conversion into dropdown.
This commit also contains a minor variable renaming.
Add realm setting to set time limit for message deleitng.
Set default value of message_content_delete_limit_seconds
to 600 seconds(10 min).
Thanks to Shubham Dhama for rebasing and reworking this. Some final
edits also done by Tim Abbott.
Fixes#7344.
This fixes an issue where with very tall messages (more than about a
screen in height), one would end up scrolled to the bottom of the
message if you clicked on it, which usually felt annoying.
Fixes#8941.
static/styles/scss/portico.scss is now compiled by webpack
and supports SCSS syntax.
Changed the server-side templates to render the portico-styles
bundle instead of directly requiring the portico stylesheet. This
allows webpack to handle stylesheet compilation and minification.
We use the mini-css-extract-plugin to extract out css from the
includes in webpack and let webpacks production mode handle
minification. Currently we're not able to use it for dev mode
because it does not support HMR so we use style-loader instead.
Once the plugin supports HMR we can go on to use it for both
dev and prod.
The downside of this is that when reloading pages in the development
environment, there's an annoying flash of unstyled content :(.
It is now possible to make a change in any of the styles included
by static/styles/scss/portico.scss and see the code reload live
in the browser. This is because style-loader which we currently
use has the module.accept code built-in.
Previously, we did a rerender without first re-computing which
messages were muted; this was incorrect, because whether a message is
muted can change if the topic changes.
Fixes#9241.
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).
This is a slight change in the responsive design, moving the 975px
cutoff to 1025px; the main effect is that for windows that just barely
had a right sidebar, we now hide the ride sidebar. This is pretty
beneficial for the user experience specifically in the common size of
1024px, where that sidebar was making things feel a bit too
constrained.
This function replaces part of compose_fade.would_receive_message(),
which has a real janky interface of returning true, false, or
undefined.
We don't need to couple the semantics of compose fading to whether
we help subscribe a mentioned user. They're mostly similar, but they
will probably diverge for things like bots, and the coupling makes
it difficult to do email -> user_id conversions.
One thing that changes here is that we get the stream name from
compose_state, instead of compose_fade.focused_recipient. The
compose_fade code uses focused_recipient for kind of complicated
reasons that don't concern us here.
Some labels like one for `translate_emoticons` which contains HTML
get escaped because of use of `{{ label }}` syntax, which escapes
the string for XSS security purpose but since labels aren't any
threat to any such security cases, we can use triple curly brackets
`{{{ label }}}` syntax.
Fixes: #9231.
A common path is a new user goes to realm_uri, which redirects to
realm_uri/login, and clicks the google auth button thinking it is a
registration button.
This commit just changes the wording on the page they land on to be
friendlier for that use case.
This coverts the "checkbox" for `realm_allow_message_editing` and
"input" for `realm_message_content_edit_limit_seconds` into a
dropdown with the option for custom time limit option.
Upgrade webpack to latest version at the time of authoring. This
involves upgrading webpack version and its loaders to compatible
versions. It also involved editing tools/webpack to use the
executable for webpack-cli instead because of a change in how the
webpack package wants you to handle shell execution.
It also fixes the confugration for TypeScript in the webpack config
as that was previously broken. Including TypeScript files in JS
files compiled by webpack now works.
If the browser is in the progress of reloading when it finishes
fetching some messages, it's not really a bug, and we shouldn't report
it as such.
This should help make Zulip's browser error reporting less spammy.
If you visit a narrow that has unread messages on it that aren't part
of the home view (e.g. in a muted stream), then we were never calling
`message_util.do_unread_count_updates`, and more importantly,
`unread.process_loaded_messages` on those messages. As a result, they
would be unread, and moving the cursor over them would never mark
those messages as read (which was visible through the little green
marker never disappearing).
I can't tell whether this fixes#8042 and/or #8236; neither of them
exactly fits the description of this issue unless the PM threads in
question were muted or something, but this does feel related.