Vine/Server/Notification/
DecorationTypeLifecycle.rs1use std::sync::{Arc, OnceLock};
12
13use serde_json::{Value, json};
14use tokio::sync::mpsc::{UnboundedSender, unbounded_channel};
15
16use crate::{
17 Host::{RendererEmitter, VineHost},
18 dev_log,
19};
20
21struct DecorationItem {
22 Emitter:Arc<dyn RendererEmitter>,
23
24 Channel:String,
25
26 Payload:Value,
27}
28
29struct DecorationChannel {
30 Sender:UnboundedSender<DecorationItem>,
31}
32
33static DECO_CH:OnceLock<DecorationChannel> = OnceLock::new();
34
35fn GetOrInitChannel() -> &'static DecorationChannel {
36 DECO_CH.get_or_init(|| {
37 let (Tx, mut Rx) = unbounded_channel::<DecorationItem>();
38
39 tokio::spawn(async move {
40 let mut Buf:Vec<DecorationItem> = Vec::with_capacity(64);
41
42 loop {
43 match Rx.recv().await {
44 None => break,
45 Some(Item) => Buf.push(Item),
46 }
47
48 Rx.recv_many(&mut Buf, 4096).await;
49
50 tokio::time::sleep(std::time::Duration::from_millis(16)).await;
51
52 Rx.recv_many(&mut Buf, 4096).await;
53
54 if Buf.is_empty() {
55 continue;
56 }
57
58 let Emitter = Buf[0].Emitter.clone();
59
60 let mut ByChannel:std::collections::HashMap<String, Vec<Value>> = std::collections::HashMap::new();
61
62 for Item in Buf.drain(..) {
63 ByChannel.entry(Item.Channel).or_default().push(Item.Payload);
64 }
65
66 for (ChannelName, Payloads) in ByChannel {
67 let Count = Payloads.len();
68
69 Emitter.Emit(&ChannelName, json!({ "batch": Payloads }));
70
71 dev_log!("sky-emit", "[SkyEmit] ok channel={} batch={}", ChannelName, Count);
72 }
73 }
74 });
75
76 DecorationChannel { Sender:Tx }
77 })
78}
79
80pub async fn DecorationTypeLifecycle(Host:&dyn VineHost, MethodName:&str, Parameter:&Value) {
81 let EventName = format!("sky://decoration/{}", &MethodName["window.".len()..]);
82
83 let Ch = GetOrInitChannel();
84
85 let _ =
86 Ch.Sender
87 .send(DecorationItem { Emitter:Host.RendererEmitter(), Channel:EventName, Payload:Parameter.clone() });
88}