feat: add full async suport

This commit is contained in:
Jonathan Kelley committed 2022-01-01 09:49:08 -05:00
1 parent 2b4e3ae6e9
commit c884f8c1b8
10 files changed
+111 -32

No files matched your search

+2
View File
@@ -15,4 +15,6 @@ hecs = "0.7.3"
ctrlc = "3.2.1" ctrlc = "3.2.1"
bumpalo = { version = "3.8.0", features = ["boxed"] } bumpalo = { version = "3.8.0", features = ["boxed"] }
stretch2 = { path = "../../Tinkering/stretch2" } stretch2 = { path = "../../Tinkering/stretch2" }
tokio = { version = "1.15.0", features = ["full"] }
futures = "0.3.19"
# stretch2 = { git = "https://github.com/elbaro/stretch2.git" } # stretch2 = { git = "https://github.com/elbaro/stretch2.git" }
-1
View File
@@ -19,7 +19,6 @@ static App: FC<()> = |cx| {
justify_content: "center", justify_content: "center",
align_items: "center", align_items: "center",
"Hello world!" "Hello world!"
} }
}) })
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+51
View File
@@ -0,0 +1,51 @@
use dioxus::prelude::*;
fn main() {
let mut dom = VirtualDom::new(app);
dom.rebuild();
rink::render_vdom(&mut dom).unwrap();
}
fn app(cx: Scope) -> Element {
let count = use_state(&cx, || 0);
use_future(&cx, || {
let set_count = count.setter();
let mut mycount = 0;
let update = cx.schedule_update();
async move {
loop {
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
mycount += 1;
set_count(mycount);
update();
}
}
});
cx.render(rsx! {
div { width: "100%",
div { width: "50%", height: "5px", background_color: "blue", justify_content: "center", align_items: "center",
"Hello {count}!"
}
div { width: "50%", height: "10px", background_color: "red", justify_content: "center", align_items: "center",
"Hello {count}!"
}
}
})
}
// use_future(&cx, || {
// let set_count = count.setter();
// let mut mycount = 0;
// let update = cx.schedule_update();
// async move {
// loop {
// tokio::time::sleep(std::time::Duration::from_millis(100)).await;
// mycount += 1;
// set_count(mycount);
// update();
// }
// }
// });
+1 -1
View File
@@ -4,7 +4,7 @@ fn main() {
let mut dom = VirtualDom::new(app); let mut dom = VirtualDom::new(app);
dom.rebuild(); dom.rebuild();
rink::render_vdom(&dom).unwrap(); rink::render_vdom(&mut dom).unwrap();
} }
fn app(cx: Scope) -> Element { fn app(cx: Scope) -> Element {
+52 -25
View File
@@ -1,14 +1,15 @@
use anyhow::Result; use anyhow::Result;
use crossterm::{ use crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyEvent}, event::{DisableMouseCapture, EnableMouseCapture, Event as TermEvent, KeyCode, KeyEvent},
execute, execute,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
}; };
use dioxus::core::exports::futures_channel::mpsc::unbounded;
use dioxus::core::*; use dioxus::core::*;
use futures::{future::Either, pin_mut, StreamExt};
use std::{ use std::{
collections::HashMap, collections::HashMap,
io, io,
sync::mpsc,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use stretch2::{prelude::Size, Stretch}; use stretch2::{prelude::Size, Stretch};
@@ -28,22 +29,10 @@ pub struct TuiNode<'a> {
pub node: &'a VNode<'a>, pub node: &'a VNode<'a>,
} }
pub fn render_vdom(vdom: &VirtualDom) -> Result<()> { pub fn render_vdom(vdom: &mut VirtualDom) -> Result<()> {
/*
Get the terminal to calcualte the layout from
*/
enable_raw_mode().unwrap();
ctrlc::set_handler(move || {
disable_raw_mode().unwrap();
})
.expect("Error setting Ctrl-C handler");
let mut stdout = std::io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap();
let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend).unwrap();
// Setup input handling // Setup input handling
let (tx, rx) = mpsc::channel(); let (tx, mut rx) = unbounded();
std::thread::spawn(move || { std::thread::spawn(move || {
let tick_rate = Duration::from_millis(100); let tick_rate = Duration::from_millis(100);
let mut last_tick = Instant::now(); let mut last_tick = Instant::now();
@@ -53,19 +42,31 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
.checked_sub(last_tick.elapsed()) .checked_sub(last_tick.elapsed())
.unwrap_or_else(|| Duration::from_secs(0)); .unwrap_or_else(|| Duration::from_secs(0));
if event::poll(timeout).unwrap() { if crossterm::event::poll(timeout).unwrap() {
if let TermEvent::Key(key) = event::read().unwrap() { let evt = crossterm::event::read().unwrap();
tx.send(InputEvent::UserInput(key)).unwrap(); tx.unbounded_send(InputEvent::UserInput(evt)).unwrap();
}
} }
if last_tick.elapsed() >= tick_rate { if last_tick.elapsed() >= tick_rate {
tx.send(InputEvent::Tick).unwrap(); tx.unbounded_send(InputEvent::Tick).unwrap();
last_tick = Instant::now(); last_tick = Instant::now();
} }
} }
}); });
tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()?
.block_on(async {
/*
Get the terminal to calcualte the layout from
*/
enable_raw_mode().unwrap();
let mut stdout = std::io::stdout();
execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap();
let backend = CrosstermBackend::new(io::stdout());
let mut terminal = Terminal::new(backend).unwrap();
terminal.clear().unwrap(); terminal.clear().unwrap();
loop { loop {
@@ -81,6 +82,9 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
use simd to compare lines for diffing? use simd to compare lines for diffing?
todo: reuse the layout and node objects.
our work_with_deadline method can tell us which nodes are dirty.
*/ */
let mut layout = Stretch::new(); let mut layout = Stretch::new();
let mut nodes = HashMap::new(); let mut nodes = HashMap::new();
@@ -106,8 +110,21 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
assert!(nodes.is_empty()); assert!(nodes.is_empty());
})?; })?;
match rx.recv()? { use futures::future::{select, Either};
InputEvent::UserInput(event) => match event.code { {
let wait = vdom.wait_for_work();
pin_mut!(wait);
match select(wait, rx.next()).await {
Either::Left((a, b)) => {
// println!("work");
}
Either::Right((evt, o)) => {
// println!("event");
match evt.unwrap() {
InputEvent::UserInput(event) => match event {
TermEvent::Key(key) => {
match key.code {
KeyCode::Char('q') => { KeyCode::Char('q') => {
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
@@ -119,6 +136,10 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
break; break;
} }
_ => {} // handle event _ => {} // handle event
}
}
TermEvent::Mouse(_) => {}
TermEvent::Resize(_, _) => {}
}, },
InputEvent::Tick => {} // tick InputEvent::Tick => {} // tick
InputEvent::Close => { InputEvent::Close => {
@@ -126,6 +147,11 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
} }
}; };
} }
}
}
vdom.work_with_deadline(|| false);
}
disable_raw_mode()?; disable_raw_mode()?;
execute!( execute!(
@@ -136,10 +162,11 @@ pub fn render_vdom(vdom: &VirtualDom) -> Result<()> {
terminal.show_cursor()?; terminal.show_cursor()?;
Ok(()) Ok(())
})
} }
enum InputEvent { enum InputEvent {
UserInput(KeyEvent), UserInput(TermEvent),
Close, Close,
Tick, Tick,
} }