I forgot to remove this code in a recent refactoring that copied
this code into activity.js. It should not have caused any errors,
but it's no longer needed.
From subs.js we don't redundantly try to remove an element
from ths sidebar; we just trigger the event.
In stream_list.js we continue to remove the element from
the DOM, and we also remove the widget from our internal
Dict of sidebar rows, so that if we re-subscribe, we know
we'll automatically re-build the widget from the template
and the latest data from stream_data.js.
We used to have hacky code where various functions would call
build_stream_sidebar_row() to get a jQuery object, and then they
would attach the jQuery object to the "sub" object from stream_data.js.
Now build_stream_sidebar_row() localizes the hack of attaching
a UI object to the "sub" object to just one function (and we can
clean this up in a follow-up commit).
Also, the UI object is now a JS object that can close on some useful
state information like the stream name and encapsulate how we
toggle the inactive_stream class.
Finally, we don't have build_stream_sidebar_row() needlessly append
list items to $('#stream_filters') when we know that our callers are
going to re-build the list anyway.
The code removed in this commit added pinned streams to a list
of elems, only to have them added again by the next block of code
(but more concisely). Through some strange quirk of appendTo() this
never created user-facing bugs, but you could clearly see in the console
that it was doing double work.
It used to be the case that you would get new messages for a
huddle, but the huddle wouldn't show up on your buddy list until
the every-50-seconds mass update of the buddy list.
Now we make sure to work with non-stale jQuery objects, and,
more importantly, we resize ourselves if we add new huddles.
(The resize issue arises due to some complicated heuristics
where we don't want group PMs to take up too much of the buddy
list for users who don't have many in their history.)
This fixes a bug with the group pm section of our
buddy list. It wasn't updating when you fetched
old private messages.
We had been calling activity.process_loaded_messages() as
part of message_store.do_unread_count_updates(), which was
called sometimes unnecessarily and sometime not called when
we needed to get huddle info.
Now we call it when we need it most, which is when you
click on "Private Messages".
This restyles the message_controls options to center them horizontally
while fixing them closer to the right side of the edge, along with just
replacing the edit button with a preview source button once editing is
disabled.
This moves the edit button to underneath the timestamp such that when
you hover over a message now the timestamp hides itself and the edit
button appears (if editing is allowed).
Fixes#1733 and other annoying issues with this field.
* Fixes handling of multiple stream links and invalid stream names.
* Fixes text regex so it handle hash sign the right way.
* Adds tests for these stream link cases.
Changes editibility type from NONE to FULL, and makes Save and Cancel
buttons work. Exposes a new bug, which is that changing the topic changes
the topic for the recipient row, rather than the message. See #2278.
The widget that gets built in topic_list.build_widget()
now knows how to add itself to its parent element and expose
an interface to retrieve the parent.
For cases where we are zoomed in to a stream and then go
to a different narrow (Home, PMs, etc.), we now let
topic_list.zoom_out orchestrate the removal of the topic list
instead of stream_list.zoom_out.
This will help us when we move to a world where topic_list
redraws topic lists on zoom-in/zoom-out, because we won't
waste effort rebuilding lists that are about to be removed.
The flow for topic list zooming is kind of complicated now, but
it's mostly a consequence of the way the UI works.
* stream_list tells topic_list to set up the topic list
click handlers to have callbacks to stream_list
* topic_list click handlers call to stream_list zoom methods
to hide/show all the other streams
* stream_list zoom methods call back to topic_list methods to
redraw topics as needed (this isn't happening yet, but allowing
topic_list.js to know that it's zoomed will set the stage for
this to happen in a more controlled manner)
We no longer use active_stream_name(), which was mostly a
duplicate of narrow.stream(). For nonsensical queries like
"stream:foo stream:bar" the behavior may change slightly here.
We know that we don't handle non-sensical queries particularly
well, but at least if we always go through narrow.stream(),
the behavior will be consistent.
I did test this with some sensible compound narrows, like searching
for a keyword within a stream.
After adding the ability to add stream links to messages using
the following pattern '#**stream_name**' there was a problem
with rendering this using our markdown engine because '**' means
bold text so that would render just to bold text.
To solve this I had to add regular expression in marked.js to match
that pattern and when it matches I call handleStreamLinks in echo.js
which will correctly render it to HTML.
Fixes#2218.
[tweaked by tabbott to url-encode the stream name in the URL and
adding the missing "#" in the display].
We now use stream_id as our key to rename streams, which
should prevent a few race conditions long term. (We are
still possibly contending with other events that use
stream_name as a key, so this is not perfect.)
If I try to send a message to an unknown user (which is possible
for some types of realms), then I simply ignore them during the
send codepath, so that I don't later need to patch up their attributes.
We no longer store pm_recipient_count on person objects, but we
instead use a Dict to store them. Then the new API is this:
people.get_recipient_count()
people.incr_recipient_count()
We now send dictionaries for cross-realm bots. This led to the
following changes:
* Create get_cross_realm_dicts() in actions.py.
* Rename the page_params field to cross_realm_bots.
* Fix some back end tests.
* Add cross_realm_dict to people.js.
* Call people.add for cross-realm bots (if they are not already part of the realm).
* Remove hack to add in feedback@zulip.com on the client side.
* Add people.is_cross_realm_email() and use it in compose.js.
* Remove util.string_in_list_case_insensitive().
This alert bar thing was buggy and didn't look that good, so let's
just remove it. We can always write a nicer thing advertising the
desktop app later.
Currently, message_edit.edit_message accesses elements of
message_edit_form.handlebars by a number of different means, and in a number
of different places. This commit is the first of two that standardizes it.
Previously we disabled fields in message_edit_form.handlebars that you
couldn't edit. This meant you could see the content of the field, but not
copy it. This commit marks those fields as readonly instead.
Previously,
* We displayed "(no topic)" in .message_edit_topic when there was no
topic;this commit changes that to a placeholder.
* We showed the .message_edit_topic_propagate dropdown when the user
cleared .message_edit_topic, despite the fact that one cannot save
or propagate an empty topic. This commit fixes the behavior.
Fixes#1273.
This change makes most of the logic on set_count() live
on our per-stream topic list widget. We can find the
jQuery object directly now rather than using the
complicated iterate_to_find() method.
We don't want to prepend new subscribers to our list of
subscribers in the settings page when they hit enter; we
want to wait till we get the event from the server.
This is a fairly new regression that was added when we
live-updated peer subscriber changes.
This fixes and issue where the change_stream_privacy template had its
own duplicate copy of the data-stream-name attribute, which wasn't
updated when streams were renamed.
Fixes#2016.
This also brought along:
iterate_to_find (copied, see large comment explaining why)
activate_topic (extracted from a one-liner)
set_count (formerly stream_list.set_subject_count)
For get_topic_filter_li, we now pass in stream_li instead of
stream to decouple parent/child responsibilities between the
components.
Also, I made some s/subject/topic/ fixes.
This creates the new topic_list.js module, and the first
function that we extract is topic_list.update_count_in_dom().
This function needed to be decoupled from some non-topic-list
stuff which was overly complicated.
I make server_events slimmer by not handling a specific
property when subs.update_subscription_properties() should
do all the dispatching (and mostly did).
And then since update_subscription_properties() has
a "sub" already, I can call directly to stream_list code
and remove a function from subs.js. Since I lose the
wrapper function in subs.js, I rename the stream_list
function as part of this commit.
The only code that gets slightly heavier here is that
we have two lines in the 'pin_to_top' case instead of one.
All of the eventual callers to prepend_subscribers()
and format_member_list_elem() call people.get_by_email()
anyway, so now we do it one place. The one exception
was using page_params.fullname, which is awkwardly
different than what we call that variable elsewhere
(fullname vs. full_name).
Previously, all of the callers of message_edit.save() would check if
it returned true, and if so, call message_edit.end(). This resulted
in various bugs in the past, so we switch to the much cleaner model of
just calling .end() inside .save().
message_edit_form.handlebars already has a message_edit_topic that
refers to the topic edit section of message editing, and this made
things very confusing.
This fixes the following issues:
1. Photos are no longer resized larger than their native resolution.
2. Photos with transparency now have a checkerboard behind them to
signal an alpha of less than one.
We get events to delete subscribers for streams we are not
necessarily subscribed to, and it is now important to
process those events to produce the correct UI for showing
the number of subscribers to streams.
Passes the allowed domains for a realm to the frontend, via
page_params.domains. Groundwork for allowing users to add and
remove domains via the admin setting page, rather than via the
realm_alias.py management command.
Because jQuery passes the actual hashchange event to an onhashchange
handler, the `if reload` checks in the `hashchanged` function were
always returning true, resulting in the wrong logic being used for
computing where to send the user in the event that they edited the
hash in the browser to change their narrow.
Previously we showed an "Edit" item in the actions popover menu when a user
could edit the content or topic of a message, and nothing otherwise. We now
show "Edit", "Edit Topic", or "View Source" in the popover menu for every
message, depending on the editability of the message, and present an
appropriate version of message_edit_form when the menu item is clicked.
Finishes #1604 and #1761.
We compute the editability of messages in several places around the
frontend; standardize the definitions and store in
message_edit.get_editability. This commit should not change app behavior.
If you chose the same language as was already selected, the alert would
say “is now the default language!” where it omits the language name.
This is the fix so that the language name appears all the time.
The lightbox will now distinguish between whether or not something is a
photo and a YouTube video by the class name of the message inline
preview. It embeds the YouTube video in the lightbox as an iFrame
rather than previewing the video screenshot.
The startup code in subs.js used to intermingle data
stuff and UI stuff in a loop inside a called function,
which made the code hard to reason about.
Now there is a clear separation of concerns, with these methods
being called in succession:
stream_data.initialize_from_page_params();
stream_list.create_initial_sidebar_rows();
The first method was mostly extracted from subs.js, but I simplified
some things, like not needing to make a copy of the hashes
we were passed in, plus I now garbage collect email_dict. Also,
the code path that initialize_from_page_params() mostly replaces
used to call create_sub(), which fired a trigger, but now it
just does data stuff.
Once the data structure is built up, it's a very simple matter
to build the initial sidebar rows, and that's what the second
method does.
This replaces add_stream_to_sidebar(), which was kind of a misleading
name, and it also adds a couple lines of code that were always
called right after calling add_stream_to_sidebar().
This function will make it easier to unit test upcoming
changes related to stream counts.
This was mostly moving code, but one change is that we
don't call create_subs() in subs.js any more (which would
have been kind of circular dependency), since the only thing
that it did besides calling a more appropriate function
in stream_data.js was to generate a trigger that was
subsequently ignored and possibly a UI trap, as we don't
want to be messing with the stream sidebar when we go into
the stream settings page.
We now simply call exports.create_sub_from_server_data() for
newly encountered unsubscribed streams (which don't belong in
the sidebar anyway.)
This function used to live in subs.js. It's mostly a code move,
but I simplified the logic to determine whether it's subscribed
not to do a lookup into the same data structure that the sub
already came from.
I also added some tests.
This moves these functions from subs.js to stream_data.js:
receives_desktop_notifications
receives_audible_notifications
This makes notifications.js no longer dependent on the
bloated subs.js.
Previously, URLs were being incorrectly treated as unknown search
operators (since they had exactly one ":" in them, just like foo:bar
for an invalid choice of foo).
Fixes#1743.
Filter behaves similarly to filter in left sidebar, see PR #684. Added
stream input field to the stream creation modal along with other settings,
for clarity.
Fixes#455, #563.
This is a new mechanism to replicate the behavior of Emoji Box
drag-to-resize without the adverse effects of the last iteration — such
as not being able to drag to select text in the compose box.
The API uses this endpoint /json/streams/<stream_name> to update
stream information such as description, since the stream_name is
part of the URI it should be encoded to escape unsafe characters.
Fixes#1986.
This fixes a bug where the .subscribers property of a subscription
object in stream_data wasn't being properly updated to remove the
current user when the current user unsubscribed from the stream.
Fixes#1667.
Previously, we sent users to an "invite your friends" page after they
created an organization. This commit removes that step in the flow and sends
users directly to the home page. We also remove the now-unused
initial_invite_page.html template, initial_invite.js (which pre-filled the
invite emails with characters from literature), and the /invite URL route.
- Expand a box full of emojis into the
compose window for users to graphically select emojis.
- Append an emoji to the end of the message when a user
clicks the emoji in the emoji box.
- Trap the escape key to always close the emoji box
before closing anything else if the box is open.
- Fixes: #147.
`glue` ingores the + sign in the name of the emoji and creates the css
class without it. This causes the emoji pallete to miss '+1'
emoji. This commit creates a translation map from emoji name to css
class that we can use for the emoji popover.
Some languages such as Japanese use different word order with
English. If the stream name must be the last word, translating to these
languages is difficult.
Adds "Topic editing only" along with the tooltip explanation to lower right
of message editing box when it's past the message content editing deadline.
Unblur the link that was clicked so that when a user presses up/down
buttons it will automatically go back over to the individual messages
rather than tabbing up and down the sidebar.
Fixes: #1875.
This fixed additional downloads of a downloaded image by following the
keypress pattern of “Download” -> Esc -> Enter -> Enter -> … where
each enter downloads the image again.
It is necessary to blur the focus on the link when closing the overlay
to prevent this.
There is an issue where the unnarrow on escape was firing before the
overlay would escape. This shouldn’t happen because then when you try
to close out the overlay you also lose your spot on the page.
By changing the order, all is restored with the world.
This adds an event listener (by way of delegation) to the
.message_inline_image elements that pops up the overlay and hides it
when the overlay exit is clicked.
Fixes#654.
This lets you use up and down arrows in certain sections on the site to
navigate lists. It also prevents potentially unwanted actions caused by
using up/down arrows in those sections.
Fixes: #1696.
This adds a support a notification at the top of the screen that
alerts a user they’ve muted a stream and gives them the option to
unmute if it was an accident.
The notification disappears automatically after 4s, but if a user
moves their mouse over the notification, the timer resets to 2s after
the user moves their mouse off the notification, to make it easy for
users to read the full message and decide what to do.
Previously, no error would display in the UI if the link to the emoji
image was invalid. This would happen for instance if you put in
“invalid” for the Emoji URL. No alerts would pop up but it would refuse
to add the emoji.
This catches the error and displays a notification that looks like
“Failed: Enter a valid URL.”
Fixes#1116.
This adds a preview button to the subscriptions page to allow a user
to check out the stream without having to subscribe.
The button’s default state is hidden but on subscription row hover it
shows itself.
The preview button updates its text from "Narrow" to "Preview" and
back when a user subscribes and unsubscribes from a stream.
Fixes: #1519.
This fixes a bug where Zulip would throw a TypeError if the user were
to try to narrow to a stream they had never been subscribed to. With
the new "preview" feature on the subscriptions page, this will now
happen much more often.
This restructures the styling for the Zulip settings and
administration pages to minimize use of Bootstrap and use a consistent
styling library for similar elements.
While it is basically a wash in terms of the page's visuals, it will
make our life a lot easier for future work on improving the settings
pages section of the site.
In HTML, the line break immediately following a start tag is ignored
(see: https://www.w3.org/TR/html4/appendix/notes.html#h-B.3.1). An
extra span tag has been introduced in the upstream Pygments
HtmlFormatter in order to preserve the first new line. The Bugdown
Tests as well as our fenced_code.js frontend markdown processor have
been updated to reflect this new behavior.
From the popups that appear when clicking the down-arrow in the left
column's streams, you can now unsubscribe from that particular
channel. This runs on the same function that unsubscribes you from
streams in the "Subscriptions" tab.
Fixes: #1554.
[tweaked by tabbott to fix some errors]
The ‘for’ attribute is not valid HTML in the case of this because the
emails are invalid character sets and the input has no ID with the
email.
This changes it to a data-name which is still searchable but doesn’t
interfere with typical input behavior.
The checkboxes no longer float-left, fixing an issue with the
subscribe buttons leaning right in narrow windows.
Fixes: #1491.
There are no modern browsers that do not have built in JSON parsing
abilities. We do not need $.parseJSON as it now just serves as a call
to JSON.parse.
Attr now returns “checked” instead of true and “” instead of false in
higher versions. This fixes those issues.
The attr(“data-*”) have also been covered to data() as well.
$.browser is not supported in higher versions of jQuery. The solution
is to instead use vanilla JavaScript to test the navigator.userAgent
property for the browser.
Fixes: #1033.
Extract dispatch_normal_event() from the inner
function dispatch_event() in get_events_success()
in server_events.js. Also, alphabetize the cases in
the switch statement. This starts to address #1541,
but see the discussion on the ticket for how we can
continue to clean up our event dispatching.
This sends an event when a new avatar is uploaded that refreshes the
avatar for all browser clients without the need to reload the browser.
Fixes: #1359.
Changes relative path to an absolute path (that doesn't contain the
subdomain) for various links to
/create_realm, /api, /apps, /integrations, /hello, /terms, and the logged
out / (the Zulip in the upper left corner of portico)
I typically left links internal to the relevant pages (e.g. a link from
integrations.html to a subpage of integrations/) as relative links, and
changed external links from within the app to the absolute path (e.g. the
link to integrations from the gear menu).
Adds a new field default language in the zerver_realm model.
This realm level default language will be used as default language
for newly created users. Realm level default language can be
changed from the administration page.
Fixes#1372.
When in debug mode, previously an explicit `blueslip.error()` call
would not display the original stack trace of the error, making
debugging difficult.
This isn't perfect, in that it seems to display some tracebacks
multiple times, but at least the trace is available.
Adding the container attribute to the color picker options parameter
modifies the behavior of the spectrum function to allow the color
picker to be attached to the #subscriptions_table element rather than
the default document.body element.
This allows for the color picker to scroll with the subscriptions page,
fixing the bug where the color picker would not scroll up/down the page.
Fixes#1293.
Currently if you try to use a non-existent handlebars
template, you get this error:
Uncaught TypeError: Handlebars.templates[name] is not a function
This change makes it a little more clear what the issue is
and what the fix would be.
This is controlled through the admin tab and a new field in the Realms table.
Notes:
* The admin tab setting takes a value in minutes, whereas the backend stores it
in seconds.
* This setting is unused when allow_message_editing is false.
* There is some generosity in how the limit is enforced. For instance, if the
user sees the hovering edit button, we ensure they have at least 5 seconds to
click it, and if the user gets to the message edit form, we ensure they have
at least 10 seconds to make the edit, by relaxing the limit.
* This commit also includes a countdown timer in the message edit form.
Resolves#903.
For longer running servers, searching the backlog can become ambiguous
since the date stamps that demarcate the messages only include the month
and day. This commit changes the behavior to include the year for
messages which are more than a year old.
We were using data for both the request and response data in
$(".administration").on("submit", "form.admin-realm-form".
Left the request data as data to be consistent with the rest of the
file, renamed the response data to response_data.
This is controlled through the admin tab and a new field in the Realms
table. This mirrors the behavior of the old hardcoded setting
feature_flags.disable_message_editing. Partially resolves#903.
Assigns hotkey 'w' to search streams.
Only show search box when active. Activate with hotkey or by clicking
STREAMS.
Filter matches at the beginning of words in stream name.
Behaviour is otherwise almost identical to user search.
Casper tests.
We only use zxcvbn in the main webapp for checking the user's password
in the change password form. Since zxcvbn is a very large javascript
library (~700KB), loading it asynchronously only when a user is trying
to change their password results in a significant performance
improvement for loading the Zulip webapp on a slow network.
Fixes#263.
Apparently, there are like 5 independently developed jquery-caret
plugins, none of which are great. The previous one we were using was
last modified in 2010. This new one comes from
https://github.com/acdvorak/jquery.caret and at least doesn't use
deprecated jQuery syntax and has a repository on GitHub.
This plugin is way larger than it needs to be for what it does, but we
can deal with that later.
Place all hotkey names into a set of three objects in hotkeys.js:
* hotkeys_shift_insensitive
These are keys where the behaviour is the same whether they are
pressed with shift or not.
* hotkeys_no_modifiers
These are keys where the event should only be fired when shift
is not being pressed.
* hotkeys_shift
These are keys where the event should only be fired when the key
is pressed simultaneously with shift.
Each object is a dictionary of key value pairs, with the key being
the keyscan code (e.which) for the key. This is normally the ASCII
key code. The value is an object with two properties, name (which
is the event name) and message_view_only, a boolean. Hotkeys with
message_view_only set to true will not be fired when the home tab
is obscured.
Following strings are marked translatable:
- All strings which are passed to `button.text` or which affect the
text of buttons.
- All strings passed to `placeholder`.
- All strings passed to `compose_error`.
Fixes#969
* The warning contains a count of the number of people in the stream.
* An error appears if the warning is ignored and the user tries to
send the message anyway.
* The message cannot be sent until the warning is acknowledged or @all
/ @everyone is removed.
* This only applies to stream messages and not private messages.
Fixes#853.
Previously, we were checking if a particular user was the current user
in dozens of places in the codebase, and correct case-insensitive
checks were not used consistently, leading to bugs like #502.
In order to genericize use of Zulip outside companies,
all instances of coworkers have been changed to users.
NOTABLE EXCEPTION: When the Zulip instance is domain-
locked, the reference to coworkers remains. The reason
for this is twofold: first, the majority of Zulip instances
which require a particular domain will be locked to a
company, and second, the template variable for the domain
necessary should be added to the alert so it is clear
to the user what the domain needs to be for access.
Fixes: #861.
Previously, the user list would remain filtered after a user hit enter
to start composing a message to a user, leaving them in a state with a
partial user list.
Fixes#360.
Move recenter_pointer_on_display, suppress_scroll_pointer_update,
fast_forward_pointer, furthest_read, and server_furthest_read to
a new pointer module in pointer.js.