We were updating the compose banners on every `keyup` event on the
topic input. Since, `keyup` also gets triggered for the modifier and
non-printing keys such as "Enter", this lead to banner for topic
required being closed via the `check_posting_policy_for_compose_box`
when pressing "Enter" to send a message with no topic.
This bug was probably introduced in 5c993f0, which moved additional
logic into `update_on_recipient_change`.
To solve this issue, we use the `input` event instead of the `keyup`
event to update the compose banners only when the value inside the
input element changes.
This change also prevents the the compose banner from being closed
when we only press modifier keys - such as Shift.
Add a word-wrap rule so that longer code elements, such as example
URLs or long return value names in the API documentation, do not
overflow out of the view in narrowed browsers or mobile views.
Only affects zulipchat, by being based on the BILLING_ENABLED setting.
The restricted backends in this commit are
- AzureAD - restricted to Standard plan
- SAML - restricted to Plus plan, although it was already practically
restricted due to requiring server-side configuration to be done by us
This restriction is placed upon **enabling** a backend - so
organizations that already have a backend enabled, will continue to be
able to use it. This allows us to make exceptions and enable a backend
for an org manually via the shell, and to grandfather organizations into
keeping the backend they have been relying on.
Since the html copied from VS Code is not structured as code but as
styled divs for each line, any code copied from it would be pasted
unformatted with blank lines between each line of code.
This has now been fixed, by detecting VS Code style code blocks by the
CSS property `white-space: pre` and pasting the text within as is, as
code.
This commit adds banner which is shown on successful stream
creation which contains a link to stream narrow. This banner
makes it more clear that stream was created successfully and
also makes it easy to navigate to the new stream.
Fixes#29171.
We want to name types/views that are not Stream or Direct related to be
"non-specific". The previously used term "non-stream" could be confusing
since it would literally mean any type/view which is not a stream type/
view, which would encapsulate the Direct type/view also.
Thus, we finally use the following terms to describe the type of
conversation:
1. Stream type (Streams or Topics)
2. Direct type (A)
3. Non specific type (Inbox, Recent conversation, All messages)
This commit fixes the bug, where navigating to inbox view does not
update the closed compose buttons. Due to this the tooltip over the
"Start new conversation" button also showed the wrong content.
In the situation where the DMs are disabled in an organization, we
disable the new conversation button. But due to this, the tooltip
hinting towards the same, was also being disabled because it was
attached to a disabled element which does not fire any events.
This commit fixes this bug, by wrapping the new conversation button
inside a div, and attaching the tooltip to this wrapper instead.
As reported on CZO, the new conversation button sometimes had stale
tooltip content rendered on it. In this commit, we change the logic
used to render this tooltip, to now render the tooltip content on the
fly via `instance.setContent()` which should eliminate any such bug.
Fixes#27158.
This is essential for converting to typescript, because
we can't create half a clean reaction and then calculate
vote_text afterwards. Instead, we should calculate it
with the information we already have, and create the
clean reaction object afterwards, all at once.
When we move to typescript, we want to be able to calculate
this value *before* creating the clean reactions, so that
we can generate the clean reactions in one go instead of
having some half-created object.
On chromium browsers, the scroll position is not restored when the text
in a textarea is replaced. So instead of directly replacing the text,
we call the `insert_and_scroll_into_view` function with `replace_all`
set to true.
We refactor the `insert_and_scroll_into_view` function to accept a new
parameter, `replace_all`, defaulting to false, that when set to `true`,
will replace all existing content of the textarea with the new content,
instead of inserting the new content at the current cursor position.
This is a prep commit for the next commit, which will set this new flag.
We want to make the default stream listing more relevant. To do this,
we always show "All streams" tab when stream is opened from another
user's profile. From other places, we show "Subscribed" if the user
is subscribed to the stream they are trying to edit otherwise
"All streams" are shown.
We want to make default group listing in left panel more relevant.
Thus "All groups" are shown when group is opened from another user's
profile. From other places, "Your groups" are shown if the user is in
the group they are trying to edit otherwise "All groups" are shown.
This commit adds links to open group settings from "User groups" tab
of user profile. These links are not shown to guests as they cannot
view `#groups` urls.
Fixes#25214.
We no longer show the 'default' visibility policy in
the inbox view. 'Unmute', 'Follow', and "Mute' are
still shown.
For topics with 'default' visibility policy, it is
still possible to change the visibility policy via the
three-dot menu.
The motivation is not to have the default state so
prominently called out.
The function 'emoji_status_fields_changed' separates the conditional
logic into two parts. Now, we compare 'selected_emoji_info' and
'old_emoji_info' only when both of them have the fields necessary for
comparison.This helps with upcoming type inference and we no longer have
to write same conditional logic twice.
While || targets null, undefined, false, NaN, 0, -0, 0n, "",
and document.all, ??(null coalescing) specifically targets
null and undefined,which we are looking for here.
Instead of partially creating it and then adding
more attributes, this commit creates the return
value (formatted draft) in a single assignment.
This is needed for typescript work, in an upcoming
commit.
It was always being set after the fact, and it will
be easier to manage types for the conversion to
Typescript if we just set this when setting the
rest of the data for the draft message.
Sometimes get_color is called with undefined
stream ids. This change makes more clear
what was already happening, and allows
for smoother conversion of other files
to typescript, including an upcoming
conversion of the drafts module, which
can call `get_color` with a draft with
undefined stream_id.
This keeps the color logic contained in
the `get_color` function, which seems
cleaner than the alternative of exporting
DEFAULT_COLOR to be used wherever sream_id
might be undefined.
It's been present since 1929cc5 and clearly is intended
to be part of a never-implemented format conversion
system. We can add a version if/when we actually need
such a feature.
The remote support view now returns results for deactivated remote
servers with those results sorted to the end and formatted to
visually stand out.
Forms to change sponsorship and discount fields on the customer
for the remote server or realm are not shown, but the data stored
on the customer object is shown, including any sponsorship request
information (if the customer had a sponsorship request pending when
it was deactivated).
Forms to schedule a plan are also not shown for deactivated servers
and their associated remote realms.
Forms and information for any current plan or scheduled plan, for
either the deactivated remote server or its associated remote
realms, are shown so that support staff can update those plans if
necessary.
Since the html copied from VS Code is not structured as code but as
styled divs for each line, any code copied from it would be pasted
unformatted with blank lines between each line of code.
This has now been fixed, by detecting VS Code style code blocks by the
CSS property `white-space: pre` and pasting the text within as is, as
code.
To address feedback that own emoji reactions were not sufficiently distinct, we increase
the prominence of one's own emoji reactions by:
- Setting a pixel-and-a-half border around own reactions.
- Reducing the alpha on the inner drop shadow of other reactions.
- Increasing the contrast on own reactions borders (and decreasing
them, in dark mode, on other reactions).
- Space around the emoji is maintained as in the current design in the own reactions.
Other reactions benefit from an additional half pixel of padding, top and bottom,
which is necessary to keep the pills (and the hover reaction button) the same
height as each other--regardless of whether there's an own reaction among them
or not. Padding is reduced in line with the increased border on own reactions.
Sets the max-width for table data cells in the activity and
installation charts.
If the content exceeds the limit, then the overflow is set to
hidden and the text-overflow is set to ellipsis, so there is
a visual indication that the text is not completely visible.
This change aids in differentiating between a normal user and a bot
account, furthur eliminating any confusion between them (a step forward,
considering how good LLM bots have become in impersonating a real user).
Fixes#25958.
Co-authored-by: 1010nishant <nishantjangid6377@gmail.com>
This commit adds a realm-level setting named
'zulip_update_announcements_stream' that configures the
stream to which zulip updates should be posted.
Fixes part of #28604.
It doesn't make sense for us to track a separate current filter when
it should just the be filter of current message list if there is one.
This will reduce possible confusion in the codebase where filter
returned by narrow_state is different from message_lists.current.
The `upload_objects_by_message_edit_row` map object was being exported
to handle the uploads during the editing of a message. To improve the
abstraction, we move the logic being used to access
`upload_objects_by_message_edit_row` and itself into `upload.js`.
Similarly, the `compose_upload_object` constant which was being exported
to handle the cancelling of compose uploads. This commit removes this
export and instead defines a new method `compose_upload_cancel` to
handle the same.
Every time a user edits a message, we call the `setup_upload` method
which creates a new Uppy instance and adds some event listeners to
enable the upload process. These event listeners were not being removed
during the cleanup process of message editing, which led to multiple
event listeners being attached to the edit message form. Due to this,
multiple duplicate files would get attached via these multiple event
listeners if a user opened the edit message form for the same message
multiple times.
This commit adds the `deactivate_upload` method to perform all the
necessary cleanups while closing the edit message form. Via this
method, we remove the event listeners attached and close the Uppy
instance which cancels all uploads, resets progress and removes all
files.
- Adds instructions for downloading a zuliprc file for a bot or for
yourself.
- Updates the button label to "Download zuliprc", since that's the
filename it downloads.
Fixes#28881.
Adds the information returned by get_push_status_for_remote_request
for remote billing users to the support page. Note that getting
the current push status data will result in some duplicate database
queries (getting customer, plan, current billed users, next billing
cycle) when generating the remote support view.
Previously, the sorting was broken due to
incorrect referencing of the property.
The code has been updated to use the "expiry_date"
property instead of "expires_at".
Fixes#29005.
When narrowing to a stream which doesn't exist, the
code to render users who are typing in that narrow
resulted in an assertion error as the stream didn't exist.
This commit removes the assertion and returns an empty array
(array of users who are typing) in such case to fix the issue.
This commit fixes an error where composing a message with
no stream selected resulted in making a POST request to
'/typing' with stream_id as undefined which resulted in
a "Missing server_id" error.
We no longer make a POST request if the stream is not
selected.
It's clearer to return undefined than an empty list,
because it's easier to do an equality check for undefined
at call sites to this function.
`ListCursor.get_row` returns early for falsey values
returned from `find_li`, so I think whatever this
comment is referring to is no longer relevant.
The work now being done in set_render_data used
to be done in render_more, which is called in
batches of 20 rows at a time. This work only
needs to be done once per narrow/view, so this
is a great performance improvement.
We already do not show the buttons for opening the group creation
form if user is not allowed to create group at all, but the
user can still open the form by going on "#groups/new" url.
This commit fixes this by redirecting such users to "#groups/your"
like we do for streams.
There were couple of problems in our handling of invalid or
incomplete URLs-
- The browser back button behavior breaks if someone enters
url with invalid group ID, incorrect group name.
- On typing group edit URLs with invalid group ID, an error
was raised and the URLs remained the same with just opening
the groups overlay with "Your" tab selected in left panel.
- On typing group edit URLs with incorrect right side tab or
without any right side tab, we showed "general" section, which
is fine, but the URL was still incorrect.
This commit fixes the above mentioned problems-
- URLs with invalid group IDs are now handled gracefully
with groups UI opening in the same way as before but the
url is updated to "#groups/your".
- We now update the right side tab to "general" if right
side tab is invalid or there is no right side tab.
- All the URL updates to fix invalid urls are done using
"history.replaceState" to make sure the browser back button
behaves as expected.
- All the code for checking the urls is done in hashchange.js
itself, so we can remove some code from change_state.
There were couple of problems in our handling of invalid or
incomplete URLs-
- The browser back button behavior breaks if someone enters
url with invalid or inaccessible stream ID, incorrect stream
name, "#streams/new" url without permission to create streams.
- On typing stream edit URLs with incorrect right side tab or
without any right side tab, we showed "general" section, which
is fine, but the URL was still incorrect.
This commit fixes the above mentioned problems-
- We now update the right side tab to "general" if right
side tab is invalid or there is no right side tab.
- All the URL updates to fix invalid urls are done using
"history.replaceState" to make sure the browser back button
behaves as expected.
- All the code for checking the urls is done in hashchange.js
itself, so we can remove some code from change_state.
We already do not show the buttons for opening the stream creation
form if user is not allowed to create streams at all, but the
user can still open the form by going on "#streams/new" url.
This commit fixes this by redirecting such users to
"#streams/subscribed" like we do for guests.
Previously, the link opened on clicking the stream name in
header was "#streams/{stream_id}/{stream_name}". It is now
changed to "#streams/{stream_id}/{stream_name}/general" as
the stream edit UI is opened with "general" tab.
The url hash for a group edit view now includes "general" or
"members" in the end depending upon which tab is selected in
the right section.
Fixes#28678.
We now use "data-group-section" attribute to set the "key" for
toggler in right section of groups overlay.
This change is preparatory work for showing the section opened
in right side in the url hash as we would use the "key" value
in url hash as well and the existing "group_general_settings"
and "group_member_settings" toggler key values were too long to
be used in the url. We previously used toggler key value as
class name and then used that class as selector to show the
relevant section but we now use "data-group-setting" section
to avoid using common class names like "general" and "members".
The (1) delay in fetching the read receipts data from the api call to
`/json/messages/${message_id}/read_receipts`; followed by the execution
of the success callback function, and the (2) use of `.append()` to
render the modal and user list, together lead to duplication of the read
receipts modal and also the user list inside the read receipts menu.
This commit adds a check to set the read receipts menu contents only if
the read receipts modal for the selected message ID is open by the time
the network request is resolved.
In addition, this commit also uses the `on_shown` hook instead of the
`on_show` hook in the read receipts modal logic, to add a delay in the
calling of the read receipts API, which prevents the stacking of the
requests.
The read receipts option, resides under the triple-dot message actions
menu. This made the process of viewing the read receipts take up
multiple steps, even via a keyboard-driven workflow.
Via this commit, now while focused on any message in a message feed,
and pressing `Shift` + `V`, efficiently brings up the read receipts
for that message.
Fixes part of #24716.
Co-Authored-by: SameepAher <sameepaher@gmail.com>
This is no longer necessary for vertical alignment, and by
removing the 6px of padding it represents, bot DM rows will have
the same 22px height as other DM rows.
This was just debugging logic working around the fact that vdom.ts was
not originally implemented in TypeScript, and should not be polluting
our types.
Updates the class name used for the sponsorship form container in
the remote support views to be more specific.
Adds a shared "support-form" class for the different forms in the
realm_details template.
Use the same CSS rule for current and next plan information sections.
This commit renames the realm-level setting
'signup_notifications_stream' to 'signup_announcements_stream'.
The new name reflects better what the setting does.
This commit renames the realm-level setting 'notifications_stream'
to 'new_stream_announcements_stream'.
The new name reflects better what the setting does.
Now whenever we initiate sending a message, we save / update its draft,
which is deleted on a successful send. Earlier, we did this only for
locally echoed messages. Hence a non locally echoed message's draft
would remain, if created in the timeframe between initiating send and
receiving the same message from the server, which can be significant
for slow connections.
Happily, every last CSS property in these styles is already
described for the places <pre> appears in the Zulip UI:
1. In rendered message markdown
2. In the compose preview
3. In the information overlay (Message formatting)
Some of these may have once been necessary to enforce an ordering on
cyclic imports, but we’ve fixed all of those now.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
The `line-height` value is set to `inherit` in zulip.css, rendering
this line moot. `inherit` will always force list items to take
their line height from the nearest ancestor that sets one.
Commit a4938d3760 (#28971) fixed the
order-sensitivity of these modules, so it suffices to just import them
where they are used.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
a4938d3760 introduced assertions
for page_params for which they were used. This caused the
assertion to fail on event_status page making the page not work.
Removed the page_params from running on event_status page to fix it.
This commit modifies the behavior of the message view header
when a stream's description is empty. Previously, it displayed
"(no description)". With this change, if the user is an admin
or owner (i.e., has permission to update the description), it
will now display a "Add description" link to the settings. If
the user does not have these permissions, it will display nothing.
Fixes#28851
Signed-off-by: Sayyed Arib Hussain <sayyedaribhussain4321@gmail.com>
This commit adds a "copy link to profile" button in user_profile_modal.
Clicking on this button copies the user's profile link and displays a
"Copied!" tooltip.
Clicking on "View profile" option now dynamically generates a URL,
allowing the user profile modal to open. Upon closing the modal,
the URL is reverted back to one that was active before the modal
was opened.
Additionally, It displays a profile access error modal when a user
attempts to either view an inaccessible profile or when an invalid
user id is present in the URL.
Fixes#28445.
Previously, in DM disabled org messaging to bot was not working when
starting new conversation and adding bot as recipient because of not
updating on recipient change. And secondly, self messaging was not
allowed.
This commit ensures that the DM to bot and self are allowed irrespective
of dm restrictions.
tests: Verify DMs adhere to DM restriction policy.
Fixes#28412
Signed-off-by: sayyedarib <sayyedaribhussain4321@gmail.com>
Commit bd6471f0e3 (#28691) added this
reference to the old name, even though it had already been renamed in
commit b220d29fed (#17775), presumably
because that had failed to update the OpenAPI description.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
Fixes#27369.
When editing a topic name via the topic header bar, it's easy to
accidentally move messages into an existing topic, which is
difficult to undo. This commit adds a confirmation modal for when
this is about to happen.
* `font-size: 100%` is unnecessary, as `font-size: 16px` is set on
the `body` selector.
* `text-size-adjust` is unnecessary, as supporting browsers appear
to use `100%` as a default value anyway.
For spectators, the chunk of page_params that originates from
do_events_register isn’t assigned until ui_init.js. That means the
TypeScript type of page_params is mostly a lie during module load
time: reading a parameter too early silently results in undefined
rather than the declared type, with unpredictable results later on.
We want to make such an early read into an immediate runtime error,
for both users and spectators consistently, and pave the way for
runtime validation of the page_params type. As a second step, split
out the subset of fields that pertain to the entire realm.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
For spectators, the chunk of page_params that originates from
do_events_register isn’t assigned until ui_init.js. That means the
TypeScript type of page_params is mostly a lie during module load
time: reading a parameter too early silently results in undefined
rather than the declared type, with unpredictable results later on.
We want to make such an early read into an immediate runtime error,
for both users and spectators consistently, and pave the way for
runtime validation of the page_params type. As a first step, split
out the subset of fields that pertain to the current user.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit disables the stream-select dropdown in the "Move message"
modal if the user is not allowed to move messages between streams, and
adds a tooltip for clarification when the dropdown is disabled.
Fixes#28345.
We previously had code to disable the "Add" button initially but
then we re-enabled it again if user had permission to add members.
We do not need that code to enable/disable the button based on
permission since the button is disabled initially and it is
only enabled when user updates the input which is not allowed
if users is not allowed to add members.
Previously, when there is no valid pill in the members list and
user clicks on "Add" button, then "No user to add" error is shown
but the error message is visible until successful user is added
and the same goes for success messages too.
This commit updates the code to remove both error and success
messages when user types in the input.
Previously, when there is no valid pill in the members list and user
clicks on "Add" button, then "No user to subscribe" error is shown
but the error message is visible until successful user is added and
the same goes for success messages too.
This commit updates the code to remove both error and success messages
when user types in the input.
Fixes#27438.
In the Personal settings stream management panel,
when notification settings are changed, Saving/Saved
indicator are shown on personal settings heading instead
of notification settings heading.
Fix this issue by showing indicator on
notification settings heading.
Fixes: zulip#28728.
This commit addresses code duplication issue in
'stream_is_muted_changed()' which was redundantly
present in 'stream_setting_changed()'.
The changes ensure that the functionality is now centralized
and can be easily updated or extended in the future.
Adds a link on the upgrade and billing pages that opens a stripe
billing portal for the customer to update their name and address
that will appear on invoices and receipts.
On the billing page, updating the credit card information will
no longer update the customer billing address, since they can
now do this directly through the billing portal. To be consistent
with the credit card form on the upgrade page, we still require
inputting a billing address for the card.
Note that, once an invoice is paid/complete, then changes to the
customer's name and address will not be applied to those invoices.
We need fields like 'url_template' to do the code extraction.
Those are absent if 'playground_info' is undefined, thus we should
return immediately in those cases.
The 'playground_url' field is specialized to the 'else' block ,
but is being written into global 'playground' object thus mutating
it.
To avoid this , we create a Map, with its values being objects
that contain all the fields (including playground_url) neccessary
to be passed into the template for rendering.
Instead of charging the customer using the attached payment
method and then creating the invoice, we create an invoice and
force an immediate payment for the invoice via the attached
payment method.
This is a preparatory commit. It adds an extra notification_event_type
to the Recipient type. This can be used to differentiate between
typing notifications and message edit typing notifications since
they send different events.
This commit extracts the edited notice computation logic of
edited_in_left_col, edited_alongside_sender and edited_status_message
to a new function - set_edited_notice_locations and calls it right
after the method merge_message_groups.
This is a preparatory commit, and is done since theses three variables
were previously wrongly initialized in the beginning for live messages
received.
We also introduce a modified flag to decide whether to display the
edited notice or not. This is useful since now we are computing
the edited notice values even when messages are not edited, and
hence we show the notices only when the modified flag is true.
The function body contains only two conditionals, so the
'switch' statements can be replaced with simple 'if's that
return immediately, thus making the code block cleaner.
This logic was part of the original desktop notifications
implementation in 4cb0c6225e.
There's no apparent standard for the number of characters allowed to
be shown in a desktop notification, so truncating at 150 characters
arbitrarily seems wrong.
Further, we've decided it's no longer a priority to truncate at word
boundaries, we can rely on the browser to take responsibility for
truncation.
Fixes#25260.
Refactoring to avoid duplication, improve readability, and standardize
deselection logic by converting calls to remove to
deselect_top_left_corner_items.
The proposed_val for "realm_can_access_all_users_group" setting
was always returning NaN value which resulted in the value
being included in request even when it was not changed or disabled
due to org not being on "Plus" plan. This resulted in a bug where
user was not allowed to change the "guest" indicator setting
on orgs without "Plus" plan.
For orgs with "Plus" plan there was no problem in changing the
setting but the save button was visible incorrectly if the setting
was set to the initial value.
This commit fixes both the bugs.
The "Who can access all users" setting is not disabled for
organizations not on "Plus" plans in production because of
the "page_params.development_environment" check.
We do not need that check anymore as the feature is now
enabled in production.
The previous logic would treat navigating with the arrow keys, or
alt-tab, as a reason to clear the subdomain unavailable warning, and
would not necessarily check again immediately. Now just trigger off
changes in the input.
Instead, just trigger off actual changes in the value of the input.
On /upgrade page, we show annual schedule & price for a
fixed-price plan, by default.
This also acts as a prep commit for fixed-price plan
with pay-by-invoice collection method as we only offer
annual plan in such case. So, annual data is shown by default
on /upgrade page.
Many of these code paths largely expect it to be a valid user ID, so
we could raise an exception if the user ID is invalid, but probably
gracefully proceeding is reasonable for the callers.
This correctly avoids pageup/pagedown scrolling past already rendered
content, while also always making progress, which the previous logic
introduced in d8ec141de2 might do, at
least in degenerate cases with very small render windows.
I'm not sure this change has any effect in practice with current
render window values, but it does fix a bug if I set the maximum
render window size to 20.
The previous batch of improvements to this code path in
6562ea94e4 introduced a race bug where:
- You navigate to a narrowed view; Zulip renders cached data from
`all_messages_data` that we know is current, but
`fetch_status.has_found_newest` is initialized to `false`
nonetheless.
- The bottom is visible, triggering the check for whether the view
should be marked as read.
- `fetch_status.has_found_newest` is still `false`, and so we
incorrectly refuse to mark as read.
- We finish fetching data from the server, do the background rerender
for that (with no changes), but that doesn't trigger a re-check for
whether the bottom is visible.
There's several ways to address this, but most correct to me is to not
check fetch_status in this particular code path.
The same reasoning applies to the navigate.js call sites.
Previously, when no parameter was passed to the get_timestamp_for_
flatpickr method, it would result in an uncaught exception. This is
breaking the "Add global time" of compose bar.
This can be avoided by doing an early return of current time to hour
in case no string is passed.
This was introduced in #28767 with the intention to skip scrolling
the selected message.
So, the actual bug that the PR fixed would have been just fixed
by opening the compose box early.
This matches the algorithm that we designed for the Python API, except
that we use a ratio of 2 rather than sqrt(2) in the message_fetch code
path, because it's a heavier request.
We increase the number of failures before showing a user-facing error
to roughly preserve the same time period before a user-facing error is
shown.
Previously, these endpoints just did exponential backoff, without
looking at the rate-limiting headers returned by the server, resulting
in requests that the client could have been certain would fail with an
additional rate-limiting error.
Fix this by using the maximum of the existing exponential backoff with
the value returned by the rate-limiting header.
Fixes#28807.
This should help reduce the risk of hitting rate limits when users
have a very large number of messages to fetch via this mechanism.
Inline the `messages` variable that was only used in one place while
we're touching this.
This function incorrectly and misleadingly did an immediate initial
call, despite both of its callers doing immediate calls themselves (in
one case, with a different parameter passed).
This led to unnecessary server load when reloading the app via event
system triggered reloads, since every client would call `/` twice.
I was not able to reproduce obviously badly broken behavior from these
logic bugs, but after the renaming of message_viewport helpers in the
last few commits, it's clear that this logic was trying to check if
we're actually at the start/end of the possibly message feed, not just
the rendered portion, and doing so incorrectly.
The previous logic for both scrolling down and using pagedown would
incorrectly mark an entire conversation as read when reaching the
bottom of a render window, even if there were more messages loaded or
to fetch from the server.
Fix this error in the calculation by asking the correct data
structures if we're actually at the bottom.
To avoid the navigate.js keyboard shortcut code paths circumventing
this new logic, or needing to duplicate it, they now call
process_visible, rather than its helper.
Since we always call `deactivate` from `hashchange`,
`browser_history.state.changing_hash` is always `true` and hence
`save_narrow` just retuns without doing anything.