mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	Normally the "n" key skips over muted streams, but if we are currently narrowed inside a muted stream, it will now go to the next topics within that stream. For me the use case was that I have a stream I check up on about once a day, and "n" would be super useful for me to clear out unread counts while still skimming some content, and without having to temporarily unmute the stream.
		
			
				
	
	
		
			253 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var topic_generator = (function () {
 | 
						|
 | 
						|
var exports = {};
 | 
						|
 | 
						|
exports.sub_list_generator = function (lst, lower, upper) {
 | 
						|
    // lower/upper has Python range semantics so if you pass
 | 
						|
    // in lower=5 and upper=8, you get elements 5/6/7
 | 
						|
    var i = lower;
 | 
						|
 | 
						|
    return {
 | 
						|
        next: function () {
 | 
						|
            if (i >= upper) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            var res = lst[i];
 | 
						|
            i += 1;
 | 
						|
            return res;
 | 
						|
        },
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.reverse_sub_list_generator = function (lst, lower, upper) {
 | 
						|
    // lower/upper has Python range semantics so if you pass
 | 
						|
    // in lower=5 and upper=8, you get elements 7/6/5
 | 
						|
    var i = upper - 1;
 | 
						|
 | 
						|
    return {
 | 
						|
        next: function () {
 | 
						|
            if (i < lower) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            var res = lst[i];
 | 
						|
            i -= 1;
 | 
						|
            return res;
 | 
						|
        },
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.list_generator = function (lst) {
 | 
						|
    return exports.sub_list_generator(lst, 0, lst.length);
 | 
						|
};
 | 
						|
 | 
						|
exports.reverse_list_generator = function (lst) {
 | 
						|
    return exports.reverse_sub_list_generator(lst, 0, lst.length);
 | 
						|
};
 | 
						|
 | 
						|
exports.fchain = function (outer_gen, get_inner_gen) {
 | 
						|
    var outer_val = outer_gen.next();
 | 
						|
    var inner_gen;
 | 
						|
 | 
						|
    return {
 | 
						|
        next: function () {
 | 
						|
            while (outer_val !== undefined) {
 | 
						|
                if (inner_gen === undefined) {
 | 
						|
                    inner_gen = get_inner_gen(outer_val);
 | 
						|
                    if (!inner_gen || !inner_gen.next) {
 | 
						|
                        blueslip.error('Invalid generator returned.');
 | 
						|
                        return;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                var inner = inner_gen.next();
 | 
						|
                if (inner !== undefined) {
 | 
						|
                    return inner;
 | 
						|
                }
 | 
						|
                outer_val = outer_gen.next();
 | 
						|
                inner_gen = undefined;
 | 
						|
            }
 | 
						|
        },
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.chain = function (gen_lst) {
 | 
						|
    function get(which) {
 | 
						|
        return which;
 | 
						|
    }
 | 
						|
 | 
						|
    var outer_gen = exports.list_generator(gen_lst);
 | 
						|
 | 
						|
    return exports.fchain(outer_gen, get);
 | 
						|
};
 | 
						|
 | 
						|
exports.wrap = function (lst, val) {
 | 
						|
    if (val === undefined) {
 | 
						|
        return exports.list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var i = _.indexOf(lst, val);
 | 
						|
    if (i < 0) {
 | 
						|
        return exports.list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var inners = [
 | 
						|
         exports.sub_list_generator(lst, i, lst.length),
 | 
						|
         exports.sub_list_generator(lst, 0, i),
 | 
						|
    ];
 | 
						|
 | 
						|
    return exports.chain(inners);
 | 
						|
};
 | 
						|
 | 
						|
exports.wrap_exclude = function (lst, val) {
 | 
						|
    if (val === undefined) {
 | 
						|
        return exports.list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var i = _.indexOf(lst, val);
 | 
						|
    if (i < 0) {
 | 
						|
        return exports.list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var inners = [
 | 
						|
         exports.sub_list_generator(lst, i+1, lst.length),
 | 
						|
         exports.sub_list_generator(lst, 0, i),
 | 
						|
    ];
 | 
						|
 | 
						|
    return exports.chain(inners);
 | 
						|
};
 | 
						|
 | 
						|
exports.reverse_wrap_exclude = function (lst, val) {
 | 
						|
    if (val === undefined) {
 | 
						|
        return exports.reverse_list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var i = _.indexOf(lst, val);
 | 
						|
    if (i < 0) {
 | 
						|
        return exports.reverse_list_generator(lst);
 | 
						|
    }
 | 
						|
 | 
						|
    var inners = [
 | 
						|
         exports.reverse_sub_list_generator(lst, 0, i),
 | 
						|
         exports.reverse_sub_list_generator(lst, i+1, lst.length),
 | 
						|
    ];
 | 
						|
 | 
						|
    return exports.chain(inners);
 | 
						|
};
 | 
						|
 | 
						|
exports.filter = function (gen, filter_func) {
 | 
						|
    return {
 | 
						|
        next: function () {
 | 
						|
            while (true) {
 | 
						|
                var val = gen.next();
 | 
						|
                if (val === undefined) {
 | 
						|
                    return;
 | 
						|
                }
 | 
						|
                if (filter_func(val)) {
 | 
						|
                    return val;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        },
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.map = function (gen, map_func) {
 | 
						|
    return {
 | 
						|
        next: function () {
 | 
						|
            var val = gen.next();
 | 
						|
            if (val === undefined) {
 | 
						|
                return;
 | 
						|
            }
 | 
						|
            return map_func(val);
 | 
						|
        },
 | 
						|
    };
 | 
						|
};
 | 
						|
 | 
						|
exports.next_topic = function (streams, get_topics, has_unread_messages, curr_stream, curr_topic) {
 | 
						|
    var stream_gen = exports.wrap(streams, curr_stream);
 | 
						|
 | 
						|
    function get_topic_gen(which_stream) {
 | 
						|
        var gen;
 | 
						|
 | 
						|
        if (which_stream === curr_stream) {
 | 
						|
            gen = exports.wrap_exclude(get_topics(which_stream), curr_topic);
 | 
						|
        } else {
 | 
						|
            gen = exports.list_generator(get_topics(which_stream));
 | 
						|
        }
 | 
						|
 | 
						|
        function has_unread(topic) {
 | 
						|
            return has_unread_messages(which_stream, topic);
 | 
						|
        }
 | 
						|
 | 
						|
        function make_object(topic) {
 | 
						|
            return {
 | 
						|
                stream: which_stream,
 | 
						|
                topic: topic,
 | 
						|
            };
 | 
						|
        }
 | 
						|
 | 
						|
        gen = exports.filter(gen, has_unread);
 | 
						|
        gen = exports.map(gen, make_object);
 | 
						|
 | 
						|
        return gen;
 | 
						|
    }
 | 
						|
 | 
						|
    var outer_gen = exports.fchain(stream_gen, get_topic_gen);
 | 
						|
    return outer_gen.next();
 | 
						|
};
 | 
						|
 | 
						|
exports.get_next_topic = function (curr_stream, curr_topic) {
 | 
						|
    var my_streams = stream_sort.get_streams();
 | 
						|
 | 
						|
    my_streams = _.filter(my_streams, function (stream_name) {
 | 
						|
        if (stream_data.name_in_home_view(stream_name)) {
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        if  (stream_name === curr_stream) {
 | 
						|
            // We can use n within a muted stream if we are
 | 
						|
            // currently narrowed to it.
 | 
						|
            return true;
 | 
						|
        }
 | 
						|
        return false;
 | 
						|
    });
 | 
						|
 | 
						|
    function get_unmuted_topics(stream_name) {
 | 
						|
        var stream_id = stream_data.get_stream_id(stream_name);
 | 
						|
        var topics = topic_data.get_recent_names(stream_id);
 | 
						|
        topics = _.reject(topics, function (topic) {
 | 
						|
            return muting.is_topic_muted(stream_name, topic);
 | 
						|
        });
 | 
						|
        return topics;
 | 
						|
    }
 | 
						|
 | 
						|
    function has_unread_messages(stream_name, topic) {
 | 
						|
        var stream_id = stream_data.get_stream_id(stream_name);
 | 
						|
        return unread.topic_has_any_unread(stream_id, topic);
 | 
						|
    }
 | 
						|
 | 
						|
    return exports.next_topic(
 | 
						|
        my_streams,
 | 
						|
        get_unmuted_topics,
 | 
						|
        has_unread_messages,
 | 
						|
        curr_stream,
 | 
						|
        curr_topic
 | 
						|
    );
 | 
						|
};
 | 
						|
 | 
						|
exports.get_next_stream = function (curr_stream) {
 | 
						|
    var my_streams = stream_sort.get_streams();
 | 
						|
    var stream_gen = exports.wrap_exclude(my_streams, curr_stream);
 | 
						|
    return stream_gen.next();
 | 
						|
};
 | 
						|
 | 
						|
exports.get_prev_stream = function (curr_stream) {
 | 
						|
    var my_streams = stream_sort.get_streams();
 | 
						|
    var stream_gen = exports.reverse_wrap_exclude(my_streams, curr_stream);
 | 
						|
    return stream_gen.next();
 | 
						|
};
 | 
						|
 | 
						|
return exports;
 | 
						|
}());
 | 
						|
 | 
						|
if (typeof module !== 'undefined') {
 | 
						|
    module.exports = topic_generator;
 | 
						|
}
 |