/ src / main.rs
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  }