2023-05-06 12:01:56 -07:00
|
|
|
use std::error::Error;
|
|
|
|
|
|
|
|
use once_cell::sync::OnceCell;
|
|
|
|
use sqlx::{
|
|
|
|
SqlitePool,
|
|
|
|
sqlite::SqlitePoolOptions,
|
|
|
|
sqlite::SqliteConnectOptions,
|
|
|
|
};
|
|
|
|
use tauri::{
|
|
|
|
App,
|
|
|
|
AppHandle,
|
|
|
|
Manager,
|
|
|
|
async_runtime as rt,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
config::{self, AppConfig},
|
|
|
|
credentials::Session,
|
|
|
|
ipc,
|
|
|
|
server::Server,
|
|
|
|
errors::*,
|
2023-09-21 10:44:35 -07:00
|
|
|
shortcuts,
|
2023-05-06 12:01:56 -07:00
|
|
|
state::AppState,
|
|
|
|
tray,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
pub static APP: OnceCell<AppHandle> = OnceCell::new();
|
|
|
|
|
|
|
|
|
|
|
|
pub fn run() -> tauri::Result<()> {
|
|
|
|
tauri::Builder::default()
|
|
|
|
.plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| {
|
|
|
|
app.get_window("main")
|
|
|
|
.map(|w| w.show().error_popup("Failed to show main window"));
|
|
|
|
}))
|
|
|
|
.system_tray(tray::create())
|
|
|
|
.on_system_tray_event(tray::handle_event)
|
|
|
|
.invoke_handler(tauri::generate_handler![
|
|
|
|
ipc::unlock,
|
|
|
|
ipc::respond,
|
|
|
|
ipc::get_session_status,
|
|
|
|
ipc::save_credentials,
|
|
|
|
ipc::get_config,
|
|
|
|
ipc::save_config,
|
2023-08-02 19:57:37 -07:00
|
|
|
ipc::launch_terminal,
|
2023-09-14 15:04:25 -07:00
|
|
|
ipc::get_setup_errors,
|
2023-05-06 12:01:56 -07:00
|
|
|
])
|
|
|
|
.setup(|app| rt::block_on(setup(app)))
|
|
|
|
.build(tauri::generate_context!())?
|
|
|
|
.run(|app, run_event| match run_event {
|
|
|
|
tauri::RunEvent::WindowEvent { label, event, .. } => match event {
|
|
|
|
tauri::WindowEvent::CloseRequested { api, .. } => {
|
|
|
|
let _ = app.get_window(&label).map(|w| w.hide());
|
|
|
|
api.prevent_close();
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
}
|
|
|
|
_ => ()
|
|
|
|
});
|
|
|
|
|
|
|
|
Ok(())
|
2023-05-06 16:56:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn connect_db() -> Result<SqlitePool, SetupError> {
|
|
|
|
let conn_opts = SqliteConnectOptions::new()
|
|
|
|
.filename(config::get_or_create_db_path()?)
|
|
|
|
.create_if_missing(true);
|
|
|
|
let pool_opts = SqlitePoolOptions::new();
|
|
|
|
let pool: SqlitePool = pool_opts.connect_with(conn_opts).await?;
|
2023-05-06 21:59:24 -07:00
|
|
|
sqlx::migrate!().run(&pool).await?;
|
2023-05-06 16:56:45 -07:00
|
|
|
Ok(pool)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
|
|
|
|
APP.set(app.handle()).unwrap();
|
|
|
|
|
2023-09-13 11:06:40 -07:00
|
|
|
// get_or_create_db_path doesn't create the actual db file, just the directory
|
|
|
|
let is_first_launch = !config::get_or_create_db_path()?.exists();
|
2023-05-06 16:56:45 -07:00
|
|
|
let pool = connect_db().await?;
|
2023-09-14 15:04:25 -07:00
|
|
|
let mut setup_errors: Vec<String> = vec![];
|
2023-09-13 11:06:40 -07:00
|
|
|
|
2023-10-09 08:50:31 -07:00
|
|
|
let mut conf = match AppConfig::load(&pool).await {
|
2023-09-13 11:06:40 -07:00
|
|
|
Ok(c) => c,
|
|
|
|
Err(SetupError::ConfigParseError(_)) => {
|
2023-09-14 15:04:25 -07:00
|
|
|
setup_errors.push(
|
|
|
|
"Could not load configuration from database. Reverting to defaults.".into()
|
|
|
|
);
|
2023-09-13 11:06:40 -07:00
|
|
|
AppConfig::default()
|
|
|
|
},
|
|
|
|
err => err?,
|
|
|
|
};
|
|
|
|
|
2023-05-06 16:56:45 -07:00
|
|
|
let session = Session::load(&pool).await?;
|
2023-09-18 20:13:29 -07:00
|
|
|
Server::start(app.handle())?;
|
2023-05-06 16:56:45 -07:00
|
|
|
|
|
|
|
config::set_auto_launch(conf.start_on_login)?;
|
2023-09-14 15:04:25 -07:00
|
|
|
if let Err(_e) = config::set_auto_launch(conf.start_on_login) {
|
|
|
|
setup_errors.push("Error: Failed to manage autolaunch.".into());
|
|
|
|
}
|
2023-10-09 08:50:31 -07:00
|
|
|
|
|
|
|
// if hotkeys fail to register, disable them so that this error doesn't have to keep showing up
|
|
|
|
if let Err(_e) = shortcuts::register_hotkeys(&conf.hotkeys) {
|
|
|
|
conf.hotkeys.disable_all();
|
|
|
|
conf.save(&pool).await?;
|
|
|
|
setup_errors.push("Failed to register hotkeys. Hotkey settings have been disabled.".into());
|
2023-09-14 15:04:25 -07:00
|
|
|
}
|
2023-09-13 11:06:40 -07:00
|
|
|
|
2023-07-11 16:13:20 -07:00
|
|
|
// if session is empty, this is probably the first launch, so don't autohide
|
|
|
|
if !conf.start_minimized || is_first_launch {
|
2023-05-06 16:56:45 -07:00
|
|
|
app.get_window("main")
|
|
|
|
.ok_or(HandlerError::NoMainWindow)?
|
|
|
|
.show()?;
|
|
|
|
}
|
|
|
|
|
2023-09-18 20:13:29 -07:00
|
|
|
let state = AppState::new(conf, session, pool, setup_errors);
|
2023-05-06 16:56:45 -07:00
|
|
|
app.manage(state);
|
|
|
|
Ok(())
|
|
|
|
}
|