GPUI Box GitHub

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()
}

Source: crates/gpui-kit/src/interaction/refresh.rs