updates: move to stable versions
This commit is contained in:
1 parent
c884f8c1b8
commit
395558232e
13 files changed
+233
-65
No files matched your search
+104
@@ -0,0 +1,104 @@
|
||||
use anyhow::Result;
|
||||
use crossterm::{
|
||||
event::{
|
||||
DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyEvent, MouseEvent,
|
||||
},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use dioxus::{core::exports::futures_channel::mpsc::unbounded, prelude::Props};
|
||||
use dioxus::{core::*, prelude::*};
|
||||
use futures::{channel::mpsc::UnboundedReceiver, future::Either, pin_mut, StreamExt};
|
||||
use std::{
|
||||
cell::{Cell, RefCell},
|
||||
collections::HashMap,
|
||||
io,
|
||||
rc::Rc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use stretch2::{prelude::Size, Stretch};
|
||||
use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal};
|
||||
|
||||
pub struct RinkContext {
|
||||
last_event: RefCell<Option<TermEvent>>,
|
||||
receiver: Rc<Cell<Option<UnboundedReceiver<TermEvent>>>>,
|
||||
}
|
||||
|
||||
impl RinkContext {
|
||||
pub fn new(receiver: UnboundedReceiver<TermEvent>) -> Self {
|
||||
Self {
|
||||
last_event: RefCell::new(None),
|
||||
receiver: Rc::new(Cell::new(Some(receiver))),
|
||||
}
|
||||
}
|
||||
pub fn subscribe_to_events(&self, scope: ScopeId) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
pub struct AppHandlerProps<'a> {
|
||||
// #[props(setter(strip_option), default)]
|
||||
onkeydown: EventHandler<'a, KeyEvent>,
|
||||
|
||||
// #[props(setter(strip_option), default)]
|
||||
onmousedown: EventHandler<'a, MouseEvent>,
|
||||
|
||||
#[props(setter(strip_option), default)]
|
||||
onresize: Option<EventHandler<'a, (u16, u16)>>,
|
||||
}
|
||||
|
||||
/// This component lets you handle input events
|
||||
///
|
||||
/// Once attached to the DOM, it will listen for input events from the terminal
|
||||
///
|
||||
///
|
||||
pub fn InputHandler<'a>(cx: Scope<'a, AppHandlerProps<'a>>) -> Element {
|
||||
let rcx = cx.use_hook(|_| {
|
||||
let rcx = cx
|
||||
.consume_context::<RinkContext>()
|
||||
.unwrap_or_else(|| panic!("Rink InputHandlers can only be used in Rink apps!"));
|
||||
|
||||
// our component will only re-render if new events are received ... or if the parent is updated
|
||||
// todo: if update was not caused by a new event, we should not re-render
|
||||
// perhaps add some tracking to context?
|
||||
rcx.subscribe_to_events(cx.scope_id());
|
||||
|
||||
let mut rec = rcx.receiver.take().unwrap();
|
||||
let updater = cx.schedule_update();
|
||||
let rc2 = rcx.clone();
|
||||
cx.push_future(async move {
|
||||
while let Some(evt) = rec.next().await {
|
||||
rc2.last_event.borrow_mut().replace(evt);
|
||||
println!("{:?}", evt);
|
||||
updater();
|
||||
}
|
||||
//
|
||||
});
|
||||
|
||||
rcx
|
||||
});
|
||||
|
||||
if let Some(evet) = rcx.last_event.borrow().as_ref() {
|
||||
match evet {
|
||||
TermEvent::Key(key) => {
|
||||
cx.props.onkeydown.call(key.clone());
|
||||
// let mut handler = cx.props.keydown.borrow_mut();
|
||||
// handler(*key);
|
||||
// if let Some(handler) = cx.props.onkeydown {
|
||||
// handler(*key);
|
||||
// }
|
||||
}
|
||||
TermEvent::Mouse(mouse) => {
|
||||
cx.props.onmousedown.call(mouse.clone());
|
||||
}
|
||||
TermEvent::Resize(x, y) => {
|
||||
// if let Some(handler) = cx.props.onresize {
|
||||
// handler((*x, *y));
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
+20
-3
@@ -67,7 +67,17 @@ pub fn collect_layout<'a>(
|
||||
for el in el.children {
|
||||
let ite = ElementIdIterator::new(vdom, el);
|
||||
for node in ite {
|
||||
child_layout.push(nodes[&node.mounted_id()].layout)
|
||||
match node {
|
||||
VNode::Element(_) | VNode::Text(_) => {
|
||||
//
|
||||
child_layout.push(nodes[&node.mounted_id()].layout)
|
||||
}
|
||||
VNode::Placeholder(_) => {}
|
||||
VNode::Fragment(_) => todo!(),
|
||||
VNode::Component(_) => todo!(),
|
||||
}
|
||||
|
||||
// child_layout.push(nodes[&node.mounted_id()].layout)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,7 +96,14 @@ pub fn collect_layout<'a>(
|
||||
collect_layout(layout, nodes, vdom, child);
|
||||
}
|
||||
}
|
||||
VNode::Component(_) => todo!(),
|
||||
VNode::Placeholder(_) => todo!(),
|
||||
VNode::Component(sc) => {
|
||||
//
|
||||
let scope = vdom.get_scope(sc.scope.get().unwrap()).unwrap();
|
||||
let root = scope.root_node();
|
||||
collect_layout(layout, nodes, vdom, root);
|
||||
}
|
||||
VNode::Placeholder(_) => {
|
||||
//
|
||||
}
|
||||
};
|
||||
}
|
||||
+32
-23
@@ -4,35 +4,52 @@ use crossterm::{
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use dioxus::core::exports::futures_channel::mpsc::unbounded;
|
||||
use dioxus::core::*;
|
||||
use futures::{future::Either, pin_mut, StreamExt};
|
||||
use dioxus::{core::exports::futures_channel::mpsc::unbounded, prelude::Props};
|
||||
use dioxus::{core::*, prelude::*};
|
||||
use futures::{
|
||||
channel::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||
future::Either,
|
||||
pin_mut, StreamExt,
|
||||
};
|
||||
use std::{
|
||||
cell::Cell,
|
||||
collections::HashMap,
|
||||
io,
|
||||
rc::Rc,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use stretch2::{prelude::Size, Stretch};
|
||||
use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal};
|
||||
|
||||
mod attributes;
|
||||
mod hooks;
|
||||
mod layout;
|
||||
mod render;
|
||||
|
||||
pub use attributes::*;
|
||||
pub use hooks::*;
|
||||
pub use layout::*;
|
||||
pub use render::*;
|
||||
|
||||
pub fn launch(app: Component<()>) {
|
||||
let mut dom = VirtualDom::new(app);
|
||||
let (tx, rx) = unbounded();
|
||||
|
||||
dom.base_scope().provide_context(RinkContext::new(rx));
|
||||
dom.rebuild();
|
||||
|
||||
render_vdom(&mut dom, tx).unwrap();
|
||||
}
|
||||
|
||||
pub struct TuiNode<'a> {
|
||||
pub layout: stretch2::node::Node,
|
||||
pub block_style: TuiStyle,
|
||||
pub node: &'a VNode<'a>,
|
||||
}
|
||||
|
||||
pub fn render_vdom(vdom: &mut VirtualDom) -> Result<()> {
|
||||
pub fn render_vdom(vdom: &mut VirtualDom, ctx: UnboundedSender<TermEvent>) -> Result<()> {
|
||||
// Setup input handling
|
||||
let (tx, mut rx) = unbounded();
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let tick_rate = Duration::from_millis(100);
|
||||
let mut last_tick = Instant::now();
|
||||
@@ -117,35 +134,27 @@ pub fn render_vdom(vdom: &mut VirtualDom) -> Result<()> {
|
||||
|
||||
match select(wait, rx.next()).await {
|
||||
Either::Left((a, b)) => {
|
||||
// println!("work");
|
||||
//
|
||||
}
|
||||
Either::Right((evt, o)) => {
|
||||
// println!("event");
|
||||
match evt.unwrap() {
|
||||
//
|
||||
match evt.as_ref().unwrap() {
|
||||
InputEvent::UserInput(event) => match event {
|
||||
TermEvent::Key(key) => {
|
||||
match key.code {
|
||||
KeyCode::Char('q') => {
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
break;
|
||||
}
|
||||
KeyCode::Char('q') => break,
|
||||
_ => {} // handle event
|
||||
}
|
||||
}
|
||||
TermEvent::Mouse(_) => {}
|
||||
TermEvent::Resize(_, _) => {}
|
||||
TermEvent::Resize(_, _) | TermEvent::Mouse(_) => {}
|
||||
},
|
||||
InputEvent::Tick => {} // tick
|
||||
InputEvent::Close => {
|
||||
break;
|
||||
}
|
||||
InputEvent::Close => break,
|
||||
};
|
||||
|
||||
if let InputEvent::UserInput(evt) = evt.unwrap() {
|
||||
ctx.unbounded_send(evt).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user