diff --git a/Cargo.lock b/Cargo.lock index 0ceac228..b7b82f6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,6 +154,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" +dependencies = [ + "objc-sys", +] + +[[package]] +name = "block2" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e58aa60e59d8dbfcc36138f5f18be5f24394d33b38b24f7fd0b1caa33095f22f" +dependencies = [ + "block-sys", + "objc2", +] + [[package]] name = "block2" version = "0.5.1" @@ -1390,6 +1409,16 @@ dependencies = [ "png", ] +[[package]] +name = "icrate" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb69199826926eb864697bddd27f73d9fddcffc004f5733131e15b465e30642" +dependencies = [ + "block2 0.4.0", + "objc2", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1615,11 +1644,13 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" name = "learn-anything" version = "0.1.0" dependencies = [ + "osakit", "serde", "serde_json", "tauri", "tauri-build", "tauri-plugin-fs", + "thiserror", ] [[package]] @@ -1986,7 +2017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ "bitflags 2.6.0", - "block2", + "block2 0.5.1", "libc", "objc2", "objc2-core-data", @@ -2002,7 +2033,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ "bitflags 2.6.0", - "block2", + "block2 0.5.1", "objc2", "objc2-foundation", ] @@ -2013,7 +2044,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "block2", + "block2 0.5.1", "objc2", "objc2-foundation", "objc2-metal", @@ -2032,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", - "block2", + "block2 0.5.1", "dispatch", "libc", "objc2", @@ -2045,7 +2076,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ "bitflags 2.6.0", - "block2", + "block2 0.5.1", "objc2", "objc2-foundation", ] @@ -2057,7 +2088,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ "bitflags 2.6.0", - "block2", + "block2 0.5.1", "objc2", "objc2-foundation", "objc2-metal", @@ -2102,6 +2133,18 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "osakit" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b95f3e5c7b6cc3dd6ebd456a38b6a0ba93c4aa54b3949039ee16fa100713b50" +dependencies = [ + "icrate", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "overload" version = "0.1.1" diff --git a/app/Cargo.toml b/app/Cargo.toml index d92a53f9..7ee4fe88 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -15,7 +15,9 @@ name = "app_lib" tauri-build = { version = "2.0.0-rc.6", features = [] } [dependencies] +osakit = { version = "0.2.3", features = ["full"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" tauri = { version = "2.0.0-rc.6", features = [] } tauri-plugin-fs = { version = "2.0.0-rc.1", features = ["watch"] } +thiserror = "1.0.63" diff --git a/app/src/browser.rs b/app/src/browser.rs new file mode 100644 index 00000000..f1371188 --- /dev/null +++ b/app/src/browser.rs @@ -0,0 +1,50 @@ +use osakit::declare_script; +use serde::{Deserialize, Serialize}; + +declare_script! { + #[language(JavaScript)] + #[source(r#" + function safari(name, index) { + return Application(name).windows[index].currentTab.url(); + } + + function chrome(name, index) { + return Application(name).windows[index].activeTab().url(); + } + "#)] + pub Browser { + pub fn safari(name: &str, index: usize) -> String; + pub fn chrome(name: &str, index: usize) -> String; + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum Kind { + Safari, + Chrome, +} + +#[derive(Debug, thiserror::Error)] +pub enum Error { + #[error("unable to run JXA function")] + JxaRunError(#[from] osakit::ScriptFunctionRunError), +} + +impl serde::Serialize for Error { + fn serialize(&self, serializer: S) -> Result + where + S: serde::ser::Serializer, + { + serializer.serialize_str(self.to_string().as_ref()) + } +} + +#[tauri::command] +pub fn get_current_browser_url(kind: Kind, name: &str, window: usize) -> Result { + let browser = Browser::new().expect("successful script compilation"); + Ok(match kind { + Kind::Safari => browser.safari(name, window)?, + Kind::Chrome => browser.chrome(name, window)?, + }) +} diff --git a/app/src/lib.rs b/app/src/lib.rs index 5249c907..45dec622 100644 --- a/app/src/lib.rs +++ b/app/src/lib.rs @@ -1,6 +1,9 @@ +mod browser; + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .invoke_handler(tauri::generate_handler![browser::get_current_browser_url]) .plugin(tauri_plugin_fs::init()) .run(tauri::generate_context!()) .expect("error while running tauri application"); diff --git a/flake.nix b/flake.nix index 422b3157..9b23d8b7 100644 --- a/flake.nix +++ b/flake.nix @@ -22,7 +22,11 @@ cargo-tauri ] ++ lib.optionals pkgs.stdenv.isDarwin ( - [ pkgs.libiconv ] ++ (with pkgs.darwin.apple_sdk.frameworks; [ WebKit ]) + [ pkgs.libiconv ] + ++ (with pkgs.darwin.apple_sdk.frameworks; [ + WebKit + OSAKit + ]) ); }; # TODO: Package LA using Nix diff --git a/lax b/lax new file mode 100755 index 00000000..0bc9ab1d --- /dev/null +++ b/lax @@ -0,0 +1,56 @@ +#!/usr/bin/env osascript -l JavaScript +ObjC.import('stdlib') + +function run(argv) { + let args = parse_args(argv); + let url = args.browser(+args.index); + let app = Application.currentApplication(); + app.includeStandardAdditions = true; + app.openLocation(`learn-anything://add-link?url=${encodeURIComponent(url)}`) +} + +function parse_args(argv) { + let args = []; + let browser = undefined; + for (i of argv) { + if (!i.startsWith("-")) { + args.push(i); + continue; + } + if (i == "-s" || i == "--safari") { + if (browser != undefined) usage(); + browser = safari; + } else if (i == "-c" || i == "--chrome") { + if (browser != undefined) usage(); + browser = chrome; + } else { + usage(); + } + } + if (args.length == 0) { + args = [0]; + } + if (args.length > 1) { + usage(); + } + if (browser == undefined) { + browser = safari; + } + return { + browser, + index: args[0], + }; +} + +function usage() { + console.log("Usage: lax [-s|--safari|-c|--chrome] [WINDOW]"); + $.exit(1); +} + +function safari(index) { + return Application("Safari").windows[index].currentTab.url(); +} + +function chrome(index) { + return Application("Google Chrome").windows[index].activeTab().url(); +}