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
+4
-3
@@ -10,11 +10,12 @@ tui = { version = "0.16.0", features = ["crossterm"] }
|
|||||||
crossterm = "0.22.1"
|
crossterm = "0.22.1"
|
||||||
anyhow = "1.0.42"
|
anyhow = "1.0.42"
|
||||||
thiserror = "1.0.24"
|
thiserror = "1.0.24"
|
||||||
dioxus = { path = "../../dioxus" }
|
# dioxus = { path = "../../dioxus" }
|
||||||
|
dioxus = { version = "0.1.7" }
|
||||||
hecs = "0.7.3"
|
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"] }
|
tokio = { version = "1.15.0", features = ["full"] }
|
||||||
futures = "0.3.19"
|
futures = "0.3.19"
|
||||||
# stretch2 = { git = "https://github.com/elbaro/stretch2.git" }
|
stretch2 = { git = "https://github.com/DioxusLabs/stretch" }
|
||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use crossterm::event::KeyEvent;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
use rink::InputHandler;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
rink::launch(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app(cx: Scope) -> Element {
|
||||||
|
let count = use_state(&cx, || 0);
|
||||||
|
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
width: "100%",
|
||||||
|
height: "10px",
|
||||||
|
background_color: "red",
|
||||||
|
justify_content: "center",
|
||||||
|
align_items: "center",
|
||||||
|
"Hello world!",
|
||||||
|
|
||||||
|
// todo: enabling this will panic
|
||||||
|
// rink::InputHandler {
|
||||||
|
// onkeydown: move |evt: KeyEvent| {
|
||||||
|
// use crossterm::event::KeyCode::*;
|
||||||
|
// match evt.code {
|
||||||
|
// Left => count += 1,
|
||||||
|
// Right => count -= 1,
|
||||||
|
// Up => count += 10,
|
||||||
|
// Down => count -= 10,
|
||||||
|
// _ => {},
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// onmousedown: move |evt| {},
|
||||||
|
// onresize: move |dims| {
|
||||||
|
// println!("{:?}", dims);
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app2<'a>(cx: Scope<'a>) -> Element<'a> {
|
||||||
|
let mut count = use_state(&cx, || 0);
|
||||||
|
|
||||||
|
cx.render(rsx! {
|
||||||
|
div {
|
||||||
|
width: "100%",
|
||||||
|
height: "10px",
|
||||||
|
background_color: "red",
|
||||||
|
justify_content: "center",
|
||||||
|
align_items: "center",
|
||||||
|
oninput: move |_| count += 1,
|
||||||
|
"Hello world!",
|
||||||
|
h1 {},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
+3
-12
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
@@ -16,44 +13,38 @@ fn app(cx: Scope) -> Element {
|
|||||||
background_color: "black",
|
background_color: "black",
|
||||||
// margin_right: "10px",
|
// margin_right: "10px",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
div {
|
div {
|
||||||
width: "70%",
|
width: "70%",
|
||||||
height: "70%",
|
height: "70%",
|
||||||
// margin_left: "4px",
|
|
||||||
background_color: "green",
|
background_color: "green",
|
||||||
|
// margin_left: "4px",
|
||||||
|
|
||||||
div {
|
div {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%",
|
||||||
|
|
||||||
|
|
||||||
margin_top: "2px",
|
margin_top: "2px",
|
||||||
margin_bottom: "2px",
|
margin_bottom: "2px",
|
||||||
margin_left: "2px",
|
margin_left: "2px",
|
||||||
margin_right: "2px",
|
margin_right: "2px",
|
||||||
// flex_shrink: "0",
|
flex_shrink: "0",
|
||||||
|
|
||||||
background_color: "red",
|
background_color: "red",
|
||||||
justify_content: "center",
|
justify_content: "center",
|
||||||
align_items: "center",
|
align_items: "center",
|
||||||
flex_direction: "column",
|
flex_direction: "column",
|
||||||
|
|
||||||
|
|
||||||
// padding_top: "2px",
|
// padding_top: "2px",
|
||||||
// padding_bottom: "2px",
|
// padding_bottom: "2px",
|
||||||
// padding_left: "4px",
|
// padding_left: "4px",
|
||||||
// padding_right: "4px",
|
// padding_right: "4px",
|
||||||
|
|
||||||
|
|
||||||
"[A]"
|
"[A]"
|
||||||
"[A]"
|
"[A]"
|
||||||
"[A]"
|
"[A]"
|
||||||
"[A]"
|
"[A]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
+1
-4
@@ -1,10 +1,7 @@
|
|||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut dom = VirtualDom::new(app);
|
rink::launch(app);
|
||||||
dom.rebuild();
|
|
||||||
|
|
||||||
rink::render_vdom(&mut dom).unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn app(cx: Scope) -> Element {
|
fn app(cx: Scope) -> Element {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
div {
|
||||||
|
div {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+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 {
|
for el in el.children {
|
||||||
let ite = ElementIdIterator::new(vdom, el);
|
let ite = ElementIdIterator::new(vdom, el);
|
||||||
for node in ite {
|
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);
|
collect_layout(layout, nodes, vdom, child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VNode::Component(_) => todo!(),
|
VNode::Component(sc) => {
|
||||||
VNode::Placeholder(_) => todo!(),
|
//
|
||||||
|
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,
|
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::exports::futures_channel::mpsc::unbounded, prelude::Props};
|
||||||
use dioxus::core::*;
|
use dioxus::{core::*, prelude::*};
|
||||||
use futures::{future::Either, pin_mut, StreamExt};
|
use futures::{
|
||||||
|
channel::mpsc::{UnboundedReceiver, UnboundedSender},
|
||||||
|
future::Either,
|
||||||
|
pin_mut, StreamExt,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
|
cell::Cell,
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
io,
|
io,
|
||||||
|
rc::Rc,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
use stretch2::{prelude::Size, Stretch};
|
use stretch2::{prelude::Size, Stretch};
|
||||||
use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal};
|
use tui::{backend::CrosstermBackend, style::Style as TuiStyle, Terminal};
|
||||||
|
|
||||||
mod attributes;
|
mod attributes;
|
||||||
|
mod hooks;
|
||||||
mod layout;
|
mod layout;
|
||||||
mod render;
|
mod render;
|
||||||
|
|
||||||
pub use attributes::*;
|
pub use attributes::*;
|
||||||
|
pub use hooks::*;
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
pub use render::*;
|
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 struct TuiNode<'a> {
|
||||||
pub layout: stretch2::node::Node,
|
pub layout: stretch2::node::Node,
|
||||||
pub block_style: TuiStyle,
|
pub block_style: TuiStyle,
|
||||||
pub node: &'a VNode<'a>,
|
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
|
// Setup input handling
|
||||||
let (tx, mut rx) = unbounded();
|
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();
|
||||||
@@ -117,35 +134,27 @@ pub fn render_vdom(vdom: &mut VirtualDom) -> Result<()> {
|
|||||||
|
|
||||||
match select(wait, rx.next()).await {
|
match select(wait, rx.next()).await {
|
||||||
Either::Left((a, b)) => {
|
Either::Left((a, b)) => {
|
||||||
// println!("work");
|
//
|
||||||
}
|
}
|
||||||
Either::Right((evt, o)) => {
|
Either::Right((evt, o)) => {
|
||||||
// println!("event");
|
//
|
||||||
match evt.unwrap() {
|
match evt.as_ref().unwrap() {
|
||||||
InputEvent::UserInput(event) => match event {
|
InputEvent::UserInput(event) => match event {
|
||||||
TermEvent::Key(key) => {
|
TermEvent::Key(key) => {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Char('q') => {
|
KeyCode::Char('q') => break,
|
||||||
disable_raw_mode()?;
|
|
||||||
execute!(
|
|
||||||
terminal.backend_mut(),
|
|
||||||
LeaveAlternateScreen,
|
|
||||||
DisableMouseCapture
|
|
||||||
)?;
|
|
||||||
terminal.show_cursor()?;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
_ => {} // handle event
|
_ => {} // handle event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TermEvent::Mouse(_) => {}
|
TermEvent::Resize(_, _) | TermEvent::Mouse(_) => {}
|
||||||
TermEvent::Resize(_, _) => {}
|
|
||||||
},
|
},
|
||||||
InputEvent::Tick => {} // tick
|
InputEvent::Tick => {} // tick
|
||||||
InputEvent::Close => {
|
InputEvent::Close => break,
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let InputEvent::UserInput(evt) = evt.unwrap() {
|
||||||
|
ctx.unbounded_send(evt).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user