1use dioxus::prelude::*;
2use network_libp2p::NodeOptions;
3
4use chat_ui_components::{ChatApp, ChatAppSignals, use_chat_app_signals, run_chat_event_loop};
5
6const CSS: &str = include_str!("../public/styles.css");
7
8fn main() {
9 tracing_subscriber::fmt()
10 .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
11 .init();
12
13 dioxus::launch(App);
14}
15
16#[component]
17fn App() -> Element {
18 let signals = use_chat_app_signals();
19 let ChatAppSignals {
20 mut tab_lock_acquired,
21 mut coordinator_handle,
22 mut error_messages,
23 ..
24 } = signals;
25
26 use_hook(|| {
28 spawn(async move {
29 let node = {
30 let node_options = NodeOptions {
31 listen_addresses: vec!["/ip4/0.0.0.0/tcp/0".into()],
32 bootstrap_peers: chat_core::config::BOOTSTRAP_PEERS.iter().map(|s| s.to_string()).collect(),
33 max_connections: 100,
34 dht_client_mode: true,
35 dht_discovery_enabled: true,
36 stun_servers: None,
37 };
38 network_libp2p::build_node(node_options).await
39 };
40
41 match node {
42 Ok(node) => {
43 let data_dir = dirs::data_dir()
44 .unwrap_or_else(|| std::path::PathBuf::from("."))
45 .join("p2pandemonium");
46 let _ = std::fs::create_dir_all(&data_dir);
47
48 let conn = chat_platform_native::storage::open_storage(
49 "chat",
50 Some(data_dir.to_str().unwrap()),
51 ).await.unwrap();
52 let storage = chat_core::storage::SqliteStorage::new(conn);
53 storage.init_schema().unwrap();
54
55 let (handle, events, loop_fut) = chat_core::coordinator::build(node, storage);
56
57 let lock_path = data_dir.join("app.lock");
59 if chat_platform_native::tab_lock::TabLock::try_acquire(&lock_path).is_none() {
60 tab_lock_acquired.set(false);
61 return;
62 }
63
64 spawn(loop_fut.run());
66
67 coordinator_handle.set(Some(handle.clone()));
68
69 run_chat_event_loop(events, signals).await;
71 }
72 Err(e) => {
73 error_messages.set(vec![format!("Failed to create node: {}", e)]);
74 }
75 }
76 });
77 });
78
79 rsx! {
80 style { dangerous_inner_html: CSS }
81 ChatApp { signals, on_room_left: None }
82 }
83}