table: Add load_more delegate method and called when scrolled near the bottom. (#183)
https://github.com/user-attachments/assets/03001a21-6a3d-4c06-a00c-9dea8208e357
This commit is contained in:
parent
a5217df13e
commit
237b0f6956
2 changed files with 86 additions and 4 deletions
|
|
@ -1,12 +1,16 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use fake::Fake;
|
||||
use gpui::{
|
||||
div, img, IntoElement, ParentElement, Pixels, Render, SharedString, Styled, View, ViewContext,
|
||||
VisualContext as _, WindowContext,
|
||||
div, img, IntoElement, ParentElement, Pixels, Render, SharedString, Styled, Timer, View,
|
||||
ViewContext, VisualContext as _, WindowContext,
|
||||
};
|
||||
use ui::{
|
||||
checkbox::Checkbox,
|
||||
h_flex,
|
||||
indicator::Indicator,
|
||||
label::Label,
|
||||
prelude::FluentBuilder as _,
|
||||
table::{ColSort, Table, TableDelegate, TableEvent},
|
||||
theme::ActiveTheme as _,
|
||||
v_flex, Icon, IconName, Selectable,
|
||||
|
|
@ -84,6 +88,8 @@ struct CustomerTableDelegate {
|
|||
col_order: bool,
|
||||
col_sort: bool,
|
||||
col_selection: bool,
|
||||
loading: bool,
|
||||
is_eof: bool,
|
||||
}
|
||||
|
||||
impl CustomerTableDelegate {
|
||||
|
|
@ -111,6 +117,8 @@ impl CustomerTableDelegate {
|
|||
col_order: true,
|
||||
col_sort: true,
|
||||
col_selection: true,
|
||||
loading: false,
|
||||
is_eof: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -322,6 +330,32 @@ impl TableDelegate for CustomerTableDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn can_load_more(&self) -> bool {
|
||||
return !self.loading && !self.is_eof;
|
||||
}
|
||||
|
||||
fn load_more_threshold(&self) -> usize {
|
||||
150
|
||||
}
|
||||
|
||||
fn load_more(&mut self, cx: &mut ViewContext<Table<Self>>) {
|
||||
self.loading = true;
|
||||
|
||||
cx.spawn(|view, mut cx| async move {
|
||||
// Simulate network request, delay 1s to load data.
|
||||
Timer::after(Duration::from_secs(1)).await;
|
||||
|
||||
cx.update(|cx| {
|
||||
let _ = view.update(cx, |view, _| {
|
||||
view.delegate_mut().customers.extend(randome_customers(200));
|
||||
view.delegate_mut().loading = false;
|
||||
view.delegate_mut().is_eof = view.delegate().customers.len() >= 6000;
|
||||
});
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TableStory {
|
||||
|
|
@ -438,7 +472,12 @@ impl Render for TableStory {
|
|||
.label("Column Selection")
|
||||
.selected(delegate.col_selection)
|
||||
.on_click(cx.listener(Self::toggle_col_selection)),
|
||||
),
|
||||
)
|
||||
.when(delegate.loading, |this| {
|
||||
this.child(h_flex().gap_1().child(Indicator::new()).child("Loading..."))
|
||||
})
|
||||
.child(format!("Total Rows: {}", delegate.rows_count()))
|
||||
.when(delegate.is_eof, |this| this.child("Is loaded all data.")),
|
||||
)
|
||||
.child(self.table.clone())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use std::{cell::Cell, rc::Rc};
|
||||
use std::{cell::Cell, ops::Range, rc::Rc};
|
||||
|
||||
use crate::{
|
||||
h_flex,
|
||||
|
|
@ -198,6 +198,29 @@ pub trait TableDelegate: Sized + 'static {
|
|||
.child(Icon::new(IconName::Inbox).size_12())
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
/// Return true to enable load more data when scrolling to the bottom.
|
||||
///
|
||||
/// Default: true
|
||||
fn can_load_more(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
/// Returns a threshold value (n rows), of course, when scrolling to the bottom,
|
||||
/// the remaining number of rows triggers `load_more`.
|
||||
///
|
||||
/// Default: 50 rows
|
||||
fn load_more_threshold(&self) -> usize {
|
||||
50
|
||||
}
|
||||
|
||||
/// Load more data when the table is scrolled to the bottom.
|
||||
///
|
||||
/// This will performed in a background task.
|
||||
///
|
||||
/// This is always called when the table is near the bottom,
|
||||
/// so you must check if there is more data to load or lock the loading state.
|
||||
fn load_more(&mut self, cx: &mut ViewContext<Table<Self>>) {}
|
||||
}
|
||||
|
||||
impl<D> Table<D>
|
||||
|
|
@ -650,6 +673,24 @@ where
|
|||
})
|
||||
}
|
||||
|
||||
/// Dispatch delegate's `load_more` method when the visible range is near the end.
|
||||
fn load_more(&mut self, visible_range: Range<usize>, cx: &mut ViewContext<Self>) {
|
||||
if !self.delegate.can_load_more() {
|
||||
return;
|
||||
}
|
||||
|
||||
if visible_range.end >= self.delegate.rows_count() - self.delegate.load_more_threshold() {
|
||||
cx.spawn(|view, mut cx| async move {
|
||||
cx.update(|cx| {
|
||||
view.update(cx, |view, cx| {
|
||||
view.delegate.load_more(cx);
|
||||
})
|
||||
})
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
}
|
||||
|
||||
fn move_col(&mut self, col_ix: usize, to_ix: usize, cx: &mut ViewContext<Self>) {
|
||||
if col_ix == to_ix {
|
||||
return;
|
||||
|
|
@ -746,6 +787,8 @@ where
|
|||
uniform_list(view, "table-uniform-list", rows_count, {
|
||||
let horizontal_scroll_handle = horizontal_scroll_handle.clone();
|
||||
move |table, visible_range, cx| {
|
||||
table.load_more(visible_range.clone(), cx);
|
||||
|
||||
visible_range
|
||||
.map(|row_ix| {
|
||||
table
|
||||
|
|
|
|||
Loading…
Reference in a new issue