Compare commits

..

3 Commits

Author SHA1 Message Date
17b6a16ec7 update 2024-12-31 19:18:02 +09:00
43be624ac2 update 2024-12-31 18:34:00 +09:00
78b4b34830 update 2024-12-31 18:32:46 +09:00
4 changed files with 90 additions and 40 deletions

View File

@ -13,7 +13,7 @@ impl Filter {
id: Uuid::new_v4(),
enabled: true,
name: "".to_string(),
lines: HashMap::new(),
rule: Default::default(),
remain: FilterRemain::Leaf(Default::default()),
}
}
@ -23,7 +23,7 @@ impl Filter {
id: Uuid::new_v4(),
enabled: true,
name: "".to_string(),
lines: HashMap::new(),
rule: Default::default(),
remain: FilterRemain::Group(Default::default()),
}
}
@ -35,7 +35,7 @@ pub struct Filter {
pub id: uuid::Uuid,
pub enabled: bool,
pub name: String,
pub lines: HashMap<String, Line>,
pub rule: FilterRule,
pub remain: FilterRemain,
}
@ -75,29 +75,29 @@ pub struct Color {
pub type Level = RangedNumber<1, 100>;
#[cfg_attr(feature = "store", derive(reactive_stores::Store))]
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum Line {
Class(Vec<ItemClass>),
BaseType(Vec<ItemBaseType>),
AreaLevel(Op, Level),
DropLevel(Op, Level),
ItemLevel(Op, Level),
Rarity(Op, ItemRarity),
Sockets(Op, u32),
Quality(Op, u32),
StackSize(Op, u32),
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct FilterRule {
pub class: Option<Vec<ItemClass>>,
pub base_type: Option<Vec<ItemBaseType>>,
pub area_level: Option<(Op, Level)>,
pub drop_level: Option<(Op, Level)>,
pub item_level: Option<(Op, Level)>,
pub rarity: Option<(Op, ItemRarity)>,
pub sockets: Option<(Op, u32)>,
pub quality: Option<(Op, u32)>,
pub stack_size: Option<(Op, u32)>,
// waystones
WaystoneTier(Op, RangedNumber<1, 16>),
pub waystone_tier: Option<(Op, RangedNumber<1, 16>)>,
// effects
SetFontSize(RangedNumber<1, 45>),
SetTextColor(Color),
SetBorderColor(Color),
SetBackgroundColor(Color),
PlayAlertSound(RangedNumber<1, 16>, RangedNumber<0, 300>),
PlayEffect(GameColor),
MinimapIcon(RangedNumber<0, 2>, GameColor, MinimapIconShape),
pub set_font_size: Option<RangedNumber<1, 45>>,
pub set_text_color: Option<Color>,
pub set_border_color: Option<Color>,
pub set_background_color: Option<Color>,
pub play_alert_sound: Option<(RangedNumber<1, 16>, RangedNumber<0, 300>)>,
pub play_effect: Option<GameColor>,
pub minimap_icon: Option<(RangedNumber<0, 2>, GameColor, MinimapIconShape)>,
}
#[derive(Serialize, Deserialize, Debug)]

View File

@ -25,7 +25,7 @@ extern "C" {
#[derive(Store, Clone)]
struct AppStore {
root: Filter,
selected_filter: Option<Field<Filter>>,
selected_filter: Option<Vec<Field<Filter>>>,
}
#[component]
@ -48,7 +48,7 @@ fn Main() -> impl IntoView {
let selected = store.selected_filter().get();
match selected {
Some(selected) => {
if selected.id().get() == store.root().id().get() {
if selected[0].id().get() == store.root().id().get() {
FilterRoot().into_any()
} else {
view! { <FilterDetail filter=selected /> }.into_any()

View File

@ -11,7 +11,7 @@ fn group(
filter: Field<Filter>,
group: Field<FilterGroup>,
on_action: Callback<(Action,)>,
selected: Field<Option<Field<Filter>>>,
selected: Field<Option<Vec<Field<Filter>>>>,
root: bool,
) -> impl IntoView {
let header = move || {
@ -51,7 +51,7 @@ fn group(
}
};
let active = move || match selected.get() {
Some(f) => filter.id().get() == f.id().get(),
Some(f) => filter.id().get() == f[0].id().get(),
None => false,
};
view! {
@ -59,7 +59,7 @@ fn group(
<a
class=("active", active)
on:click=move |_| {
on_action.run((Action::Select(filter),));
on_action.run((Action::Select(vec![filter]),));
}
>
<div class="flex gap-2">
@ -103,11 +103,11 @@ fn group(
<For
each=move || group.filters()
key=|row| row.read().id.to_string()
children=move |filter| {
let id = filter.clone().id().get();
children=move |child| {
let id = child.clone().id().get();
view! {
<Filter
filter
filter=child
selected
on_action=move |action| {
let i = group
@ -126,8 +126,9 @@ fn group(
group.filters().write().swap(i, i + 1);
}
}
a @ Action::Select(_) => {
on_action.run((a,));
Action::Select(mut v) => {
v.push(filter);
on_action.run((Action::Select(v),));
}
}
}
@ -144,7 +145,7 @@ fn leaf(
filter: Field<Filter>,
leaf: Field<FilterLeaf>,
on_action: Callback<(Action,)>,
selected: Field<Option<Field<Filter>>>,
selected: Field<Option<Vec<Field<Filter>>>>,
) -> impl IntoView {
let header = move || filter.id().get().to_string();
@ -156,7 +157,7 @@ fn leaf(
}
};
let active = move || match selected.get() {
Some(f) => filter.id().get() == f.id().get(),
Some(f) => filter.id().get() == f[0].id().get(),
None => false,
};
view! {
@ -164,7 +165,7 @@ fn leaf(
<a
class=("active", active)
on:click=move |_| {
on_action.run((Action::Select(filter),));
on_action.run((Action::Select(vec![filter]),));
}
>
<div class="flex gap-2">
@ -204,14 +205,14 @@ fn leaf(
pub enum Action {
Up,
Down,
Select(Field<Filter>),
Select(Vec<Field<Filter>>),
}
#[component]
pub fn Filter(
#[prop(into)] filter: Field<Filter>,
#[prop(into)] on_action: Callback<(Action,)>,
#[prop(into)] selected: Field<Option<Field<Filter>>>,
#[prop(into)] selected: Field<Option<Vec<Field<Filter>>>>,
#[prop(optional)] root: bool,
) -> impl IntoView {
let remain = filter.remain();

View File

@ -1,12 +1,61 @@
use leptos::prelude::*;
use reactive_stores::Field;
use src_common::models::loot_filter::Filter;
use reactive_stores::{Field, OptionStoreExt};
use src_common::models::loot_filter::{
Filter, FilterLeafStoreFields, FilterRemain, FilterRemainStoreFields, FilterRule,
FilterRuleStoreFields, FilterStoreFields,
};
#[component]
pub fn FilterDetail(#[prop(into)] filter: Field<Filter>) -> impl IntoView {
pub fn FilterDetail(#[prop(into)] filter: Vec<Field<Filter>>) -> impl IntoView {
let (first, rest) = filter.split_first().unwrap();
view! {
<article class="prose">
<h3>Filter details:</h3>
</article>
{match first.remain().get_untracked() {
FilterRemain::Leaf(_) => {
let leaf = first.remain().leaf_0().unwrap();
Some(
view! {
<div class="flex gap-2 items-center">
<label class="label">Hide</label>
<input
type="checkbox"
class="toggle"
prop:checked=move || leaf.show().get()
on:change:target=move |ev| {
leaf.show().set(event_target_checked(&ev));
}
/>
<label class="label">Show</label>
</div>
},
)
}
FilterRemain::Group(_) => None,
}}
<RuleDetail rule=first.rule() />
}
}
#[component]
pub fn RuleDetail(#[prop(into)] rule: Field<FilterRule>) -> impl IntoView {
let class = view! {
<tr class="flex items-center gap-2">
<td>
<input type="checkbox" class="checkbox" />
</td>
<td>
<label class="label">Class</label>
</td>
<td>
<label class="label">Class</label>
</td>
</tr>
};
view! {
<table class="table">
<tbody>{class}</tbody>
</table>
}
}