1use std::net::SocketAddr;
2
3use tao::event::{Event, WindowEvent};
4use tao::event_loop::{ControlFlow, EventLoop};
5use tao::window::WindowBuilder;
6use wry::WebViewBuilder;
7
8const DEFAULT_WIDTH: f64 = 1280.0;
9const DEFAULT_HEIGHT: f64 = 800.0;
10
11pub fn run_app(open_id: Option<String>) -> anyhow::Result<()> {
12 let (port_tx, port_rx) = std::sync::mpsc::channel::<u16>();
14 let (shutdown_tx, shutdown_rx) = tokio::sync::oneshot::channel::<()>();
15 let mut shutdown_tx = Some(shutdown_tx);
16
17 std::thread::spawn(move || {
18 let rt = tokio::runtime::Runtime::new().expect("failed to create tokio runtime");
19 rt.block_on(async {
20 let app = draw_webapp::create_router(open_id);
21 let addr = SocketAddr::from(([127, 0, 0, 1], 0));
22 let listener = tokio::net::TcpListener::bind(addr)
23 .await
24 .expect("failed to bind");
25 let actual_port = listener.local_addr().unwrap().port();
26 port_tx.send(actual_port).ok();
27
28 axum::serve(listener, app)
29 .with_graceful_shutdown(async {
30 shutdown_rx.await.ok();
31 })
32 .await
33 .ok();
34 });
35 });
36
37 let port = port_rx.recv().expect("failed to receive server port");
38 let url = format!("http://127.0.0.1:{port}");
39
40 let event_loop = EventLoop::new();
42
43 let window = WindowBuilder::new()
44 .with_title("draw")
45 .with_inner_size(tao::dpi::LogicalSize::new(DEFAULT_WIDTH, DEFAULT_HEIGHT))
46 .build(&event_loop)?;
47
48 let _webview = WebViewBuilder::new().with_url(&url).build(&window)?;
49
50 event_loop.run(move |event, _, control_flow| {
51 *control_flow = ControlFlow::Wait;
52
53 if let Event::WindowEvent {
54 event: WindowEvent::CloseRequested,
55 ..
56 } = event
57 {
58 if let Some(tx) = shutdown_tx.take() {
59 tx.send(()).ok();
60 }
61 *control_flow = ControlFlow::Exit;
62 }
63 });
64}