Compare commits

...

2 Commits

2 changed files with 136 additions and 47 deletions

6
web/dist/index.html vendored
View File

@ -6,7 +6,7 @@
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
<title>LAN Party</title> <title>LAN Party</title>
<link rel="preload" href="/index-a2c5ffc914f34da_bg.wasm" as="fetch" type="application/wasm" crossorigin=""> <link rel="preload" href="/index-175ab564dbb350a3_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/index-a2c5ffc914f34da.js"></head> <link rel="modulepreload" href="/index-175ab564dbb350a3.js"></head>
<body> <body>
<script type="module">import init from '/index-a2c5ffc914f34da.js';init('/index-a2c5ffc914f34da_bg.wasm');</script></body></html> <script type="module">import init from '/index-175ab564dbb350a3.js';init('/index-175ab564dbb350a3_bg.wasm');</script></body></html>

View File

@ -1,4 +1,4 @@
use std::{marker::PhantomData, str::FromStr}; use std::{cell::RefCell, marker::PhantomData, str::FromStr};
use crate::components::Block; use crate::components::Block;
use lan_party_core::event::{ use lan_party_core::event::{
@ -7,11 +7,11 @@ use lan_party_core::event::{
}; };
use log::debug; use log::debug;
use paste::paste; use paste::paste;
use sycamore::prelude::*; use sycamore::{builder::prelude::*, component::Prop, prelude::*};
macro_rules! editable { macro_rules! editable {
($type:ty => $editor:ty) => { ($type:ty => $editor:ty) => {
impl<'a, G: Html> Editable<'a, G> for $type { impl<'d, 's, 't, G: Html> Editable<'d, 's, 't, G> for $type {
type Editor = $editor; type Editor = $editor;
} }
}; };
@ -48,8 +48,8 @@ macro_rules! edit_struct {
paste! { paste! {
pub struct [<$struct Edit>]; pub struct [<$struct Edit>];
impl<'a, G: Html> Editor<'a, G, $struct> for [<$struct Edit>] { impl<'d, 's, 't, G: Html> Editor<'d, 's, 't, G, $struct> for [<$struct Edit>] {
fn edit(cx: Scope<'a>, props: EditProps<'a, $struct>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, $struct>) -> View<G> {
let state = props.state; let state = props.state;
link_fields!(cx, $($prop,)* => state as $struct); link_fields!(cx, $($prop,)* => state as $struct);
view! { cx, view! { cx,
@ -90,8 +90,8 @@ macro_rules! edit_enum {
paste! { paste! {
pub struct [<$enum Edit>]; pub struct [<$enum Edit>];
impl<'a, G: Html> Editor<'a, G, $enum> for [<$enum Edit>] { impl<'d, 's, 't, G: Html> Editor<'d, 's, 't, G, $enum> for [<$enum Edit>] {
fn edit(cx: Scope<'a>, props: EditProps<'a, $enum>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, $enum>) -> View<G> {
let state = props.state; let state = props.state;
link_variants!(cx, $selected => link_variants!(cx, $selected =>
@ -129,40 +129,40 @@ impl<'a, T> From<&'a Signal<T>> for EditProps<'a, T> {
} }
} }
pub trait IntoEdit<'a, G: Html> { pub trait IntoEdit<'d, 's, G: Html> {
fn edit(self, cx: Scope<'a>) -> View<G>; fn edit(self, cx: BoundedScope<'d, 's>) -> View<G>;
} }
impl<'a, G: Html, T: Editable<'a, G>> IntoEdit<'a, G> for &'a Signal<T> impl<'d, 's, 't, G: Html, T: Editable<'d, 's, 't, G> + 't> IntoEdit<'d, 's, G> for &'d Signal<T>
where where
EditProps<'a, T>: From<&'a Signal<T>>, EditProps<'d, T>: From<&'d Signal<T>>,
{ {
fn edit(self, cx: Scope<'a>) -> View<G> { fn edit(self, cx: BoundedScope<'d, 's>) -> View<G> {
T::edit(cx, self.into()) T::edit(cx, self.into())
} }
} }
pub trait Edit<'a, G: Html>: Sized { pub trait Edit<'d, 's, 't, G: Html>: Sized {
fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View<G>; fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, Self>) -> View<G>;
} }
impl<'a, G, E, Type> Edit<'a, G> for Type impl<'d, 's, 't, G, E, Type> Edit<'d, 's, 't, G> for Type
where where
G: Html, G: Html,
E: Editor<'a, G, Type>, E: Editor<'d, 's, 't, G, Type>,
Type: Editable<'a, G, Editor = E>, Type: Editable<'d, 's, 't, G, Editor = E> + 't,
{ {
fn edit(cx: Scope<'a>, props: EditProps<'a, Self>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, Self>) -> View<G> {
E::edit(cx, props) E::edit(cx, props)
} }
} }
pub trait Editor<'a, G: Html, Type>: Sized { pub trait Editor<'d, 's, 't, G: Html, Type: 't>: Sized {
fn edit(cx: Scope<'a>, props: EditProps<'a, Type>) -> View<G>; fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, Type>) -> View<G>;
} }
pub trait Editable<'a, G: Html>: Sized { pub trait Editable<'d, 's, 't, G: Html>: Sized + 't {
type Editor: Editor<'a, G, Self>; type Editor: Editor<'d, 's, 't, G, Self>;
} }
edit_struct!(EventSpec => ("Name", name), ("Description", description), ("Event type", event_type)); edit_struct!(EventSpec => ("Name", name), ("Description", description), ("Event type", event_type));
@ -179,8 +179,8 @@ edit_struct!(FreeForAllGameSpec => );
pub struct StringEdit; pub struct StringEdit;
impl<'a, G: Html> Editor<'a, G, String> for StringEdit { impl<'d, 's, 't, G: Html> Editor<'d, 's, 't, G, String> for StringEdit {
fn edit(cx: Scope<'a>, props: EditProps<'a, String>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, String>) -> View<G> {
view! { cx, view! { cx,
input(bind:value=props.state) input(bind:value=props.state)
} }
@ -191,11 +191,11 @@ editable!(String => StringEdit);
pub struct StubEdit; pub struct StubEdit;
impl<'a, G: Html, T> Editor<'a, G, T> for StubEdit impl<'d, 's, 't, G: Html, T> Editor<'d, 's, 't, G, T> for StubEdit
where where
T: Editable<'a, G, Editor = StubEdit>, T: Editable<'d, 's, 't, G, Editor = StubEdit>,
{ {
fn edit(cx: Scope<'a>, _props: EditProps<'a, T>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, _props: EditProps<'d, T>) -> View<G> {
view! { cx, view! { cx,
i { "Editor Unimplemented" } i { "Editor Unimplemented" }
} }
@ -204,11 +204,11 @@ where
pub struct InputEdit; pub struct InputEdit;
impl<'a, G: Html, T> Editor<'a, G, T> for InputEdit impl<'d, 's, 't, G: Html, T> Editor<'d, 's, 't, G, T> for InputEdit
where where
T: Editable<'a, G, Editor = InputEdit> + FromStr + ToString + Default, T: Editable<'d, 's, 't, G, Editor = InputEdit> + FromStr + ToString + Default,
{ {
fn edit(cx: Scope<'a>, props: EditProps<'a, T>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, T>) -> View<G> {
let value = create_signal(cx, props.state.get_untracked().to_string()); let value = create_signal(cx, props.state.get_untracked().to_string());
create_effect(cx, || { create_effect(cx, || {
@ -236,8 +236,8 @@ editable!(f32 => InputEdit);
pub struct BoolEdit; pub struct BoolEdit;
impl<'a, G: Html> Editor<'a, G, bool> for BoolEdit { impl<'d, 's, 't, G: Html> Editor<'d, 's, 't, G, bool> for BoolEdit {
fn edit(cx: Scope<'a>, props: EditProps<'a, bool>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, bool>) -> View<G> {
view! { cx, view! { cx,
input(type="checkbox", bind:checked=props.state) input(type="checkbox", bind:checked=props.state)
} }
@ -248,14 +248,18 @@ editable!(bool => BoolEdit);
pub struct VecEdit; pub struct VecEdit;
impl<'a, G, T, I> Editor<'a, G, I> for VecEdit impl<'d, 's, 't, 'c, G, T, I> Editor<'d, 's, 't, G, I> for VecEdit
where where
't: 'c,
's: 'd,
'd: 's,
't: 'd,
G: Html, G: Html,
T: Editable<'a, G> + Clone + PartialEq + 'a, T: Editable<'c, 's, 't, G> + Clone + PartialEq + 't,
I: IntoIterator<Item = T> + FromIterator<T> + Clone, I: IntoIterator<Item = T> + FromIterator<T> + Clone + 't,
{ {
fn edit(cx: Scope<'a>, props: EditProps<'a, I>) -> View<G> { fn edit(cx: BoundedScope<'d, 's>, props: EditProps<'d, I>) -> View<G> {
let vec = create_signal( let vec: &'s Signal<Vec<&'s Signal<T>>> = create_signal(
cx, cx,
props props
.state .state
@ -273,7 +277,6 @@ where
create_effect(cx, || { create_effect(cx, || {
props.state.set( props.state.set(
vec.get() vec.get()
.as_ref()
.iter() .iter()
.cloned() .cloned()
.map(|x| x.get().as_ref().clone()) .map(|x| x.get().as_ref().clone())
@ -281,26 +284,112 @@ where
) )
}); });
let test = Indexed(
cx,
IndexedProps::builder()
.iterable(vec)
.view(|cx: BoundedScope<'s, 's>, x: &'s Signal<T>| {
//view! { cx, (T::edit(cx, EditProps { state: x })) }
//T::edit(cx, EditProps { state: x })
view! { cx, }
})
.build(),
);
test
/* /*
//view! { cx, "Vec" }
view! { cx, view! { cx,
Indexed( Indexed(
iterable=vec, iterable=vec,
view=|cx: BoundedScope<'_, 'a>, x| { view=|cx: BoundedScope<'_, 'a>, x: &'a Signal<T>| {
let signal = create_ref(cx, x);
view! { cx, view! { cx,
(T::edit(cx, x.into())) //(T::edit(cx, EditProps { state: x }))
(something_with_signal(cx, EditProps { state: x }))
} }
}, },
) )
} }
*/ */
/*
view! { cx,
(View::new_fragment((vec.get().try_borrow().unwrap().clone().into_iter().map(|s: &'a Signal<T>| {
view! { cx, (T::edit(cx, s.into())) }
})).collect()))
}
*/
} }
} }
impl<'a, G, T> Editable<'a, G> for Vec<T> #[component]
where pub fn VecTest<
's,
'c,
'd,
't,
G: Html, G: Html,
T: Editable<'a, G> + Clone + PartialEq + 'a, T: 't + PartialEq + Clone + Editable<'s, 'd, 't, G, Editor = E>,
E: Editor<'s, 'd, 't, G, T>,
>(
cx: BoundedScope<'d, 's>,
props: EditProps<'d, Vec<T>>,
) -> View<G> {
/*
let signals: &'a Signal<Vec<&'a Signal<String>>> = create_signal(
cx,
vec![
create_signal(cx, String::new()),
create_signal(cx, String::new()),
],
);
*/
let signals = create_signal(
cx,
props
.state
.get()
.iter()
.cloned()
.map(|s| create_signal(cx, s))
.collect::<Vec<_>>(),
);
view! { cx,
Indexed(
iterable=signals,
view=|cx: BoundedScope<'_, 'd>, signal: &'d Signal<T>| {
view! { cx,
(something_with_signal(cx, EditProps { state: signal }))
//(E::edit(cx, EditProps { state: signal }))
//(T::edit(cx, EditProps { state: signal }))
//(signal.edit(cx))
}
},
)
}
}
pub struct SignalWrapper<'a, T>(&'a Signal<T>);
#[component]
pub fn something_with_signal<'a, 'b, 'c, G: Html, T: 'a + Editable<'b, 'c, 'a, G>>(
cx: Scope<'a>,
signal: EditProps<'a, T>,
) -> View<G> {
drop(signal);
view! { cx, "Something" }
}
impl<'d, 's, 't, 'c, G, T> Editable<'d, 's, 't, G> for Vec<T>
where
't: 'c,
's: 'd,
'd: 's,
't: 'd,
G: Html,
T: Editable<'c, 's, 't, G> + Clone + PartialEq + 't,
{ {
type Editor = VecEdit; type Editor = VecEdit;
} }