mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-03 21:43:21 +00:00 
			
		
		
		
	This adds support for unstarring all (starred) messages from a particular topic, from the topic popover. The earlier implementation of this in #16898 was reverted inbc55aa6a01(#17429) because it had two problems- 1. The crash reported inbc55aa6a01was due to message_store returning undefined. This happens when the message itself hasn't been fetched from the server yet, but we know that the message is starred from the ids in `page_params` in `starred_messages.js`. This commit handles this case explicitly. Note that, we simply ignore those messages which we haven't fetched, and because of this, it may happen that we don't unstar some messages from that topic. The correct implementation for this would be to ask the backend for starred IDs in a topic. 2. The earlier implementation actually unstarred **all** messages. This was because it grabbed the topic and stream_id from the topic popover `data` attributes, after the topic popover had been closed. This passed `undefined`, which the function then interpreted as an action to unstar all messages. With this commit, we use the confirm_dialog widget, which eliminates the need to store this data in the DOM.
		
			
				
	
	
		
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import _ from "lodash";
 | 
						|
 | 
						|
import * as channel from "./channel";
 | 
						|
import * as message_store from "./message_store";
 | 
						|
import * as starred_messages from "./starred_messages";
 | 
						|
import * as ui from "./ui";
 | 
						|
import * as unread_ops from "./unread_ops";
 | 
						|
 | 
						|
function send_flag_update_for_messages(msg_ids, flag, op) {
 | 
						|
    channel.post({
 | 
						|
        url: "/json/messages/flags",
 | 
						|
        idempotent: true,
 | 
						|
        data: {
 | 
						|
            messages: JSON.stringify(msg_ids),
 | 
						|
            flag,
 | 
						|
            op,
 | 
						|
        },
 | 
						|
    });
 | 
						|
}
 | 
						|
export const _unread_batch_size = 1000;
 | 
						|
 | 
						|
export const send_read = (function () {
 | 
						|
    let queue = [];
 | 
						|
    let on_success;
 | 
						|
    let start;
 | 
						|
    function server_request() {
 | 
						|
        // Wait for server IDs before sending flags
 | 
						|
        const real_msgs = queue.filter((msg) => !msg.locally_echoed);
 | 
						|
        const real_msg_ids = real_msgs.map((msg) => msg.id);
 | 
						|
 | 
						|
        if (real_msg_ids.length === 0) {
 | 
						|
            setTimeout(start, 100);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        const real_msg_ids_batch = real_msg_ids.slice(0, _unread_batch_size);
 | 
						|
 | 
						|
        // We have some real IDs.  If there are any left in the queue when this
 | 
						|
        // call finishes, they will be handled in the success callback.
 | 
						|
 | 
						|
        channel.post({
 | 
						|
            url: "/json/messages/flags",
 | 
						|
            idempotent: true,
 | 
						|
            data: {messages: JSON.stringify(real_msg_ids_batch), op: "add", flag: "read"},
 | 
						|
            success: on_success,
 | 
						|
        });
 | 
						|
    }
 | 
						|
 | 
						|
    start = _.throttle(server_request, 1000);
 | 
						|
 | 
						|
    on_success = function on_success(data) {
 | 
						|
        if (data === undefined || data.messages === undefined) {
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        queue = queue.filter((message) => !data.messages.includes(message.id));
 | 
						|
 | 
						|
        if (queue.length > 0) {
 | 
						|
            start();
 | 
						|
        }
 | 
						|
    };
 | 
						|
 | 
						|
    function add(messages) {
 | 
						|
        queue = queue.concat(messages);
 | 
						|
        start();
 | 
						|
    }
 | 
						|
 | 
						|
    return add;
 | 
						|
})();
 | 
						|
 | 
						|
export function save_collapsed(message) {
 | 
						|
    send_flag_update_for_messages([message.id], "collapsed", "add");
 | 
						|
}
 | 
						|
 | 
						|
export function save_uncollapsed(message) {
 | 
						|
    send_flag_update_for_messages([message.id], "collapsed", "remove");
 | 
						|
}
 | 
						|
 | 
						|
// This updates the state of the starred flag in local data
 | 
						|
// structures, and triggers a UI rerender.
 | 
						|
export function update_starred_flag(message_id, new_value) {
 | 
						|
    const message = message_store.get(message_id);
 | 
						|
    if (message === undefined) {
 | 
						|
        // If we don't have the message locally, do nothing; if later
 | 
						|
        // we fetch it, it'll come with the correct `starred` state.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    message.starred = new_value;
 | 
						|
    ui.update_starred_view(message_id, new_value);
 | 
						|
}
 | 
						|
 | 
						|
export function toggle_starred_and_update_server(message) {
 | 
						|
    if (message.locally_echoed) {
 | 
						|
        // This is defensive code for when you hit the "*" key
 | 
						|
        // before we get a server ack.  It's rare that somebody
 | 
						|
        // can star this quickly, and we don't have a good way
 | 
						|
        // to tell the server which message was starred.
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    message.starred = !message.starred;
 | 
						|
 | 
						|
    // Unlike most calls to mark messages as read, we don't check
 | 
						|
    // msg_list.can_mark_messages_read, because starring a message is an
 | 
						|
    // explicit interaction and we'd like to preserve the user
 | 
						|
    // expectation invariant that all starred messages are read.
 | 
						|
    unread_ops.notify_server_message_read(message);
 | 
						|
    ui.update_starred_view(message.id, message.starred);
 | 
						|
 | 
						|
    if (message.starred) {
 | 
						|
        send_flag_update_for_messages([message.id], "starred", "add");
 | 
						|
        starred_messages.add([message.id]);
 | 
						|
    } else {
 | 
						|
        send_flag_update_for_messages([message.id], "starred", "remove");
 | 
						|
        starred_messages.remove([message.id]);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
export function unstar_all_messages() {
 | 
						|
    const starred_msg_ids = starred_messages.get_starred_msg_ids();
 | 
						|
    send_flag_update_for_messages(starred_msg_ids, "starred", "remove");
 | 
						|
}
 | 
						|
 | 
						|
export function unstar_all_messages_in_topic(stream_id, topic) {
 | 
						|
    const starred_message_ids = starred_messages.get_starred_message_ids_in_topic(stream_id, topic);
 | 
						|
    send_flag_update_for_messages(starred_message_ids, "starred", "remove");
 | 
						|
}
 |