Skip to content

Commit

Permalink
message_list: Add buttons for different actions.
Browse files Browse the repository at this point in the history
  • Loading branch information
amanagr authored and timabbott committed Oct 22, 2024
1 parent 5686233 commit fa549a9
Show file tree
Hide file tree
Showing 37 changed files with 494 additions and 165 deletions.
5 changes: 1 addition & 4 deletions templates/zerver/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,11 @@
<div id="page_loading_indicator"></div>
<div id="message_feed_errors_container"></div>
<div id="message-lists-container"></div>
<div id="message-list-navigation"></div>
<div id="scheduled_message_indicator">
</div>
<div id="mark_read_on_scroll_state_banner">
</div>
<div id="typing_notifications">
</div>
<div id="mark_read_on_scroll_state_banner_place_holder">
</div>
<div id="bottom_whitespace">
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions tools/test-js-with-node
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ EXEMPT_FILES = make_set(
"web/src/message_list_data.ts",
"web/src/message_list_data_cache.ts",
"web/src/message_list_hover.ts",
"web/src/message_list_navigation.ts",
"web/src/message_list_tooltips.ts",
"web/src/message_list_view.ts",
"web/src/message_lists.ts",
Expand Down
1 change: 1 addition & 0 deletions web/shared/icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions web/src/click_handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,17 @@ export function initialize() {

// MISC

$("body").on("click", "#message-list-navigation-next-unread-conversation", (e) => {
assert(message_lists.current !== undefined);
e.currentTarget.blur();

if (message_lists.current.data.filter.can_show_next_unread_dm_conversation_button()) {
message_view.narrow_to_next_pm_string({trigger: "hotkey"});
} else {
message_view.narrow_to_next_topic({trigger: "hotkey", only_followed_topics: false});
}
});

{
const sel = [
"#stream_filters",
Expand Down
10 changes: 10 additions & 0 deletions web/src/hotkey.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import * as list_util from "./list_util";
import * as message_actions_popover from "./message_actions_popover";
import * as message_edit from "./message_edit";
import * as message_edit_history from "./message_edit_history";
import * as message_list_navigation from "./message_list_navigation";
import * as message_lists from "./message_lists";
import * as message_scroll_state from "./message_scroll_state";
import * as message_view from "./message_view";
Expand Down Expand Up @@ -63,6 +64,7 @@ import * as user_card_popover from "./user_card_popover";
import * as user_group_popover from "./user_group_popover";
import {user_settings} from "./user_settings";
import * as user_topics_ui from "./user_topics_ui";
import * as views_util from "./views_util";

function do_narrow_action(action) {
if (message_lists.current === undefined) {
Expand Down Expand Up @@ -694,6 +696,14 @@ export function process_hotkey(e, hotkey) {
}
}

switch (event_name) {
case "right_arrow":
if (message_lists.current?.navigation_bar_focused && views_util.is_in_focus()) {
return message_list_navigation.handle_right_arrow();
}
break;
}

// We handle the most complex keys in their own functions.
switch (event_name) {
case "escape":
Expand Down
2 changes: 2 additions & 0 deletions web/src/message_fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as message_feed_top_notices from "./message_feed_top_notices";
import * as message_helper from "./message_helper";
import type {MessageList} from "./message_list";
import type {MessageListData} from "./message_list_data";
import * as message_list_navigation from "./message_list_navigation";
import * as message_lists from "./message_lists";
import {raw_message_schema} from "./message_store";
import * as message_util from "./message_util";
Expand Down Expand Up @@ -132,6 +133,7 @@ function process_result(data: MessageFetchResponse, opts: MessageFetchOptions):
direct_message_group_data.process_loaded_messages(messages);
stream_list.update_streams_sidebar();
stream_list.maybe_scroll_narrow_into_view();
message_list_navigation.update();

if (
message_lists.current !== undefined &&
Expand Down
44 changes: 44 additions & 0 deletions web/src/message_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ export class MessageList {
// the user. Possibly this can be unified in some nice way.
reading_prevented: boolean;

// Tracks if the message list is visibly focused (has blue border
// around the selected message) or if the navigation buttons at
// the bottom of the feed are focused.
navigation_bar_focused: boolean;

// Tracks if the navigation bar is visible or not. Navigation bar
// hidden if there are no buttons to show or if the message feed
// is empty.
navigation_bar_visible: boolean;

// TODO: Clean up these monkey-patched properties somehow.
last_message_historical?: boolean;
should_trigger_message_selected_event?: boolean;
Expand All @@ -90,6 +100,8 @@ export class MessageList {
this.view = new MessageListView(this, collapse_messages, opts.is_node_test);
this.is_combined_feed_view = this.data.filter.is_in_home();
this.reading_prevented = false;
this.navigation_bar_focused = false;
this.navigation_bar_visible = false;

return this;
}
Expand Down Expand Up @@ -377,6 +389,38 @@ export class MessageList {
}
}

focus_navigation_bar(): void {
this.navigation_bar_focused = true;

if (this.navigation_bar_visible) {
this.view.focus_navigation_bar();
}
}

unfocus_navigation_bar(): void {
this.navigation_bar_focused = false;
this.view.unfocus_navigation_bar();
}

hide_navigation_bar(): void {
this.navigation_bar_visible = false;
this.view.unfocus_navigation_bar();
this.view.hide_navigation_bar();
}

show_navigation_bar(): void {
this.navigation_bar_visible = true;
this.view.show_navigation_bar();

if (this.navigation_bar_focused) {
this.focus_navigation_bar();
}
}

is_navigation_bar_focused(): boolean {
return this.navigation_bar_visible && this.navigation_bar_focused;
}

selected_message(): Message | undefined {
return this.get(this.data.selected_id());
}
Expand Down
165 changes: 165 additions & 0 deletions web/src/message_list_navigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import $ from "jquery";
import assert from "minimalistic-assert";
import type * as tippy from "tippy.js";

import render_message_list_navigation_buttons from "../templates/message_list_navigation_buttons.hbs";

import * as browser_history from "./browser_history";
import * as message_lists from "./message_lists";
import * as narrow_state from "./narrow_state";
import {web_mark_read_on_scroll_policy_values} from "./settings_config";
import * as settings_config from "./settings_config";
import * as unread from "./unread";
import {user_settings} from "./user_settings";

export function update_next_unread_conversation_button(): boolean {
if (message_lists.current === undefined) {
return false;
}

const filter = message_lists.current.data.filter;
const $next_unread = $("#message-list-navigation-next-unread-conversation");
if (
(filter.can_show_next_unread_dm_conversation_button() &&
unread.get_msg_ids_for_private().length !== 0) ||
(filter.can_show_next_unread_topic_conversation_button() &&
unread.get_unread_topics().stream_unread_messages !== 0)
) {
$next_unread.show();
return true;
}
$next_unread.hide();
return false;
}

export function update_mark_as_read_button(): boolean {
if (message_lists.current === undefined) {
return false;
}

const $mark_as_read = $("#message-list-navigation-mark-as-read");

if (!message_lists.current.has_unread_messages()) {
$mark_as_read.hide();
return false;
}

const filter = narrow_state.filter();
const is_conversation_view = filter === undefined ? false : filter.is_conversation_view();
const msg_list_navigation_mark_as_read: tippy.ReferenceElement | undefined =
$mark_as_read.get(0);
assert(msg_list_navigation_mark_as_read !== undefined);

if (
user_settings.web_mark_read_on_scroll_policy ===
web_mark_read_on_scroll_policy_values.never.code
) {
$mark_as_read.show();
return true;
}

if (
user_settings.web_mark_read_on_scroll_policy ===
web_mark_read_on_scroll_policy_values.conversation_only.code &&
!is_conversation_view
) {
$mark_as_read.show();
return true;
}

if (message_lists.current.can_mark_messages_read_without_setting()) {
$mark_as_read.hide();
return false;
}

$mark_as_read.show();
return true;
}

export function update_home_view_button(): boolean {
const $home_view_button = $("#message-list-navigation-home-view");
if (browser_history.is_current_hash_home_view()) {
$home_view_button.hide();
return false;
}
$home_view_button.show();
return true;
}

export function update(): void {
if (message_lists.current === undefined) {
return;
}

if (message_lists.current.visibly_empty()) {
message_lists.current.hide_navigation_bar();
return;
}

const update_button_functions = [
update_home_view_button,
update_mark_as_read_button,
update_next_unread_conversation_button,
];

let any_button_visible = false;
for (const update_function of update_button_functions) {
if (update_function()) {
any_button_visible = true;
}
}

if (any_button_visible) {
message_lists.current.show_navigation_bar();
} else {
message_lists.current.hide_navigation_bar();
}
}

export function is_any_button_focused(): boolean {
return document.activeElement?.classList.contains("message-list-navigation-button") ?? false;
}

export function handle_right_arrow(): boolean {
assert(document.activeElement !== null);
const $focused_button = $(document.activeElement);
let $next_button = $focused_button.nextAll(":visible").first();
if ($next_button.length === 0) {
$next_button = $focused_button.siblings(":visible").first();
}

if ($next_button[0] === $focused_button[0]) {
return true;
}

$next_button.trigger("focus");
return true;
}

export function render(): void {
let home_view_code;
switch (user_settings.web_home_view) {
case settings_config.web_home_view_values.inbox.code:
home_view_code = "inbox";
break;
case settings_config.web_home_view_values.all_messages.code:
home_view_code = "all-messages";
break;
case settings_config.web_home_view_values.recent_topics.code:
home_view_code = "recent";
break;
}

const rendered_buttons = render_message_list_navigation_buttons({home_view_code});
$("#message-list-navigation").html(rendered_buttons);
update();
}

export function init(): void {
render();
$("body").on("click", "#message-list-navigation-home-view", (e) => {
$(e.currentTarget).trigger("blur");
browser_history.set_hash("");
$(document).trigger(new $.Event("hashchange"));
});
}
17 changes: 17 additions & 0 deletions web/src/message_list_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,23 @@ export class MessageListView {
);
}

focus_navigation_bar(): void {
$(".message-list-navigation-button:visible").first().trigger("focus");
}

unfocus_navigation_bar(): void {
// Unfocus the buttons and hide any tooltips.
$(".message-list-navigation-button").trigger("blur");
}

hide_navigation_bar(): void {
$("#message-list-navigation").hide();
}

show_navigation_bar(): void {
$("#message-list-navigation").show();
}

maybe_rerender(): boolean {
const selected_idx = this.list.selected_idx();

Expand Down
15 changes: 13 additions & 2 deletions web/src/message_scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import _ from "lodash";

import * as compose_banner from "./compose_banner";
import * as message_fetch from "./message_fetch";
import * as message_list_navigation from "./message_list_navigation";
import * as message_lists from "./message_lists";
import * as message_scroll_state from "./message_scroll_state";
import * as message_viewport from "./message_viewport";
import * as narrow_state from "./narrow_state";
import * as unread from "./unread";
import * as unread_ops from "./unread_ops";
import * as unread_ui from "./unread_ui";

let hide_scroll_to_bottom_timer;
export function hide_scroll_to_bottom() {
Expand Down Expand Up @@ -119,6 +119,17 @@ export function scroll_finished() {
msg_list: message_lists.current,
});
}

// User is scrolling up
if (message_viewport.last_movement_direction < 0) {
const navigation_bar_bottom = $("#message-list-navigation").get_offset_to_window().bottom;
const visible_bottom = $("#compose").position().top;
// and the navigation bar is not completely in view
if (navigation_bar_bottom > visible_bottom) {
// then, focus on the currently selected message.
message_lists.current?.unfocus_navigation_bar();
}
}
}

let scroll_timer;
Expand Down Expand Up @@ -189,7 +200,7 @@ export function initialize() {
narrow_state.filter() !== undefined &&
message_lists.current === event.msg_list
) {
unread_ui.notify_messages_remain_unread();
message_list_navigation.update();
}
}
});
Expand Down
Loading

0 comments on commit fa549a9

Please sign in to comment.