use std::pin::Pin;
use std::task::{Context, Poll};
use futures_core::{ready, Stream};
use pin_project::pin_project;
use wasm_bindgen::JsCast;
use crate::events::EventStream;
use crate::keyboard::KeyboardEvent;
use crate::prelude::*;
use crate::utils;
#[derive(Debug)]
pub struct Keyboard {
_priv: (),
}
impl Keyboard {
pub fn new() -> Self {
Self { _priv: () }
}
pub fn key_down(&self) -> KeyDownStream {
KeyDownStream {
listener: utils::document().on("keydown"),
}
}
pub fn key_up(&self) -> KeyDownStream {
KeyDownStream {
listener: utils::document().on("keyup"),
}
}
}
impl Default for Keyboard {
fn default() -> Self {
Self::new()
}
}
#[pin_project]
#[derive(Debug)]
pub struct KeyDownStream {
#[pin]
listener: EventStream,
}
impl Stream for KeyDownStream {
type Item = KeyboardEvent;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.project();
let ev = ready!(this.listener.poll_next(cx));
let ev = ev.map(|ev| {
let inner = ev
.into_raw()
.dyn_into::<web_sys::KeyboardEvent>()
.unwrap_throw();
KeyboardEvent { inner }
});
Poll::Ready(ev)
}
}
#[pin_project]
#[derive(Debug)]
pub struct KeyUpStream {
#[pin]
listener: EventStream,
}
impl Stream for KeyUpStream {
type Item = KeyboardEvent;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.project();
let ev = ready!(this.listener.poll_next(cx));
let ev = ev.map(|ev| {
let inner = ev
.into_raw()
.dyn_into::<web_sys::KeyboardEvent>()
.unwrap_throw();
KeyboardEvent { inner }
});
Poll::Ready(ev)
}
}