From 04d720f3a71ec387dd38b4095b18d1c2ba8f3132 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Fri, 17 Jan 2025 11:25:41 +0800 Subject: [PATCH] chore: Improve Table, List load more threshold, and avoid duplicate request. (#550) - Default `threshold` changed to 20. --- crates/ui/src/list/list.rs | 42 +++++++++++++++++++------------------ crates/ui/src/table.rs | 43 ++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/crates/ui/src/list/list.rs b/crates/ui/src/list/list.rs index 53d12ed4..1ee01987 100644 --- a/crates/ui/src/list/list.rs +++ b/crates/ui/src/list/list.rs @@ -1,4 +1,3 @@ -use std::ops::Range; use std::time::Duration; use std::{cell::Cell, rc::Rc}; @@ -95,10 +94,11 @@ pub trait ListDelegate: Sized + 'static { /// Returns a threshold value (n rows), of course, when scrolling to the bottom, /// the remaining number of rows triggers `load_more`. + /// This should smaller than the total number of first load rows. /// - /// Default: 50 rows + /// Default: 20 rows fn load_more_threshold(&self) -> usize { - 50 + 20 } /// Load more data when the table is scrolled to the bottom. @@ -126,6 +126,7 @@ pub struct List { selected_index: Option, right_clicked_index: Option, _search_task: Task<()>, + _load_more_task: Task<()>, } impl List @@ -160,6 +161,7 @@ where loading: false, size: Size::default(), _search_task: Task::ready(()), + _load_more_task: Task::ready(()), } } @@ -323,27 +325,26 @@ where } /// Dispatch delegate's `load_more` method when the visible range is near the end. - fn load_more_if_need(&mut self, visible_range: Range, cx: &mut ViewContext) { - if !self.delegate.can_load_more(cx) { - return; - } - - let items_count = self.delegate.items_count(cx); + fn load_more_if_need( + &mut self, + items_count: usize, + visible_end: usize, + cx: &mut ViewContext, + ) { let threshold = self.delegate.load_more_threshold(); - if items_count < threshold { - return; - } - // Securely handle subtract logic to prevent attempt to subtract with overflow - if visible_range.end >= items_count - threshold { - cx.spawn(|view, mut cx| async move { - cx.update(|cx| { + if visible_end >= items_count.saturating_sub(threshold) { + if !self.delegate.can_load_more(cx) { + return; + } + + self._load_more_task = cx.spawn(|view, mut cx| async move { + _ = cx.update(|cx| { view.update(cx, |view, cx| { view.delegate.load_more(cx); }) - }) - }) - .detach() + }); + }); } } @@ -525,7 +526,8 @@ where uniform_list(view, "uniform-list", items_count, { move |list, visible_range, cx| { list.load_more_if_need( - visible_range.clone(), + items_count, + visible_range.end, cx, ); diff --git a/crates/ui/src/table.rs b/crates/ui/src/table.rs index b9de45e5..47a828df 100644 --- a/crates/ui/src/table.rs +++ b/crates/ui/src/table.rs @@ -15,7 +15,7 @@ use gpui::{ DragMoveEvent, Edges, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, InteractiveElement, IntoElement, KeyBinding, ListSizingBehavior, MouseButton, MouseDownEvent, ParentElement, Pixels, Point, Render, ScrollHandle, ScrollStrategy, SharedString, Stateful, - StatefulInteractiveElement as _, Styled, UniformListScrollHandle, ViewContext, + StatefulInteractiveElement as _, Styled, Task, UniformListScrollHandle, ViewContext, VisualContext as _, WindowContext, }; @@ -176,6 +176,8 @@ pub struct Table { visible_range: VisibleRangeState, /// The loading state of the table. loading: bool, + + _load_more_task: Task<()>, } #[allow(unused)] @@ -297,10 +299,11 @@ pub trait TableDelegate: Sized + 'static { /// Returns a threshold value (n rows), of course, when scrolling to the bottom, /// the remaining number of rows triggers `load_more`. + /// This should smaller than the total number of first load rows. /// - /// Default: 50 rows + /// Default: 20 rows fn load_more_threshold(&self) -> usize { - 50 + 20 } /// Load more data when the table is scrolled to the bottom. @@ -371,6 +374,7 @@ where scrollbar_visible: Edges::all(true), visible_range: VisibleRangeState::default(), loading: false, + _load_more_task: Task::ready(()), }; this.prepare_col_groups(cx); @@ -691,27 +695,26 @@ where } /// Dispatch delegate's `load_more` method when the visible range is near the end. - fn load_more_if_need(&mut self, visible_range: Range, cx: &mut ViewContext) { - if !self.delegate.can_load_more(cx) { - return; - } - - let row_count = self.delegate.rows_count(cx); + fn load_more_if_need( + &mut self, + rows_count: usize, + visible_end: usize, + cx: &mut ViewContext, + ) { let threshold = self.delegate.load_more_threshold(); - if row_count < threshold { - return; - } - // Securely handle subtract logic to prevent attempt to subtract with overflow - if visible_range.end >= row_count - threshold { - cx.spawn(|view, mut cx| async move { - cx.update(|cx| { + if visible_end >= rows_count.saturating_sub(threshold) { + if !self.delegate.can_load_more(cx) { + return; + } + + self._load_more_task = cx.spawn(|view, mut cx| async move { + _ = cx.update(|cx| { view.update(cx, |view, cx| { view.delegate.load_more(cx); }) - }) - }) - .detach() + }); + }); } } @@ -1345,7 +1348,7 @@ where rows_count + extra_rows_needed, { move |table, visible_range, cx| { - table.load_more_if_need(visible_range.clone(), cx); + table.load_more_if_need(rows_count, visible_range.end, cx); table.update_visible_range_if_need( visible_range.clone(), Axis::Vertical,