Skip to main content

draw_app/
lib.rs

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    // Start the axum webapp on a random available port in a background thread
13    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    // Create native window and webview
41    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}