main.rs
1 #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] 2 3 use anyhow::Result; 4 use gpui::{prelude::*, *}; 5 use gpui_component::Root; 6 use std::{fs, sync::LazyLock}; 7 use tokio::runtime; 8 9 mod api; 10 mod components; 11 mod database; 12 mod gateway; 13 mod layouts; 14 mod stores; 15 16 use crate::{ 17 api::ClientProperties, gateway::client::Client, layouts::RootLayout, 18 stores::router::Route, 19 }; 20 21 /// Tokio runtime used to perform asynchronous operations. 22 static RUNTIME: LazyLock<runtime::Runtime> = LazyLock::new(|| { 23 runtime::Builder::new_multi_thread() 24 .enable_all() 25 // .worker_threads(2) 26 .build() 27 .unwrap() 28 }); 29 30 fn main() -> Result<()> { 31 // retrieve and create app data directory if none ---------------------------- 32 let data_dir = dirs::data_dir() 33 .expect("couldn't get data directory") 34 .join("quarrel"); 35 36 fs::create_dir_all(&data_dir)?; 37 38 // retrieve discord desktop client properties -------------------------------- 39 let client_properties = RUNTIME.block_on(ClientProperties::new())?; 40 println!("cp: built discord properties"); 41 42 // create sqlite pool -------------------------------------------------------- 43 let pool = RUNTIME.block_on(database::pool::create(data_dir))?; 44 println!("db: created sqlite pool"); 45 46 // determine what should we show on window open ------------------------------ 47 let accounts = RUNTIME.block_on(database::accounts::get_all(&pool))?; 48 let token = accounts.first().map(|account| account.token.clone()); 49 println!("db: found {} account(s)", accounts.len()); 50 51 // initialize the app -------------------------------------------------------- 52 let app = Application::new(); 53 app.run(move |cx| { 54 database::pool::init(cx, pool); 55 gpui_component::init(cx); 56 57 // if token is provided, show app directly; 58 // otherwise, always show auth. 59 stores::router::init( 60 cx, 61 if token.is_some() { 62 Route::App 63 } else { 64 Route::Auth 65 }, 66 ); 67 68 // if token is provided, make authenticated requests directly. 69 stores::http_manager::init(cx, client_properties.clone(), token.clone()); 70 71 // create the gateway handler. 72 gateway::client::init(cx, client_properties); 73 if let Some(token) = token { 74 // if token is provided, connect to the gateway with token. 75 Client::start_with(cx, token); 76 } 77 78 // gpui window properties. 79 let opts: WindowOptions = WindowOptions { 80 window_bounds: Some(WindowBounds::centered(size(px(900.), px(600.)), cx)), 81 titlebar: Some(TitlebarOptions { 82 title: Some(SharedString::from("Quarrel")), 83 ..Default::default() 84 }), 85 app_id: Some(String::from("quarrel")), 86 ..Default::default() 87 }; 88 89 // make sure to quit the app when windows are closed. 90 cx.on_window_closed(|cx| { 91 if cx.windows().is_empty() { 92 cx.quit(); 93 } 94 }) 95 .detach(); 96 97 // focus the app above everything else when opening. 98 cx.activate(true); 99 100 // open the app window. 101 cx.open_window(opts, |window, cx| { 102 let view = cx.new(|cx| RootLayout::new(window, cx)); 103 cx.new(|cx| Root::new(view, window, cx)) 104 }) 105 .expect("cannot open the window"); 106 }); 107 108 Ok(()) 109 }