diff --git a/backend/events.go b/backend/events.go index 5ff5251..ce2bc71 100644 --- a/backend/events.go +++ b/backend/events.go @@ -65,12 +65,7 @@ func ListenNewImageEvents(db *sql.DB, eventManager *EventManager) { } orchestrator := agents.NewOrchestratorAgent(createLogger("Orchestrator 🎼", splitWriter), noteAgent, contactAgent, locationAgent, eventAgent, image.Image.ImageName, image.Image.Image) - err = orchestrator.RunAgent(image.UserID, image.ImageID, image.Image.ImageName, image.Image.Image) - if err != nil { - databaseEventLog.Error("Orchestrator failed", "error", err) - return - } - + orchestrator.RunAgent(image.UserID, image.ImageID, image.Image.ImageName, image.Image.Image) _, err = imageModel.FinishProcessing(ctx, image.ID) if err != nil { databaseEventLog.Error("Failed to finish processing", "ImageID", imageId) diff --git a/frontend/.idea/.gitignore b/frontend/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/frontend/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/frontend/.idea/caches/deviceStreaming.xml b/frontend/.idea/caches/deviceStreaming.xml new file mode 100644 index 0000000..9e9ba09 --- /dev/null +++ b/frontend/.idea/caches/deviceStreaming.xml @@ -0,0 +1,607 @@ + + + + + + \ No newline at end of file diff --git a/frontend/.idea/frontend.iml b/frontend/.idea/frontend.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/frontend/.idea/frontend.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/frontend/.idea/misc.xml b/frontend/.idea/misc.xml new file mode 100644 index 0000000..639900d --- /dev/null +++ b/frontend/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/.idea/modules.xml b/frontend/.idea/modules.xml new file mode 100644 index 0000000..f3d93d7 --- /dev/null +++ b/frontend/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/frontend/.idea/vcs.xml b/frontend/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/frontend/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/frontend/.idea/workspace.xml b/frontend/.idea/workspace.xml new file mode 100644 index 0000000..9c6cebb --- /dev/null +++ b/frontend/.idea/workspace.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + { + "associatedIndex": 5 +} + + + + + + + + + 1745226104717 + + + + \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index d83836f..9002825 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "@tabler/icons-solidjs": "^3.30.0", "@tauri-apps/api": "^2", "@tauri-apps/plugin-dialog": "~2", + "@tauri-apps/plugin-fs": "~2", "@tauri-apps/plugin-http": "~2", "@tauri-apps/plugin-opener": "^2", "clsx": "^2.1.1", @@ -30,6 +31,7 @@ "solid-motionone": "^1.0.3", "solidjs-markdown": "^0.2.0", "tailwind-scrollbar-hide": "^2.0.0", + "tauri-plugin-sharetarget-api": "^0.1.6", "valibot": "^1.0.0-rc.2" }, "devDependencies": { diff --git a/frontend/src-tauri/Cargo.lock b/frontend/src-tauri/Cargo.lock index e777b10..a7d3e94 100644 --- a/frontend/src-tauri/Cargo.lock +++ b/frontend/src-tauri/Cargo.lock @@ -15,9 +15,12 @@ dependencies = [ "tauri", "tauri-build", "tauri-plugin-dialog", + "tauri-plugin-fs", "tauri-plugin-global-shortcut", "tauri-plugin-http", + "tauri-plugin-log", "tauri-plugin-opener", + "tauri-plugin-sharetarget", "tauri-plugin-store", "tokio", ] @@ -37,6 +40,17 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.15", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -67,6 +81,23 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" +[[package]] +name = "android_log-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" + +[[package]] +name = "android_logger" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f39be698127218cca460cb624878c9aa4e2b47dba3b277963d2bf00bad263b" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -82,6 +113,12 @@ version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "ashpd" version = "0.11.0" @@ -320,6 +357,18 @@ dependencies = [ "serde", ] +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "block" version = "0.1.6" @@ -366,6 +415,29 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +dependencies = [ + "once_cell", + "proc-macro-crate 3.3.0", + "proc-macro2", + "quote", + "syn 2.0.100", +] + [[package]] name = "brotli" version = "7.0.0" @@ -393,6 +465,39 @@ version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" +[[package]] +name = "byte-unit" +version = "5.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174" +dependencies = [ + "rust_decimal", + "serde", + "utf8-width", +] + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.22.0" @@ -1006,6 +1111,16 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1068,6 +1183,15 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "fern" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" +dependencies = [ + "log", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1151,6 +1275,12 @@ dependencies = [ "libc", ] +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futf" version = "0.1.5" @@ -1597,6 +1727,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -2224,6 +2357,9 @@ name = "log" version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +dependencies = [ + "value-bag", +] [[package]] name = "mac" @@ -2445,6 +2581,15 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc" version = "0.2.7" @@ -3073,6 +3218,26 @@ version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "publicsuffix" version = "2.3.0" @@ -3161,6 +3326,12 @@ version = "5.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -3327,6 +3498,15 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.15" @@ -3416,6 +3596,51 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rust_decimal" +version = "1.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3560,6 +3785,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "selectors" version = "0.22.0" @@ -3769,6 +4000,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "0.3.11" @@ -4040,6 +4277,12 @@ dependencies = [ "syn 2.0.100", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "target-lexicon" version = "0.12.16" @@ -4256,6 +4499,28 @@ dependencies = [ "urlpattern", ] +[[package]] +name = "tauri-plugin-log" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d2b582d860eb214f28323f4ce4f2797ae3b78f197e27b11677f976f9f52aedb" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2 0.6.0", + "objc2-foundation 0.3.0", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.12", + "time", +] + [[package]] name = "tauri-plugin-opener" version = "2.2.6" @@ -4278,6 +4543,20 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-sharetarget" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15a6e4638b6a5492a46847fc9e994df8cfd2dbc1bacc11f15c207d6a2163c341" +dependencies = [ + "serde", + "serde_json", + "tauri", + "tauri-build", + "tauri-plugin", + "thiserror 1.0.69", +] + [[package]] name = "tauri-plugin-store" version = "2.2.0" @@ -4467,7 +4746,9 @@ checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa 1.0.15", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -4828,6 +5109,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -4844,6 +5131,12 @@ dependencies = [ "serde", ] +[[package]] +name = "value-bag" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" + [[package]] name = "version-compare" version = "0.2.0" @@ -5680,6 +5973,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml index 359848d..66abbcd 100644 --- a/frontend/src-tauri/Cargo.toml +++ b/frontend/src-tauri/Cargo.toml @@ -19,19 +19,25 @@ tauri-build = { version = "2.0.0-beta.12", features = [] } [dependencies] tauri = { version = "2.0.0-beta.12", features = ["macos-private-api"] } -tauri-plugin-opener = "2.0.0-beta.12" serde = { version = "1", features = ["derive"] } serde_json = "1" -tauri-plugin-dialog = "2.0.0-beta.12" notify = "6.1.1" base64 = "0.21.7" tokio = { version = "1.36.0", features = ["full"] } tauri-plugin-store = "2.0.0-beta.12" tauri-plugin-http = "2.0.0-beta.12" chrono = "0.4" +tauri-plugin-log = "2" +tauri-plugin-sharetarget = "0.1.6" +tauri-plugin-fs = "2" +tauri-plugin-dialog = "2.2.1" +tauri-plugin-opener = "2.2.6" [target."cfg(target_os = \"macos\")".dependencies] cocoa = "0.26" [target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies] tauri-plugin-global-shortcut = "2.0.0-beta.12" + +[target."cfg(target_os = \"android\")".dependencies] +tauri-plugin-sharetarget = "0.1.6" diff --git a/frontend/src-tauri/capabilities/default.json b/frontend/src-tauri/capabilities/default.json deleted file mode 100644 index d8c4686..0000000 --- a/frontend/src-tauri/capabilities/default.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "../gen/schemas/desktop-schema.json", - "identifier": "default", - "description": "Capability for the main window", - "windows": ["main"], - "permissions": [ - "core:default", - "opener:default", - "dialog:default", - "core:window:allow-start-dragging", - "global-shortcut:allow-is-registered", - "global-shortcut:allow-register", - "global-shortcut:allow-unregister", - "global-shortcut:allow-unregister-all", - "http:default", - "core:window:allow-show", - "core:window:allow-set-focus", - { - "identifier": "http:default", - "allow": [ - { - "url": "https://haystack.johncosta.tech" - }, - { - "url": "http://localhost:3040" - } - ] - } - ] -} diff --git a/frontend/src-tauri/capabilities/desktop.toml b/frontend/src-tauri/capabilities/desktop.toml new file mode 100644 index 0000000..9cd239c --- /dev/null +++ b/frontend/src-tauri/capabilities/desktop.toml @@ -0,0 +1,16 @@ +identifier = "Desktop" +description = "Capabilities for desktop platforms" +windows = ["main"] +platforms = ["linux", "macOS", "windows"] + +permissions = [ + "core:default", + "core:window:allow-start-dragging", + "fs:default", + "http:default", + { identifier = "http:default", allow = [ + { url = "https://haystack.johncosta.tech" }, + { url = "http://localhost:3040" }, + { url = "http://192.168.1.199:3040" } + ] }, +] diff --git a/frontend/src-tauri/capabilities/mobile.toml b/frontend/src-tauri/capabilities/mobile.toml new file mode 100644 index 0000000..be5417f --- /dev/null +++ b/frontend/src-tauri/capabilities/mobile.toml @@ -0,0 +1,16 @@ +identifier = "Mobile" +description = "Capabilities for mobile platforms" +windows = ["main"] +platforms = ["android", "iOS"] + +permissions = [ + "core:default", + "fs:default", + "http:default", + "sharetarget:default", + { identifier = "http:default", allow = [ + { url = "https://haystack.johncosta.tech" }, + { url = "http://localhost:3040" }, + { url = "http://192.168.1.199:3040" } + ] }, +] diff --git a/frontend/src-tauri/gen/android/.editorconfig b/frontend/src-tauri/gen/android/.editorconfig new file mode 100644 index 0000000..ebe51d3 --- /dev/null +++ b/frontend/src-tauri/gen/android/.editorconfig @@ -0,0 +1,12 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = false +insert_final_newline = false \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/.gitignore b/frontend/src-tauri/gen/android/.gitignore new file mode 100644 index 0000000..b248203 --- /dev/null +++ b/frontend/src-tauri/gen/android/.gitignore @@ -0,0 +1,19 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +build +/captures +.externalNativeBuild +.cxx +local.properties +key.properties + +/.tauri +/tauri.settings.gradle \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/.gitignore b/frontend/src-tauri/gen/android/app/.gitignore new file mode 100644 index 0000000..538803f --- /dev/null +++ b/frontend/src-tauri/gen/android/app/.gitignore @@ -0,0 +1,6 @@ +/src/main/java/com/haystack/app/generated +/src/main/jniLibs/**/*.so +/src/main/assets/tauri.conf.json +/tauri.build.gradle.kts +/proguard-tauri.pro +/tauri.properties \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/build.gradle.kts b/frontend/src-tauri/gen/android/app/build.gradle.kts new file mode 100644 index 0000000..ec62fa2 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/build.gradle.kts @@ -0,0 +1,83 @@ +import java.util.Properties +import java.io.FileInputStream + +val keyPropertiesFile = rootProject.file("key.properties") +val keyProperties = Properties() +keyProperties.load(FileInputStream(keyPropertiesFile)) + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.android") + id("rust") +} + +val tauriProperties = Properties().apply { + val propFile = file("tauri.properties") + if (propFile.exists()) { + propFile.inputStream().use { load(it) } + } +} + +android { + compileSdk = 34 + namespace = "com.haystack.app" + defaultConfig { + manifestPlaceholders["usesCleartextTraffic"] = "false" + applicationId = "com.haystack.app" + minSdk = 24 + targetSdk = 34 + versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() + versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") + } + signingConfigs { + create("release") { + keyAlias = keyProperties["keyAlias"] as String + keyPassword = keyProperties["keyPassword"] as String + storeFile = file(keyProperties["storeFile"] as String) + storePassword = keyProperties["storePassword"] as String + } + } + buildTypes { + getByName("debug") { + manifestPlaceholders["usesCleartextTraffic"] = "true" + isDebuggable = true + isJniDebuggable = true + isMinifyEnabled = false + packaging { jniLibs.keepDebugSymbols.add("*/arm64-v8a/*.so") + jniLibs.keepDebugSymbols.add("*/armeabi-v7a/*.so") + jniLibs.keepDebugSymbols.add("*/x86/*.so") + jniLibs.keepDebugSymbols.add("*/x86_64/*.so") + } + } + getByName("release") { + isMinifyEnabled = true + proguardFiles( + *fileTree(".") { include("**/*.pro") } + .plus(getDefaultProguardFile("proguard-android-optimize.txt")) + .toList().toTypedArray() + ) + signingConfig = signingConfigs.getByName("release") + } + } + kotlinOptions { + jvmTarget = "1.8" + } + buildFeatures { + buildConfig = true + } +} + +rust { + rootDirRel = "../../../" +} + +dependencies { + implementation("androidx.webkit:webkit:1.6.1") + implementation("androidx.appcompat:appcompat:1.6.1") + implementation("com.google.android.material:material:1.8.0") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.4") + androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0") +} + +apply(from = "tauri.build.gradle.kts") \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/proguard-rules.pro b/frontend/src-tauri/gen/android/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml b/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..faad303 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src-tauri/gen/android/app/src/main/java/com/haystack/app/MainActivity.kt b/frontend/src-tauri/gen/android/app/src/main/java/com/haystack/app/MainActivity.kt new file mode 100644 index 0000000..8bbc680 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/java/com/haystack/app/MainActivity.kt @@ -0,0 +1,3 @@ +package com.haystack.app + +class MainActivity : TauriActivity() \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/frontend/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml b/frontend/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..07d5da9 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml b/frontend/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..4fc2444 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..28f1aa1 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..85d0c88 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..28f1aa1 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..73e48db Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..13dd214 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..73e48db Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..1d98044 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..a888b33 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..1d98044 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..0818324 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..a2a838e Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..0818324 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b18bceb Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..3f8a57f Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..b18bceb Binary files /dev/null and b/frontend/src-tauri/gen/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/frontend/src-tauri/gen/android/app/src/main/res/values-night/themes.xml b/frontend/src-tauri/gen/android/app/src/main/res/values-night/themes.xml new file mode 100644 index 0000000..3bf00f3 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/values-night/themes.xml @@ -0,0 +1,6 @@ + + + + diff --git a/frontend/src-tauri/gen/android/app/src/main/res/values/colors.xml b/frontend/src-tauri/gen/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..f8c6127 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/values/colors.xml @@ -0,0 +1,10 @@ + + + #FFBB86FC + #FF6200EE + #FF3700B3 + #FF03DAC5 + #FF018786 + #FF000000 + #FFFFFFFF + \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/res/values/strings.xml b/frontend/src-tauri/gen/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..05a98f5 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + Haystack + Haystack + \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/app/src/main/res/values/themes.xml b/frontend/src-tauri/gen/android/app/src/main/res/values/themes.xml new file mode 100644 index 0000000..3bf00f3 --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/values/themes.xml @@ -0,0 +1,6 @@ + + + + diff --git a/frontend/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml b/frontend/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml new file mode 100644 index 0000000..782d63b --- /dev/null +++ b/frontend/src-tauri/gen/android/app/src/main/res/xml/file_paths.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/frontend/src-tauri/gen/android/app/upload-keystore.jks b/frontend/src-tauri/gen/android/app/upload-keystore.jks new file mode 100644 index 0000000..165c579 Binary files /dev/null and b/frontend/src-tauri/gen/android/app/upload-keystore.jks differ diff --git a/frontend/src-tauri/gen/android/build.gradle.kts b/frontend/src-tauri/gen/android/build.gradle.kts new file mode 100644 index 0000000..c5ef452 --- /dev/null +++ b/frontend/src-tauri/gen/android/build.gradle.kts @@ -0,0 +1,22 @@ +buildscript { + repositories { + google() + mavenCentral() + } + dependencies { + classpath("com.android.tools.build:gradle:8.5.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +tasks.register("clean").configure { + delete("build") +} + diff --git a/frontend/src-tauri/gen/android/buildSrc/build.gradle.kts b/frontend/src-tauri/gen/android/buildSrc/build.gradle.kts new file mode 100644 index 0000000..39e90b0 --- /dev/null +++ b/frontend/src-tauri/gen/android/buildSrc/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + `kotlin-dsl` +} + +gradlePlugin { + plugins { + create("pluginsForCoolKids") { + id = "rust" + implementationClass = "RustPlugin" + } + } +} + +repositories { + google() + mavenCentral() +} + +dependencies { + compileOnly(gradleApi()) + implementation("com.android.tools.build:gradle:8.5.1") +} + diff --git a/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/BuildTask.kt b/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/BuildTask.kt new file mode 100644 index 0000000..6276570 --- /dev/null +++ b/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/BuildTask.kt @@ -0,0 +1,52 @@ +import java.io.File +import org.apache.tools.ant.taskdefs.condition.Os +import org.gradle.api.DefaultTask +import org.gradle.api.GradleException +import org.gradle.api.logging.LogLevel +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +open class BuildTask : DefaultTask() { + @Input + var rootDirRel: String? = null + @Input + var target: String? = null + @Input + var release: Boolean? = null + + @TaskAction + fun assemble() { + val executable = """bun"""; + try { + runTauriCli(executable) + } catch (e: Exception) { + if (Os.isFamily(Os.FAMILY_WINDOWS)) { + runTauriCli("$executable.cmd") + } else { + throw e; + } + } + } + + fun runTauriCli(executable: String) { + val rootDirRel = rootDirRel ?: throw GradleException("rootDirRel cannot be null") + val target = target ?: throw GradleException("target cannot be null") + val release = release ?: throw GradleException("release cannot be null") + val args = listOf("tauri", "android", "android-studio-script"); + + project.exec { + workingDir(File(project.projectDir, rootDirRel)) + executable(executable) + args(args) + if (project.logger.isEnabled(LogLevel.DEBUG)) { + args("-vv") + } else if (project.logger.isEnabled(LogLevel.INFO)) { + args("-v") + } + if (release) { + args("--release") + } + args(listOf("--target", target)) + }.assertNormalExitValue() + } +} \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/RustPlugin.kt b/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/RustPlugin.kt new file mode 100644 index 0000000..4aa7fca --- /dev/null +++ b/frontend/src-tauri/gen/android/buildSrc/src/main/java/com/haystack/app/kotlin/RustPlugin.kt @@ -0,0 +1,85 @@ +import com.android.build.api.dsl.ApplicationExtension +import org.gradle.api.DefaultTask +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.get + +const val TASK_GROUP = "rust" + +open class Config { + lateinit var rootDirRel: String +} + +open class RustPlugin : Plugin { + private lateinit var config: Config + + override fun apply(project: Project) = with(project) { + config = extensions.create("rust", Config::class.java) + + val defaultAbiList = listOf("arm64-v8a", "armeabi-v7a", "x86", "x86_64"); + val abiList = (findProperty("abiList") as? String)?.split(',') ?: defaultAbiList + + val defaultArchList = listOf("arm64", "arm", "x86", "x86_64"); + val archList = (findProperty("archList") as? String)?.split(',') ?: defaultArchList + + val targetsList = (findProperty("targetList") as? String)?.split(',') ?: listOf("aarch64", "armv7", "i686", "x86_64") + + extensions.configure { + @Suppress("UnstableApiUsage") + flavorDimensions.add("abi") + productFlavors { + create("universal") { + dimension = "abi" + ndk { + abiFilters += abiList + } + } + defaultArchList.forEachIndexed { index, arch -> + create(arch) { + dimension = "abi" + ndk { + abiFilters.add(defaultAbiList[index]) + } + } + } + } + } + + afterEvaluate { + for (profile in listOf("debug", "release")) { + val profileCapitalized = profile.replaceFirstChar { it.uppercase() } + val buildTask = tasks.maybeCreate( + "rustBuildUniversal$profileCapitalized", + DefaultTask::class.java + ).apply { + group = TASK_GROUP + description = "Build dynamic library in $profile mode for all targets" + } + + tasks["mergeUniversal${profileCapitalized}JniLibFolders"].dependsOn(buildTask) + + for (targetPair in targetsList.withIndex()) { + val targetName = targetPair.value + val targetArch = archList[targetPair.index] + val targetArchCapitalized = targetArch.replaceFirstChar { it.uppercase() } + val targetBuildTask = project.tasks.maybeCreate( + "rustBuild$targetArchCapitalized$profileCapitalized", + BuildTask::class.java + ).apply { + group = TASK_GROUP + description = "Build dynamic library in $profile mode for $targetArch" + rootDirRel = config.rootDirRel + target = targetName + release = profile == "release" + } + + buildTask.dependsOn(targetBuildTask) + tasks["merge$targetArchCapitalized${profileCapitalized}JniLibFolders"].dependsOn( + targetBuildTask + ) + } + } + } + } +} \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/gradle.properties b/frontend/src-tauri/gen/android/gradle.properties new file mode 100644 index 0000000..bb2051d --- /dev/null +++ b/frontend/src-tauri/gen/android/gradle.properties @@ -0,0 +1,25 @@ +# Project-wide Gradle settings. +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app"s APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true +# Kotlin code style for this project: "official" or "obsolete": +kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +android.nonFinalResIds=false +# org.gradle.java.home=/usr/lib/jvm/java-21-openjdk \ No newline at end of file diff --git a/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar b/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..e708b1c Binary files /dev/null and b/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties b/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..0df10d5 --- /dev/null +++ b/frontend/src-tauri/gen/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Tue May 10 19:22:52 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/frontend/src-tauri/gen/android/gradlew b/frontend/src-tauri/gen/android/gradlew new file mode 100755 index 0000000..4f906e0 --- /dev/null +++ b/frontend/src-tauri/gen/android/gradlew @@ -0,0 +1,185 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/frontend/src-tauri/gen/android/gradlew.bat b/frontend/src-tauri/gen/android/gradlew.bat new file mode 100644 index 0000000..107acd3 --- /dev/null +++ b/frontend/src-tauri/gen/android/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/frontend/src-tauri/gen/android/settings.gradle b/frontend/src-tauri/gen/android/settings.gradle new file mode 100644 index 0000000..3939116 --- /dev/null +++ b/frontend/src-tauri/gen/android/settings.gradle @@ -0,0 +1,3 @@ +include ':app' + +apply from: 'tauri.settings.gradle' diff --git a/frontend/src-tauri/src/lib.rs b/frontend/src-tauri/src/lib.rs index b977eec..f76e08e 100644 --- a/frontend/src-tauri/src/lib.rs +++ b/frontend/src-tauri/src/lib.rs @@ -1,22 +1,26 @@ mod commands; pub mod screenshot; -pub mod shortcut; mod state; pub mod utils; mod window; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] +mod shortcut; + use state::new_shared_watcher_state; use window::setup_window; -#[cfg_attr(mobile, tauri::mobile_entry_point)] -pub fn run() { +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] +pub fn desktop() { let watcher_state = new_shared_watcher_state(); tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_http::init()) - .plugin(tauri_plugin_dialog::init()) - .plugin(tauri_plugin_opener::init()) + .plugin(tauri_plugin_sharetarget::init()) + // .plugin(tauri_plugin_dialog::init()) + // .plugin(tauri_plugin_opener::init()) .manage(watcher_state) .invoke_handler(tauri::generate_handler![ commands::handle_selected_folder, @@ -36,3 +40,20 @@ pub fn run() { .run(tauri::generate_context!()) .expect("error while running tauri application"); } + +#[cfg_attr(mobile, tauri::mobile_entry_point)] +#[cfg(any(target_os = "ios", target_os = "android"))] +pub fn android() { + tauri::Builder::default() + .plugin(tauri_plugin_fs::init()) + .plugin(tauri_plugin_store::Builder::new().build()) + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_sharetarget::init()) + .setup(|app| { + setup_window(app)?; + + Ok(()) + }) + .run(tauri::generate_context!()) + .expect("error while running android tauri application"); +} diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index d5ca6e0..cc833e9 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -2,5 +2,9 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] fn main() { - haystack_lib::run() + #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] + haystack_lib::desktop(); + + #[cfg(any(target_os = "ios", target_os = "android"))] + haystack_lib::android(); } diff --git a/frontend/src-tauri/src/window.rs b/frontend/src-tauri/src/window.rs index 5c8767f..d271158 100644 --- a/frontend/src-tauri/src/window.rs +++ b/frontend/src-tauri/src/window.rs @@ -2,10 +2,10 @@ use tauri::App; use tauri::{WebviewUrl, WebviewWindowBuilder}; pub fn setup_window(app: &mut App) -> Result<(), Box> { - let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()) - .inner_size(480.0, 360.0) - .title("Haystack") - .resizable(false); + let win_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default()); + //.inner_size(480.0, 360.0) + //.title("Haystack") + //.resizable(false); #[cfg(target_os = "macos")] { @@ -31,7 +31,6 @@ pub fn setup_window(app: &mut App) -> Result<(), Box> { } } - #[cfg(target_os = "linux")] { win_builder.build().unwrap(); } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index c4fefac..7dcf0ed 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -6,6 +6,7 @@ import { ProtectedRoute } from "./ProtectedRoute"; import { Search } from "./Search"; import { Settings } from "./Settings"; import { ImageViewer } from "./components/ImageViewer"; +import { ShareTarget } from "./components/share-target/ShareTarget"; export const App = () => { createEffect(() => { @@ -22,6 +23,7 @@ export const App = () => { return ( <> + diff --git a/frontend/src/components/share-target/ShareTarget.tsx b/frontend/src/components/share-target/ShareTarget.tsx new file mode 100644 index 0000000..b3f99fa --- /dev/null +++ b/frontend/src/components/share-target/ShareTarget.tsx @@ -0,0 +1,47 @@ +import { readFile } from "@tauri-apps/plugin-fs"; +import { type Component, createEffect, createSignal, Show } from "solid-js"; +import { listenForShareEvents } from "tauri-plugin-sharetarget-api"; +import { sendImageFile } from "../../network"; + +export const ShareTarget: Component = () => { + const [file, setFile] = createSignal(); + + createEffect(() => { + const listener = listenForShareEvents(async (intent) => { + if (intent.stream == null) { + throw new Error( + "The shared item does not have a stream to read form. This might be an issue with the type of file that was shared.", + ); + } + + if (intent.name == null) { + throw new Error("The shared item does not have a name."); + } + + const contents = await readFile(intent.stream); + + setFile( + new File([contents], intent.name, { + type: intent.content_type, + }), + ); + }); + + return () => { + listener.then((l) => l.unregister()); + }; + }); + + // TODO: This might be made better by just sending the file without setting it. + // And simply displaying a message or not displaying anything really. + createEffect(() => { + const f = file(); + if (f == null) { + return; + } + + sendImageFile(f.name, f); + }); + + return {(f) =>

Name: {f().name}

}
; +}; diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 0e0c8ca..0e8f6d5 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -1,8 +1,21 @@ /* @refresh reload */ import { render } from "solid-js/web"; - import "./index.css"; - import { App } from "./App"; +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); +console.log("Hello android!"); + render(() => , document.getElementById("root") as HTMLElement); diff --git a/frontend/src/network/index.ts b/frontend/src/network/index.ts index c5b58b0..4f4ae0e 100644 --- a/frontend/src/network/index.ts +++ b/frontend/src/network/index.ts @@ -19,9 +19,7 @@ type BaseRequestParams = Partial<{ method: "GET" | "POST"; }>; -export const base = import.meta.env.DEV - ? "http://localhost:3040" - : "https://haystack.johncosta.tech"; +export const base = "http://192.168.1.199:3040"; const getBaseRequest = ({ path, body, method }: BaseRequestParams): Request => { return new Request(`${base}/${path}`, { @@ -50,6 +48,23 @@ const sendImageResponseValidator = strictObject({ Status: string(), }); +export const sendImageFile = async ( + imageName: string, + file: File, +): Promise> => { + const request = getBaseAuthorizedRequest({ + path: `image/${imageName}`, + body: file, + method: "POST", + }); + + request.headers.set("Content-Type", "application/oclet-stream"); + + const res = await fetch(request).then((res) => res.json()); + + return parse(sendImageResponseValidator, res); +}; + export const sendImage = async ( imageName: string, base64Image: string, diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 5cd5350..a70b4ea 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -25,10 +25,10 @@ export default defineConfig(async () => ({ host: host || false, hmr: host ? { - protocol: "ws", - host, - port: 1421, - } + protocol: "ws", + host, + port: 1421, + } : undefined, watch: { // 3. tell vite to ignore watching `src-tauri`