// Copyright: Ankitects Pty Ltd and contributors // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // use std::sync::Mutex; use tauri::http; use tauri::App; use tauri::AppHandle; use tauri::Manager; use tauri::Runtime; use tauri::UriSchemeContext; use tauri::UriSchemeResponder; use tauri_plugin_os::locale; use crate::generated; use crate::lang::I18n; use crate::state::State; use crate::uv; pub const PROTOCOL: &str = "anki"; pub fn init() -> Option { let mut state = State::init().unwrap_or_else(State::Error); match state { State::Normal(ref mut state) => state.check_versions(), State::LaunchAnki(ref paths) => { let args: Vec = std::env::args().skip(1).collect(); let cmd = paths.build_python_command(&args).unwrap(); uv::launch_anki_normally(cmd).unwrap(); return None; } _ => {} } Some(state) } pub fn setup(app: &mut App, state: State) -> anyhow::Result<()> { let tr = I18n::new(&[&locale().unwrap_or_default()]); app.manage(crate::lang::Tr::new(Some(tr))); app.manage(state); #[cfg(debug_assertions)] let _ = app .get_webview_window("main") .unwrap() .set_always_on_top(true); Ok(()) } pub fn serve( ctx: UriSchemeContext<'_, R>, req: http::Request>, responder: UriSchemeResponder, ) { let app = ctx.app_handle().to_owned(); let window = app .get_webview_window(ctx.webview_label()) .expect("could not get webview"); let builder = http::Response::builder() .header(http::header::ACCESS_CONTROL_ALLOW_ORIGIN, "*") .header(http::header::CONTENT_TYPE, "application/binary"); tauri::async_runtime::spawn(async move { match *req.method() { http::Method::POST => { let response = match generated::handle_rpc(app, window, req).await { Ok(res) if !res.is_empty() => builder.body(res), Ok(res) => builder.status(http::StatusCode::NO_CONTENT).body(res), Err(e) => { eprintln!("ERROR: {e:?}"); builder .status(http::StatusCode::INTERNAL_SERVER_ERROR) .header(http::header::CONTENT_TYPE, "text/plain") .body(format!("{e:?}").as_bytes().to_vec()) } }; responder.respond(response.expect("could not build response")); } // handle preflight requests (on windows at least) http::Method::OPTIONS => { responder.respond( builder .header(http::header::ACCESS_CONTROL_ALLOW_METHODS, "POST") .header(http::header::ACCESS_CONTROL_ALLOW_HEADERS, "Content-Type") .body(vec![]) .unwrap(), ); } _ => unimplemented!("rpc calls must use POST"), } }); } pub fn on_second_instance(app: &AppHandle, _args: Vec, _cwd: String) { let _ = app .get_webview_window("main") .expect("no main window") .set_focus(); }