perspective 2.0.0

A data visualization and analytics component, especially well-suited for large and/or streaming datasets.
////////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2018, the Perspective Authors.
//
// This file is part of the Perspective library, distributed under the terms
// of the Apache License 2.0.  The full license can be found in the LICENSE
// file.

use async_trait::async_trait;
use extend::ext;
use futures::channel::oneshot::*;
use yew::html::Scope;
use yew::prelude::*;

use super::ApiResult;

#[ext]
pub impl<T> Scope<T>
where
    T: Component,
{
    /// Send a message with a callback, then suspend until the callback is
    /// invoked.
    fn send_message_async<F, U>(&self, f: F) -> Receiver<U>
    where
        F: FnOnce(Sender<U>) -> T::Message,
    {
        let (sender, receiver) = channel::<U>();
        self.send_message(f(sender));
        receiver
    }
}

#[ext]
#[async_trait(?Send)]
pub impl<T> Callback<Sender<T>>
where
    T: 'static,
{
    /// This is "safe" because `emit()` is not called synchronously.  Normally
    /// we want this to minimize the async by doing as much work synchronous
    /// as possible (see `seng_message_async()` e.g.), but this method calls
    /// `Yew` which _never_ wants to be called synchronously.
    ///
    /// TODO Need test coverage for this - error behavior is that presize/render
    /// blocking calls are out-of-order, e.g. toggle config `presize()` call.
    /// Engineering the test to capture this faulty behavior may be difficult
    async fn emit_async_safe(&self) -> ApiResult<T> {
        let (sender, receiver) = channel::<T>();
        self.emit(sender);
        Ok(receiver.await?)
    }

    // fn emit_async(&self) -> super::ApiFuture<T> {
    //     let (sender, receiver) = channel::<T>();
    //     self.emit(sender);
    //     super::ApiFuture::new(async move { Ok(receiver.await?) })
    // }
}