160 lines
4.4 KiB
Rust
160 lines
4.4 KiB
Rust
mod fig_container;
|
|
mod fonts;
|
|
mod menu;
|
|
mod menu_events;
|
|
#[cfg(target_os = "macos")]
|
|
mod window;
|
|
|
|
use fig_container::build_fig_file;
|
|
use fonts::{list_system_fonts, load_system_font};
|
|
use menu::install_app_menu;
|
|
use menu_events::handle_menu_event;
|
|
use std::{
|
|
path::{Path, PathBuf},
|
|
sync::Mutex,
|
|
};
|
|
use tauri::{Emitter, Manager};
|
|
use tauri_plugin_fs::FsExt;
|
|
#[cfg(target_os = "macos")]
|
|
use window::show_main_window;
|
|
|
|
#[derive(Clone, serde::Serialize)]
|
|
struct PendingOpenFile {
|
|
path: String,
|
|
}
|
|
|
|
struct PendingOpen(Mutex<Vec<PendingOpenFile>>);
|
|
|
|
#[tauri::command]
|
|
fn take_pending_open(state: tauri::State<PendingOpen>) -> Vec<PendingOpenFile> {
|
|
state
|
|
.0
|
|
.lock()
|
|
.map(|mut pending| pending.drain(..).collect())
|
|
.unwrap_or_default()
|
|
}
|
|
|
|
fn file_association_path(path: PathBuf) -> Option<PathBuf> {
|
|
let path = path.canonicalize().ok()?;
|
|
if !path.is_file() {
|
|
return None;
|
|
}
|
|
let ext = path.extension()?.to_string_lossy().to_lowercase();
|
|
matches!(ext.as_str(), "fig" | "pen").then_some(path)
|
|
}
|
|
|
|
fn path_from_arg(arg: String, cwd: &Path) -> Option<PathBuf> {
|
|
if arg.starts_with('-') {
|
|
return None;
|
|
}
|
|
|
|
if let Ok(url) = tauri::Url::parse(&arg) {
|
|
if let Ok(path) = url.to_file_path() {
|
|
return Some(path);
|
|
}
|
|
}
|
|
|
|
let path = PathBuf::from(arg);
|
|
Some(if path.is_absolute() {
|
|
path
|
|
} else {
|
|
cwd.join(path)
|
|
})
|
|
}
|
|
|
|
fn open_paths_from_args(args: Vec<String>, cwd: &Path) -> Vec<PathBuf> {
|
|
args.into_iter()
|
|
.filter_map(|arg| path_from_arg(arg, cwd))
|
|
.filter_map(file_association_path)
|
|
.collect()
|
|
}
|
|
|
|
fn queue_open_paths<R: tauri::Runtime>(app: &tauri::AppHandle<R>, paths: Vec<PathBuf>) {
|
|
let files = paths
|
|
.into_iter()
|
|
.filter_map(|path| {
|
|
let _ = app.fs_scope().allow_file(&path);
|
|
Some(PendingOpenFile {
|
|
path: path.to_string_lossy().into_owned(),
|
|
})
|
|
})
|
|
.collect::<Vec<_>>();
|
|
|
|
if files.is_empty() {
|
|
return;
|
|
}
|
|
|
|
if let Ok(mut pending) = app.state::<PendingOpen>().0.lock() {
|
|
pending.extend(files);
|
|
}
|
|
|
|
let _ = app.emit("open-associated-files", ());
|
|
if let Some(window) = app.get_webview_window("main") {
|
|
let _ = window.set_focus();
|
|
}
|
|
}
|
|
|
|
fn startup_open_paths() -> Vec<PathBuf> {
|
|
let cwd = std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."));
|
|
open_paths_from_args(std::env::args().skip(1).collect(), &cwd)
|
|
}
|
|
|
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
pub fn run() {
|
|
let _ = fix_path_env::fix();
|
|
|
|
let mut builder = tauri::Builder::default();
|
|
|
|
#[cfg(any(target_os = "macos", windows, target_os = "linux"))]
|
|
{
|
|
builder = builder.plugin(tauri_plugin_single_instance::init(|app, args, cwd| {
|
|
queue_open_paths(app, open_paths_from_args(args, Path::new(&cwd)));
|
|
}));
|
|
}
|
|
|
|
builder
|
|
.manage(PendingOpen(Mutex::new(Vec::new())))
|
|
.invoke_handler(tauri::generate_handler![
|
|
build_fig_file,
|
|
list_system_fonts,
|
|
load_system_font,
|
|
take_pending_open
|
|
])
|
|
.plugin(tauri_plugin_opener::init())
|
|
.plugin(tauri_plugin_dialog::init())
|
|
.plugin(tauri_plugin_fs::init())
|
|
.plugin(tauri_plugin_shell::init())
|
|
.plugin(tauri_plugin_updater::Builder::new().build())
|
|
.plugin(tauri_plugin_process::init())
|
|
.on_menu_event(|app, event| {
|
|
handle_menu_event(app, event.id().0.as_str());
|
|
})
|
|
.setup(|app| {
|
|
queue_open_paths(app.handle(), startup_open_paths());
|
|
Ok(install_app_menu(app)?)
|
|
})
|
|
.build(tauri::generate_context!())
|
|
.expect("error while building tauri application")
|
|
.run(|_app, event| match event {
|
|
#[cfg(target_os = "macos")]
|
|
tauri::RunEvent::Opened { urls } => {
|
|
let paths = urls
|
|
.into_iter()
|
|
.filter_map(|url| url.to_file_path().ok())
|
|
.filter_map(file_association_path)
|
|
.collect();
|
|
queue_open_paths(_app, paths);
|
|
}
|
|
#[cfg(target_os = "macos")]
|
|
tauri::RunEvent::Reopen {
|
|
has_visible_windows,
|
|
..
|
|
} => {
|
|
if !has_visible_windows {
|
|
show_main_window(_app);
|
|
}
|
|
}
|
|
_ => {}
|
|
});
|
|
}
|