1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
use std::cell::{Ref, RefCell};
use std::collections::VecDeque;
use std::hash::Hash;
use std::rc::Rc;
use yew::prelude::*;
use super::use_update;
/// State handle for the [`use_queue`] hook.
pub struct UseQueueHandle<T> {
inner: Rc<RefCell<VecDeque<T>>>,
update: Rc<dyn Fn()>,
}
impl<T> UseQueueHandle<T> {
/// Get immutable ref to the queue.
///
/// # Panics
///
/// Panics if the value is currently mutably borrowed
pub fn current(&self) -> Ref<VecDeque<T>> {
self.inner.borrow()
}
/// Set the queue.
pub fn set(&self, queue: VecDeque<T>) {
*self.inner.borrow_mut() = queue;
(self.update)();
}
/// Appends an element to the back of the queue.
pub fn push_back(&self, value: T)
where
T: Eq + Hash,
{
self.inner.borrow_mut().push_back(value);
(self.update)();
}
/// Removes the first element and returns it, or None if the queue is empty.
pub fn pop_front(&self) -> Option<T>
where
T: Eq + Hash,
{
let v = self.inner.borrow_mut().pop_front();
(self.update)();
v
}
/// Retains only the elements specified by the predicate.
pub fn retain<F>(&self, f: F)
where
T: Eq + Hash,
F: FnMut(&T) -> bool,
{
self.inner.borrow_mut().retain(f);
(self.update)();
}
/// Clears the queue, removing all values.
pub fn clear(&self) {
self.inner.borrow_mut().clear();
(self.update)();
}
}
impl<T> Clone for UseQueueHandle<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
update: self.update.clone(),
}
}
}
impl<T> PartialEq for UseQueueHandle<T>
where
T: Eq + Hash,
{
fn eq(&self, other: &Self) -> bool {
*self.inner == *other.inner
}
}
/// A hook that tracks a queue and provides methods to modify it.
///
/// # Example
///
/// ```rust
/// # use std::collections::VecDeque;
/// # use yew::prelude::*;
/// #
/// use yew_hooks::use_queue;
///
/// #[function_component(UseQueue)]
/// fn queue() -> Html {
/// let queue = use_queue(VecDeque::from(["Mercury", "Venus", "Earth", "Mars"]));
///
/// let onset = {
/// let queue = queue.clone();
/// Callback::from(move |_| queue.set(VecDeque::from(["Moon", "Earth"])))
/// };
/// let onpush_back = {
/// let queue = queue.clone();
/// Callback::from(move |_| {
/// queue.push_back("Jupiter");
/// })
/// };
/// let onpop_front = {
/// let queue = queue.clone();
/// Callback::from(move |_| {
/// let _ = queue.pop_front();
/// })
/// };
/// let onretain = {
/// let queue = queue.clone();
/// Callback::from(move |_| queue.retain(|v| v.contains('a')))
/// };
/// let onclear = {
/// let queue = queue.clone();
/// Callback::from(move |_| queue.clear())
/// };
///
/// html! {
/// <div>
/// <button onclick={onset}>{ "Set" }</button>
/// <button onclick={onpush_back}>{ "Push back" }</button>
/// <button onclick={onpop_front}>{ "Pop front" }</button>
/// <button onclick={onretain}>{ "Retain" }</button>
/// <button onclick={onclear}>{ "Clear all" }</button>
/// <p>
/// <b>{ "Current value: " }</b>
/// </p>
/// {
/// for queue.current().iter().map(|v| {
/// html! {
/// <p><b>{ v }</b></p>
/// }
/// })
/// }
/// </div>
/// }
/// }
/// ```
pub fn use_queue<T>(initial_value: VecDeque<T>) -> UseQueueHandle<T>
where
T: 'static,
{
let inner = use_mut_ref(|| initial_value);
let update = use_update();
UseQueueHandle { inner, update }
}