anchor_prepend/
anchor_prepend.rs

1use virtualizer_adapter::Controller;
2
3fn main() {
4    // Example: preserve visual scroll position across "prepend" (chat/timeline load older messages).
5    //
6    // The adapter flow is typically:
7    // 1) capture an anchor (key + offset_in_viewport) before data changes
8    // 2) apply data changes (count/key mapping)
9    // 3) apply the anchor to adjust scroll_offset so the same item stays in the same place
10    let mut c = Controller::new(virtualizer::VirtualizerOptions::new_with_key(
11        100,
12        |_| 1,
13        |i| 1000u64 + i as u64,
14    ));
15    c.virtualizer_mut().set_viewport_and_scroll_clamped(10, 50);
16
17    let anchor = c
18        .capture_first_visible_anchor()
19        .expect("visible range must not be empty");
20    println!(
21        "before prepend: off={} anchor={anchor:?}",
22        c.virtualizer().scroll_offset()
23    );
24
25    // Prepend 10 items; old items shift by +10 indexes.
26    c.virtualizer_mut().set_count(110);
27    c.virtualizer_mut().set_get_item_key(|i| {
28        if i < 10 {
29            2000u64 + i as u64
30        } else {
31            1000u64 + (i - 10) as u64
32        }
33    });
34    // Note: `set_count` and `set_get_item_key` rebuild per-index sizes. In real apps, call
35    // `sync_item_keys()` when your underlying dataset is reordered while `count` stays the same.
36
37    // Provide a key -> index mapping for the current dataset (owned by your adapter).
38    let ok = c.apply_anchor(&anchor, |k| {
39        if (1000..1100).contains(k) {
40            Some((*k as usize - 1000) + 10)
41        } else if (2000..2010).contains(k) {
42            Some(*k as usize - 2000)
43        } else {
44            None
45        }
46    });
47
48    println!(
49        "after prepend: ok={ok} off={}",
50        c.virtualizer().scroll_offset()
51    );
52}