Components / interaction
PullToRefresh view
Retains its caller-built content in every state, including a failed refresh. The supplied scroll handle must be the handle used by that content.
A view survives a frame. Hold it in an Entity with cx.new(..) and reach it with .update(..).
use gpui_kit::interaction::refresh::PullToRefresh;
Reviewed in pull-to-refresh.
Construct
new(ident: impl Into<Ident>, scroll: ScrollHandle, label: impl Into<SharedString>, armed_label: impl Into<SharedString>) -> Self
Commands
Need a Context, so they need a view.
set_content(body: Option<Body>, cx: &mut Context<Self>)
set_state(state: RefreshState, cx: &mut Context<Self>)
set_enabled(enabled: bool, cx: &mut Context<Self>)
set_threshold(threshold: f32, cx: &mut Context<Self>) -> bool
Reports
The variants of the event it emits. It never applies the change itself.
- RefreshRequested
Example · pull-to-refresh
fn pull_to_refresh(_window: &mut Window, cx: &mut App) -> AnyElement {
if !cx.has_global::<SceneRefresh>() {
let states = [
("ready", RefreshState::Ready),
(
"pending",
RefreshState::Pending("Waiting for caller".into()),
),
(
"loading",
RefreshState::Loading("Refreshing fixture".into()),
),
(
"error",
RefreshState::Error("Refresh failed · retained rows".into()),
),
];
let mut views = Vec::new();
for (id, state) in states {
let scroll = gpui::ScrollHandle::new();
let view = cx.new(|_| {
PullToRefresh::new(
format!("scene.refresh.{id}"),
scroll.clone(),
"Refresh",
"Release to refresh",
)
});
view.update(cx, |refresh, cx| {
refresh.set_state(state, cx);
refresh.set_content(
Some(Rc::new(move |_, cx| {
let theme = cx.theme().clone();
div()
.id(SharedString::from(format!("scene.refresh.{id}.scroll")))
.column()
.size_full()
.overflow_y_scroll()
.track_scroll(&scroll)
.children(
[
("notes", "Notes · verified fixture"),
("draft", "Draft · verified fixture"),
("archive", "Archive · verified fixture"),
("saved", "Saved · verified fixture"),
]
.into_iter()
.map(|(key, label)| {
div()
.h(px(64.0))
.flex_none()
.p_token(&theme, Space::Sm)
.child(crate::foundation::text(
&theme,
TypeScale::Body,
label,
))
.semantic_in(
cx,
NodeSpec::new(
format!("scene.refresh.{id}.{key}"),
Role::Group,
)
.text(label),
)
}),
)
.into_any_element()
})),
cx,
);
});
views.push(view);
}
cx.set_global(SceneRefresh(views));
}
let theme = cx.theme().clone();
stack(&theme)
.w_full()
.child(caption(
&theme,
"Fixture states · refreshing never replaces the verified rows",
))
.child(
row(&theme).items_start().children(
cx.global::<SceneRefresh>()
.0
.iter()
.map(|view| div().w(px(250.0)).h(px(370.0)).child(view.clone())),
),
)
.into_any_element()
}