-
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Try out new design * Impl View for tuples * Create use_ref hook * Re-import web code and refactor * Clean up
- Loading branch information
Showing
25 changed files
with
324 additions
and
983 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,74 @@ | ||
use concoct::{ | ||
hook::{use_context, use_on_drop, use_provider, use_ref}, | ||
TextViewContext, View, ViewBuilder, | ||
hook::{use_context, use_provider, use_ref}, | ||
Scope, TextViewContext, View, | ||
}; | ||
use std::{cell::RefCell, rc::Rc}; | ||
use web_sys::{Document, Node, Text, Window}; | ||
use rustc_hash::FxHasher; | ||
use std::{ | ||
cell::Cell, | ||
hash::{Hash, Hasher}, | ||
rc::Rc, | ||
}; | ||
use web_sys::{Document, HtmlElement, Window}; | ||
|
||
pub mod html; | ||
|
||
struct WebContext { | ||
window: Window, | ||
document: Document, | ||
parent: Node, | ||
body: HtmlElement, | ||
parent: HtmlElement, | ||
} | ||
|
||
struct WebRoot<VB> { | ||
pub body: Rc<VB>, | ||
pub struct HtmlRoot<C> { | ||
content: C, | ||
} | ||
|
||
impl<VB: ViewBuilder> ViewBuilder for WebRoot<VB> { | ||
fn build(&self) -> impl View { | ||
let window = web_sys::window().unwrap(); | ||
let document = window.document().unwrap(); | ||
let body = document.body().unwrap(); | ||
|
||
use_provider(WebContext { | ||
window, | ||
document, | ||
parent: body.into(), | ||
impl<T: 'static, A: 'static, C: View<T, A>> View<T, A> for HtmlRoot<C> { | ||
fn body(&mut self, cx: &Scope<T, A>) -> impl View<T, A> { | ||
use_provider(cx, || { | ||
let window = web_sys::window().unwrap(); | ||
let document = window.document().unwrap(); | ||
let body = document.body().unwrap(); | ||
WebContext { | ||
window, | ||
document, | ||
body: body.clone(), | ||
parent: body, | ||
} | ||
}); | ||
|
||
use_provider(TextViewContext::new(|s| { | ||
let web_cx = use_context::<WebContext>().unwrap(); | ||
use_provider(cx, || { | ||
TextViewContext::new(|cx: &Scope<T, A>, s| { | ||
let web_cx: Rc<WebContext> = use_context(cx); | ||
|
||
let data = use_ref(|| RefCell::new((s.clone(), None::<Text>))); | ||
let (last, node_cell) = &mut *data.borrow_mut(); | ||
let mut is_init = false; | ||
let (hash_cell, node) = use_ref(cx, || { | ||
let elem = web_cx.document.create_text_node(s); | ||
web_cx.parent.append_child(&elem).unwrap(); | ||
|
||
let data_clone = data.clone(); | ||
use_on_drop(move || { | ||
if let Some(node) = &data_clone.borrow_mut().1 { | ||
node.remove(); | ||
} | ||
}); | ||
let mut hasher = FxHasher::default(); | ||
s.hash(&mut hasher); | ||
let hash = hasher.finish(); | ||
|
||
is_init = true; | ||
(Cell::new(hash), elem) | ||
}); | ||
|
||
if !is_init { | ||
let mut hasher = FxHasher::default(); | ||
s.hash(&mut hasher); | ||
let hash = hasher.finish(); | ||
|
||
if let Some(node) = node_cell { | ||
if s != *last { | ||
node.set_text_content(Some(&s)); | ||
*last = s.clone(); | ||
let last_hash = hash_cell.get(); | ||
hash_cell.set(hash); | ||
|
||
if hash != last_hash { | ||
node.set_text_content(Some(s)); | ||
} | ||
} | ||
} else { | ||
let node = web_cx.document.create_text_node(&s); | ||
web_cx.parent.append_child(&node).unwrap(); | ||
*node_cell = Some(node); | ||
} | ||
})); | ||
}) | ||
}); | ||
|
||
self.body.clone() | ||
&mut self.content | ||
} | ||
} | ||
|
||
pub async fn run(view: impl ViewBuilder) { | ||
concoct::run(WebRoot { | ||
body: Rc::new(view), | ||
}) | ||
.await; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
use concoct::{Scope, View, VirtualDom}; | ||
|
||
struct Child; | ||
|
||
impl View<Counter> for Child { | ||
fn body(&mut self, cx: &Scope<Counter>) -> impl View<Counter> { | ||
dbg!(cx.key); | ||
} | ||
} | ||
|
||
struct Counter; | ||
|
||
impl View<Self> for Counter { | ||
fn body(&mut self, _cx: &Scope<Self>) -> impl View<Self> { | ||
dbg!("view"); | ||
(Child, Child) | ||
} | ||
} | ||
|
||
fn main() { | ||
let mut app = VirtualDom::new(Counter); | ||
app.build(); | ||
app.rebuild(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,8 @@ | ||
//! Hooks to access render context. | ||
|
||
mod use_context; | ||
pub use use_context::{use_context, use_provider}; | ||
pub use self::use_context::use_context; | ||
|
||
mod use_effect; | ||
pub use self::use_effect::use_effect; | ||
mod use_provider; | ||
pub use self::use_provider::use_provider; | ||
|
||
mod use_ref; | ||
pub use use_ref::use_ref; | ||
|
||
mod use_state; | ||
pub use use_state::use_state; | ||
|
||
mod use_on_drop; | ||
pub use use_on_drop::use_on_drop; | ||
pub use self::use_ref::use_ref; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,8 @@ | ||
use crate::Runtime; | ||
use crate::Scope; | ||
use std::{any::TypeId, rc::Rc}; | ||
|
||
/// Hook to provide a context. | ||
pub fn use_provider<T: 'static>(value: T) { | ||
let cx = Runtime::current(); | ||
let cx_ref = cx.inner.borrow(); | ||
let mut scope = cx_ref.scope.as_ref().unwrap().inner.borrow_mut(); | ||
|
||
scope.contexts.insert(TypeId::of::<T>(), Rc::new(value)); | ||
} | ||
|
||
/// Hook to get a context from its type. | ||
pub fn use_context<T: 'static>() -> Option<Rc<T>> { | ||
Runtime::current() | ||
.inner | ||
.borrow() | ||
.scope | ||
.as_ref() | ||
.unwrap() | ||
.inner | ||
.borrow() | ||
.contexts | ||
.get(&TypeId::of::<T>()) | ||
.map(|rc| Rc::downcast(rc.clone()).unwrap()) | ||
pub fn use_context<T, A, R: 'static>(cx: &Scope<T, A>) -> Rc<R> { | ||
let contexts = cx.contexts.borrow(); | ||
let rc = contexts.get(&TypeId::of::<R>()).unwrap(); | ||
Rc::downcast(rc.clone()).unwrap() | ||
} |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
use crate::Scope; | ||
use std::{any::TypeId, rc::Rc}; | ||
|
||
use super::use_ref; | ||
|
||
pub fn use_provider<T, A, R: 'static>(cx: &Scope<T, A>, make_initial: impl FnOnce() -> R) { | ||
use_ref(cx, || { | ||
cx.contexts | ||
.borrow_mut() | ||
.insert(TypeId::of::<R>(), Rc::new(make_initial())) | ||
}); | ||
} |
Oops, something went wrong.