diff --git a/web/src/list_widget.ts b/web/src/list_widget.ts index 62d197d1e9..34d98aa9f3 100644 --- a/web/src/list_widget.ts +++ b/web/src/list_widget.ts @@ -541,8 +541,23 @@ export function create( const $target_row = opts.html_selector!(meta.filtered_list[insert_index - 1]!); $target_row.after($(rendered_row)); } else { - const $target_row = opts.html_selector!(meta.filtered_list[insert_index + 1]!); - $target_row.before($(rendered_row)); + let $target_row = opts.html_selector!(meta.filtered_list[insert_index + 1]!); + if ($target_row.length !== 0) { + $target_row.before($(rendered_row)); + } else if (insert_index > 0) { + // We don't have a row rendered after row we are trying to insert at. + // So, try looking for the row before current row. + $target_row = opts.html_selector!(meta.filtered_list[insert_index - 1]!); + if ($target_row.length !== 0) { + $target_row.after($(rendered_row)); + } + } + + // If we failed at inserting the row due rows around the row + // not being rendered yet, just do a clean redraw. + if ($target_row.length === 0) { + widget.clean_redraw(); + } } widget.increase_rendered_offset(); } diff --git a/web/src/recent_view_ui.ts b/web/src/recent_view_ui.ts index 0fa6f5608a..42a83535f1 100644 --- a/web/src/recent_view_ui.ts +++ b/web/src/recent_view_ui.ts @@ -923,10 +923,16 @@ export function bulk_inplace_rerender(row_keys: string[]): void { // we ensure the list remains sorted after insertion. topics_widget.replace_list_data(get_list_data_for_widget(), false); topics_widget.filter_and_sort(); - for (const key of row_keys) { - inplace_rerender(key, true); + // Iterate in the order of which the rows should be present so that + // we are not inserting rows without any rows being present around them. + for (const topic_data of topics_widget.get_current_list()) { + const msg = message_store.get(topic_data.last_msg_id); + assert(msg !== undefined); + const topic_key = recent_view_util.get_key_from_message(msg); + if (row_keys.includes(topic_key)) { + inplace_rerender(topic_key, true); + } } - setTimeout(revive_current_focus, 0); }