rsiot/components/cmp_leptos/component/
fn_process.rs

1use gloo::storage::{LocalStorage, Storage};
2use leptos::prelude::*;
3use reactive_stores::Store;
4use tokio::{sync::mpsc, task::JoinSet};
5use tracing::debug;
6
7use crate::{
8    executor::{join_set_spawn, CmpInOut},
9    message::{system_messages::*, *},
10};
11
12use super::{
13    super::{Error, Result},
14    Config, StoreBound,
15};
16
17pub async fn fn_process<TMsg, TInputStore, TOutputStore>(
18    config: Config<TMsg, TInputStore, TOutputStore>,
19    in_out: CmpInOut<TMsg>,
20) -> Result
21where
22    TMsg: MsgDataBound + 'static,
23    TInputStore: StoreBound + 'static,
24    TOutputStore: StoreBound + 'static,
25{
26    // Монтируем корневой компонент
27    let input_store = Store::new(config.input_store);
28    let input_store_clone = input_store;
29    let output_store = Store::new(config.output_store);
30    let output_store_clone = output_store;
31    mount_to_body(move || {
32        view! {
33            <RootComponent
34                body_component = config.body_component
35                input_store=input_store_clone
36                output_store=output_store_clone
37            />
38        }
39    });
40    debug!("Leptos app mounted");
41
42    let mut task_set: JoinSet<Result> = JoinSet::new();
43
44    let task = task_input(in_out.clone(), config.fn_input, input_store);
45    join_set_spawn(&mut task_set, task);
46
47    let task = task_output(in_out.clone(), config.fn_output, output_store);
48    join_set_spawn(&mut task_set, task);
49
50    while let Some(task_result) = task_set.join_next().await {
51        task_result??
52    }
53    Ok(())
54}
55
56async fn task_input<TMsg, TInputStore>(
57    mut msg_bus: CmpInOut<TMsg>,
58    fn_input: fn(&Message<TMsg>, &Store<TInputStore>),
59    input_store: Store<TInputStore>,
60) -> Result
61where
62    TMsg: MsgDataBound + 'static,
63    TInputStore: StoreBound + 'static,
64{
65    while let Ok(msg) = msg_bus.recv_input().await {
66        (fn_input)(&msg, &input_store);
67    }
68    Ok(())
69}
70
71async fn task_output<TMsg, TOutputStore>(
72    msg_bus: CmpInOut<TMsg>,
73    fn_output: fn(Store<TOutputStore>, mpsc::Sender<TMsg>),
74    output_store: Store<TOutputStore>,
75) -> Result
76where
77    TMsg: MsgDataBound + 'static,
78    TOutputStore: StoreBound + 'static,
79{
80    let (tx, mut rx) = mpsc::channel(100);
81
82    (fn_output)(output_store, tx);
83
84    while let Some(msg) = rx.recv().await {
85        let msg = Message::new_custom(msg);
86        msg_bus.send_output(msg).await.map_err(Error::CmpOutput)?;
87    }
88
89    Ok(())
90}
91
92/// Пробуем найти токен в LocalStorage.
93///
94/// Если токен присутствует, отправляем запрос на проверку токена
95fn _try_to_find_token<TMsg>() -> Option<Message<TMsg>>
96where
97    TMsg: MsgDataBound,
98{
99    let msg: Message<TMsg> = LocalStorage::get("System-AuthResponseOk").ok()?;
100    match msg.data {
101        MsgData::System(System::AuthResponseOk(value)) => {
102            let value = AuthRequestByToken { token: value.token };
103            let msg = Message::new(MsgData::System(System::AuthRequestByToken(value)));
104            Some(msg)
105        }
106        _ => None,
107    }
108}
109
110/// Корневой компонент
111#[component]
112fn RootComponent<TView, TIntoView, TInputStore, TOutputStore>(
113    body_component: TView,
114    input_store: Store<TInputStore>,
115    output_store: Store<TOutputStore>,
116) -> impl IntoView
117where
118    TView: Fn() -> TIntoView,
119    TIntoView: IntoView,
120    TInputStore: StoreBound + 'static,
121    TOutputStore: StoreBound + 'static,
122{
123    provide_context(input_store);
124    provide_context(output_store);
125
126    view! {
127        { body_component() }
128    }
129}