diff --git a/apps/tauri/package.json b/apps/tauri/package.json index 8eab808..7b7e5a7 100644 --- a/apps/tauri/package.json +++ b/apps/tauri/package.json @@ -14,7 +14,7 @@ } }, "scripts": { - "dev:mobile:raw": "adb reverse tcp:3000 tcp:3000 && tauri android dev --host ${TAURI_DEV_HOST:-127.0.0.1}", + "dev:mobile:raw": "tauri android dev --host ${TAURI_DEV_HOST:-127.0.0.1}", "start-adb:mobile:raw": "adb devices", "build:mobile:raw": "tauri android build", "build:mobile:ci": "node render-version.ts && trap 'node render-version.ts --unrender' EXIT && tauri android build --debug", diff --git a/apps/tauri/src-tauri/Cargo.lock b/apps/tauri/src-tauri/Cargo.lock index 744d5a2..8e5d93d 100644 --- a/apps/tauri/src-tauri/Cargo.lock +++ b/apps/tauri/src-tauri/Cargo.lock @@ -560,6 +560,17 @@ dependencies = [ "uuid", ] +[[package]] +name = "cfb" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a347dcabdae9c31b0825fd6a8bed285ec9c2acb89c47827126d52fa4f59cece3" +dependencies = [ + "fnv", + "uuid", + "web-time", +] + [[package]] name = "cfg-expr" version = "0.15.8" @@ -832,7 +843,20 @@ version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" dependencies = [ - "cssparser-macros", + "cssparser-macros 0.6.1", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser" +version = "0.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9cdaae01d5ed7882b04d795e7f752f46ff52d2fa3b50a20d28c464510bba98" +dependencies = [ + "cssparser-macros 0.7.0", "dtoa-short", "itoa", "phf", @@ -849,6 +873,16 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "cssparser-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a2a99df6e410a8ff4245aa2006499ea662245f967cc7c0a38c83ef8eb44dbf" +dependencies = [ + "quote", + "syn 2.0.119", +] + [[package]] name = "ctor" version = "0.8.0" @@ -1145,11 +1179,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ "bit-set", - "cssparser", + "cssparser 0.36.0", "foldhash", - "html5ever", + "html5ever 0.38.0", "precomputed-hash", - "selectors", + "selectors 0.36.1", + "tendril", +] + +[[package]] +name = "dom_query" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac5fca71e65e94cc718a6e2af65d6e0f9c6027751c2aa562fbb5087fda639bc" +dependencies = [ + "bit-set", + "cssparser 0.37.0", + "foldhash", + "html5ever 0.39.0", + "precomputed-hash", + "selectors 0.38.0", "tendril", ] @@ -1334,7 +1383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2024,7 +2073,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "markup5ever", + "markup5ever 0.38.0", +] + +[[package]] +name = "html5ever" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a1761807faccc9a19e86944bbf40610014066306f96edcdedc2fb714bcb7b8" +dependencies = [ + "log", + "markup5ever 0.39.0", ] [[package]] @@ -2123,6 +2182,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots", ] [[package]] @@ -2160,7 +2220,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -2320,7 +2380,16 @@ version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" dependencies = [ - "cfb", + "cfb 0.7.3", +] + +[[package]] +name = "infer" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4200d433cbd5178df7797c9c2e75b348b728e39631cf14520d1e2fc424201f4" +dependencies = [ + "cfb 0.14.0", ] [[package]] @@ -2683,6 +2752,17 @@ dependencies = [ "web_atoms", ] +[[package]] +name = "markup5ever" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7122d987ec5f704ee56f6e5b41a7d93722e9aae27ae07cafa4036c4d3f9757de" +dependencies = [ + "log", + "tendril", + "web_atoms", +] + [[package]] name = "memchr" version = "2.8.3" @@ -3840,7 +3920,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4020,14 +4100,13 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", "futures-core", - "futures-util", "http", "http-body", "http-body-util", @@ -4041,12 +4120,45 @@ dependencies = [ "quinn", "rustls", "rustls-pki-types", - "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", "serde", "serde_json", "sync_wrapper", "tokio", - "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -4116,7 +4228,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4175,7 +4287,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -4328,7 +4440,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5d9c0c92a92d33f08817311cf3f2c29a3538a8240e94a6a3c622ce652d7e00c" dependencies = [ "bitflags 2.13.1", - "cssparser", + "cssparser 0.36.0", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", +] + +[[package]] +name = "selectors" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8adfa1c298912827b8a28b223b3b874357397ae706e6190acd9bf28cee99114d" +dependencies = [ + "bitflags 2.13.1", + "cssparser 0.37.0", "derive_more", "log", "new_debug_unreachable", @@ -4457,6 +4588,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "3.21.0" @@ -4888,7 +5031,7 @@ dependencies = [ "unicode-segmentation", "url", "windows", - "windows-core", + "windows-core 0.61.2", "windows-version", "x11-dl", ] @@ -4939,13 +5082,13 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest", + "reqwest 0.13.4", "serde", "serde_json", "serde_repr", "serialize-to-javascript", "swift-rs", - "tauri-build", + "tauri-build 2.6.3 (git+https://github.com/tauri-apps/tauri?rev=4af26a3f7f8b692d62cca549bbacd93f5ce90b41)", "tauri-macros", "tauri-runtime", "tauri-runtime-wry", @@ -4980,6 +5123,26 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-build" +version = "2.6.3" +source = "git+https://github.com/tauri-apps/tauri?rev=e2e585ad1196c9572f86ef39aae01ef4c3b1a762#e2e585ad1196c9572f86ef39aae01ef4c3b1a762" +dependencies = [ + "anyhow", + "cargo_toml", + "dirs", + "glob", + "heck 0.5.0", + "json-patch 4.2.0", + "schemars 0.8.22", + "semver", + "serde", + "serde_json", + "tauri-utils 2.9.3 (git+https://github.com/tauri-apps/tauri?rev=e2e585ad1196c9572f86ef39aae01ef4c3b1a762)", + "tauri-winres", + "walkdir", +] + [[package]] name = "tauri-codegen" version = "2.6.3" @@ -5067,7 +5230,7 @@ dependencies = [ "tracing", "url", "windows-registry", - "windows-result", + "windows-result 0.3.4", ] [[package]] @@ -5188,11 +5351,11 @@ dependencies = [ "anyhow", "cargo_metadata", "ctor 0.8.0", - "dom_query", + "dom_query 0.27.0", "dunce", "glob", "http", - "infer", + "infer 0.19.0", "json-patch 3.0.1", "log", "memchr", @@ -5224,11 +5387,11 @@ dependencies = [ "brotli", "cargo_metadata", "ctor 1.0.12", - "dom_query", + "dom_query 0.27.0", "dunce", "glob", "http", - "infer", + "infer 0.19.0", "json-patch 4.2.0", "log", "memchr", @@ -5252,6 +5415,42 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-utils" +version = "2.9.3" +source = "git+https://github.com/tauri-apps/tauri?rev=e2e585ad1196c9572f86ef39aae01ef4c3b1a762#e2e585ad1196c9572f86ef39aae01ef4c3b1a762" +dependencies = [ + "anyhow", + "cargo_metadata", + "ctor 1.0.12", + "dom_query 0.28.0", + "dunce", + "glob", + "http", + "infer 0.22.0", + "json-patch 4.2.0", + "log", + "memchr", + "phf", + "plist", + "proc-macro2", + "quote", + "regex", + "schemars 0.8.22", + "semver", + "serde", + "serde-untagged", + "serde_json", + "serde_with", + "swift-rs", + "thiserror 2.0.19", + "toml 1.1.4+spec-1.1.0", + "url", + "urlpattern 0.6.0", + "uuid", + "walkdir", +] + [[package]] name = "tauri-winres" version = "0.3.6" @@ -5281,10 +5480,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.4", + "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -5298,17 +5497,17 @@ dependencies = [ [[package]] name = "tensamin" -version = "0.0.11" +version = "0.0.0" dependencies = [ "base64 0.22.1", "jni 0.22.4", "mtp", "mtp-transport 0.2.0 (git+https://git.methanium.net/methanium/mtp.git?rev=b067614a684eb1856bc5db7b3fd82148c036ce6b)", - "reqwest", + "reqwest 0.12.28", "serde", "serde_json", "tauri", - "tauri-build", + "tauri-build 2.6.3 (git+https://github.com/tauri-apps/tauri?rev=e2e585ad1196c9572f86ef39aae01ef4c3b1a762)", "tauri-plugin-barcode-scanner", "tauri-plugin-deep-link", "tauri-plugin-log", @@ -6066,6 +6265,15 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.38.2" @@ -6075,7 +6283,7 @@ dependencies = [ "webview2-com-macros", "webview2-com-sys", "windows", - "windows-core", + "windows-core 0.61.2", "windows-implement", "windows-interface", ] @@ -6099,7 +6307,7 @@ checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ "thiserror 2.0.19", "windows", - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -6124,7 +6332,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -6155,7 +6363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ "windows-collections", - "windows-core", + "windows-core 0.61.2", "windows-future", "windows-link 0.1.3", "windows-numerics", @@ -6167,7 +6375,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-core", + "windows-core 0.61.2", ] [[package]] @@ -6179,8 +6387,21 @@ dependencies = [ "windows-implement", "windows-interface", "windows-link 0.1.3", - "windows-result", - "windows-strings", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -6189,7 +6410,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "windows-core", + "windows-core 0.61.2", "windows-link 0.1.3", "windows-threading", ] @@ -6234,7 +6455,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ - "windows-core", + "windows-core 0.61.2", "windows-link 0.1.3", ] @@ -6245,8 +6466,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" dependencies = [ "windows-link 0.1.3", - "windows-result", - "windows-strings", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -6258,6 +6479,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-strings" version = "0.4.2" @@ -6267,6 +6497,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-sys" version = "0.45.0" @@ -6493,7 +6732,7 @@ dependencies = [ "cookie", "crossbeam-channel", "dirs", - "dom_query", + "dom_query 0.27.0", "dpi", "dunce", "gdkx11", @@ -6521,7 +6760,7 @@ dependencies = [ "webkit2gtk-sys", "webview2-com", "windows", - "windows-core", + "windows-core 0.61.2", "windows-version", "x11-dl", ] diff --git a/apps/tauri/src-tauri/Cargo.toml b/apps/tauri/src-tauri/Cargo.toml index 3b7e6b5..3c70f02 100644 --- a/apps/tauri/src-tauri/Cargo.toml +++ b/apps/tauri/src-tauri/Cargo.toml @@ -15,14 +15,14 @@ name = "mobile_lib" crate-type = ["staticlib", "cdylib", "rlib"] [build-dependencies] -tauri-build = { git = "https://github.com/tauri-apps/tauri", rev = "4af26a3f7f8b692d62cca549bbacd93f5ce90b41", features = [] } +tauri-build = { git = "https://github.com/tauri-apps/tauri", rev = "e2e585ad1196c9572f86ef39aae01ef4c3b1a762", features = [] } [dependencies] tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" base64 = "0.22" -reqwest = { version = "0.13", default-features = false, features = ["json", "rustls"] } +reqwest = { version = "0.13", default-features = false, features = ["json", "rustls-tls"] } tokio = { version = "1", features = ["rt-multi-thread", "sync", "time"] } mtp = { git = "https://git.methanium.net/methanium/mtp.git", rev = "7182272e3edb0079d7b74b45b2f62a298d2fee22", features = ["client", "crypto"] } mtp-transport = { git = "https://git.methanium.net/methanium/mtp.git", rev = "b067614a684eb1856bc5db7b3fd82148c036ce6b" } diff --git a/apps/tauri/src-tauri/capabilities/mobile.json b/apps/tauri/src-tauri/capabilities/mobile.json index 7121f98..447a06f 100644 --- a/apps/tauri/src-tauri/capabilities/mobile.json +++ b/apps/tauri/src-tauri/capabilities/mobile.json @@ -1,9 +1,13 @@ { "identifier": "mobile-capability", - "platforms": ["android", "iOS"], - "windows": ["main"], + "platforms": [ + "android", + "iOS" + ], + "windows": [ + "main" + ], "permissions": [ - "core:event:default", "deep-link:default", "barcode-scanner:default", "barcode-scanner:allow-scan", diff --git a/apps/tauri/src-tauri/gen/android/app/build.gradle.kts b/apps/tauri/src-tauri/gen/android/app/build.gradle.kts index 66d6289..e7120ba 100644 --- a/apps/tauri/src-tauri/gen/android/app/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/app/build.gradle.kts @@ -1,4 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget import java.util.Properties import java.io.FileInputStream @@ -62,17 +61,14 @@ android { ) } } + kotlinOptions { + jvmTarget = "1.8" + } buildFeatures { buildConfig = true } } -kotlin { - compilerOptions { - jvmTarget = JvmTarget.JVM_1_8 - } -} - rust { rootDirRel = "../../../" } diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt index fc3be18..bd10948 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MainActivity.kt @@ -3,8 +3,10 @@ package net.tensamin.client import android.Manifest import android.app.Activity import android.content.pm.PackageManager +import android.graphics.Rect import android.media.projection.MediaProjectionManager import android.os.Bundle +import android.view.ViewGroup import android.view.ViewTreeObserver import android.view.WindowManager import android.webkit.JavascriptInterface @@ -54,7 +56,7 @@ class MainActivity : TauriActivity() { } override fun onWebViewCreate(webView: WebView) { - NativeAccessibilityBridge.attach(webView) + webView.setInitialScale(290) mediaWebView = webView MobileMediaEvents.attach(webView) webView.addJavascriptInterface(MobileMediaJavascriptInterface(), "tensaminMobileMedia") @@ -63,12 +65,11 @@ class MainActivity : TauriActivity() { override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, true) window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) - super.onCreate(savedInstanceState) - NativeMtpBridge.nativeAttach(applicationContext) if (MtpSecureStore.isEnabled(this) && MtpSecureStore.hasConfig(this)) { NativeMtpBridge.startService(this) } - NativeAccessibilityBridge.nativeAttach(applicationContext) + super.onCreate(savedInstanceState) + NativeMtpBridge.nativeAttach(applicationContext) installKeyboardResizeWorkaround() } @@ -89,10 +90,7 @@ class MainActivity : TauriActivity() { attachLayoutListener = null contentRoot = null contentChild = null - mediaWebView?.let { - NativeAccessibilityBridge.detach(it) - it.removeJavascriptInterface("tensaminMobileMedia") - } + mediaWebView?.removeJavascriptInterface("tensaminMobileMedia") mediaWebView = null MobileMediaEvents.detach() super.onDestroy() @@ -205,20 +203,16 @@ class MainActivity : TauriActivity() { child: android.view.View, insets: WindowInsetsCompat? = ViewCompat.getRootWindowInsets(child), ) { + val visibleFrame = Rect() + child.getWindowVisibleDisplayFrame(visibleFrame) + val rootHeight = child.rootView.height if (rootHeight <= 0) return - val imeVisible = insets?.isVisible(WindowInsetsCompat.Type.ime()) == true - val imeHeight = if (imeVisible) { - insets.getInsets(WindowInsetsCompat.Type.ime()).bottom - } else { - 0 - } - val usableHeight = if (imeHeight in 1 until rootHeight) { - rootHeight - imeHeight - } else { - WindowManager.LayoutParams.MATCH_PARENT - } + val imeHeight = insets?.getInsets(WindowInsetsCompat.Type.ime())?.bottom ?: 0 + val keyboardHeight = maxOf(imeHeight, rootHeight - visibleFrame.bottom) + val keyboardVisible = keyboardHeight > rootHeight * 0.15 + val usableHeight = if (keyboardVisible) rootHeight - keyboardHeight else ViewGroup.LayoutParams.MATCH_PARENT if (previousUsableHeight == usableHeight) return diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt index 3e961df..0afa75a 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MediaProjectionService.kt @@ -26,7 +26,6 @@ import android.os.HandlerThread import android.os.IBinder import android.util.Base64 import android.util.DisplayMetrics -import androidx.core.app.NotificationCompat import androidx.core.content.ContextCompat import java.io.ByteArrayOutputStream import java.util.concurrent.atomic.AtomicBoolean @@ -108,12 +107,16 @@ class MediaProjectionService : Service() { stopIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, ) - val notification = NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) + val notification = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + android.app.Notification.Builder(this, NOTIFICATION_CHANNEL_ID) + } else { + android.app.Notification.Builder(this) + } .setSmallIcon(android.R.drawable.ic_menu_share) .setContentTitle("Tensamin is sharing your screen") .setContentText("Tap Stop to end screen sharing") .setOngoing(true) - .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setCategory(android.app.Notification.CATEGORY_SERVICE) .addAction(android.R.drawable.ic_media_pause, "Stop", stopPendingIntent) .build() diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt index 56cca97..8b41c78 100644 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt +++ b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/MtpForegroundService.kt @@ -13,8 +13,6 @@ import android.net.Network import android.net.NetworkCapabilities import android.os.Build import android.os.IBinder -import android.os.Process -import android.os.SystemClock import androidx.core.app.NotificationCompat class MtpForegroundService : Service() { @@ -76,19 +74,10 @@ class MtpForegroundService : Service() { } override fun onTaskRemoved(rootIntent: Intent?) { - val preferences = getSharedPreferences(SERVICE_PREFERENCES, Context.MODE_PRIVATE) - val now = SystemClock.elapsedRealtime() - if (now - preferences.getLong(LAST_TASK_RESTART, 0) < TASK_RESTART_COOLDOWN_MS) { - super.onTaskRemoved(rootIntent) - return - } - preferences.edit().putLong(LAST_TASK_RESTART, now).commit() if (MtpSecureStore.isEnabled(this) && MtpSecureStore.hasConfig(this)) { startService(Intent(this, MtpForegroundService::class.java)) } super.onTaskRemoved(rootIntent) - // Tauri cannot recreate its WebView after the UI task is removed while this process survives. - Process.killProcess(Process.myPid()) } override fun onDestroy() { @@ -105,9 +94,6 @@ class MtpForegroundService : Service() { private const val CHANNEL_ID = "tensamin-connection" private const val NOTIFICATION_ID = 2201 private const val ACTION_STOP = "net.tensamin.client.STOP_MTP" - private const val SERVICE_PREFERENCES = "tensamin-service" - private const val LAST_TASK_RESTART = "last-task-restart" - private const val TASK_RESTART_COOLDOWN_MS = 15_000L @Volatile private var connectionStatus = "Connecting" fun updateNotification(context: Context, status: String) { diff --git a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt b/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt deleted file mode 100644 index e04365a..0000000 --- a/apps/tauri/src-tauri/gen/android/app/src/main/java/net/tensamin/client/NativeAccessibilityBridge.kt +++ /dev/null @@ -1,51 +0,0 @@ -package net.tensamin.client - -import android.content.Context -import android.webkit.WebView -import androidx.annotation.Keep -import java.lang.ref.WeakReference - -@Keep -object NativeAccessibilityBridge { - const val DEFAULT_INITIAL_SCALE = 290 - private const val MIN_INITIAL_SCALE = 210 - private const val MAX_INITIAL_SCALE = 500 - private const val PREFERENCES = "tensamin-accessibility" - private const val INITIAL_SCALE = "initial-scale" - - private var webView = WeakReference(null) - - init { - System.loadLibrary("mobile_lib") - } - - @JvmStatic external fun nativeAttach(context: Context) - - fun attach(webView: WebView) { - this.webView = WeakReference(webView) - webView.setInitialScale(getInitialScale(webView.context)) - } - - fun detach(webView: WebView) { - if (this.webView.get() === webView) this.webView.clear() - } - - fun getInitialScale(context: Context): Int { - val preferences = context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE) - val storedScale = preferences.getInt(INITIAL_SCALE, DEFAULT_INITIAL_SCALE) - val scale = storedScale.coerceIn(MIN_INITIAL_SCALE, MAX_INITIAL_SCALE) - if (scale != storedScale) preferences.edit().putInt(INITIAL_SCALE, scale).apply() - return scale - } - - fun setInitialScale(context: Context, initialScale: Int) { - val nextScale = initialScale.coerceIn(MIN_INITIAL_SCALE, MAX_INITIAL_SCALE) - context.getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE) - .edit() - .putInt(INITIAL_SCALE, nextScale) - .apply() - webView.get()?.let { currentWebView -> - currentWebView.post { currentWebView.setInitialScale(nextScale) } - } - } -} diff --git a/apps/tauri/src-tauri/gen/android/build.gradle.kts b/apps/tauri/src-tauri/gen/android/build.gradle.kts index 1488b27..20ec414 100644 --- a/apps/tauri/src-tauri/gen/android/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/build.gradle.kts @@ -1,4 +1,4 @@ -import com.android.build.api.dsl.LibraryExtension +import com.android.build.gradle.LibraryExtension buildscript { repositories { @@ -6,8 +6,8 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.11.0") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20") + classpath("com.android.tools.build:gradle:9.3.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.4.10") } } diff --git a/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts b/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts index 09776c6..cc18ea8 100644 --- a/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts +++ b/apps/tauri/src-tauri/gen/android/buildSrc/build.gradle.kts @@ -18,5 +18,6 @@ repositories { dependencies { compileOnly(gradleApi()) - implementation("com.android.tools.build:gradle:8.11.0") + implementation("com.android.tools.build:gradle:9.3.1") } + diff --git a/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt b/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt index e2be2d1..a7e39eb 100644 --- a/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt +++ b/apps/tauri/src-tauri/gen/android/buildSrc/src/main/java/net/tensamin/client/kotlin/BuildTask.kt @@ -5,12 +5,8 @@ import org.gradle.api.GradleException import org.gradle.api.logging.LogLevel import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction -import org.gradle.process.ExecOperations -import javax.inject.Inject -open class BuildTask @Inject constructor( - private val execOperations: ExecOperations, -) : DefaultTask() { +open class BuildTask : DefaultTask() { @Input var rootDirRel: String? = null @Input @@ -54,7 +50,7 @@ open class BuildTask @Inject constructor( val release = release ?: throw GradleException("release cannot be null") val args = listOf("tauri", "android", "android-studio-script"); - execOperations.exec { + project.exec { workingDir(File(project.projectDir, rootDirRel)) executable(executable) args(args) @@ -69,4 +65,4 @@ open class BuildTask @Inject constructor( args(listOf("--target", target)) }.assertNormalExitValue() } -} +} \ No newline at end of file diff --git a/apps/tauri/src-tauri/src/accessibility_backend.rs b/apps/tauri/src-tauri/src/accessibility_backend.rs deleted file mode 100644 index 692b42e..0000000 --- a/apps/tauri/src-tauri/src/accessibility_backend.rs +++ /dev/null @@ -1,135 +0,0 @@ -#[cfg(not(target_os = "android"))] -const DEFAULT_INITIAL_SCALE: i32 = 290; -const MIN_INITIAL_SCALE: i32 = 210; -const MAX_INITIAL_SCALE: i32 = 500; - -#[tauri::command] -pub fn accessibility_get_initial_scale() -> Result { - android_get_initial_scale() -} - -#[tauri::command] -pub fn accessibility_set_initial_scale(initial_scale: i32) -> Result<(), String> { - if !(MIN_INITIAL_SCALE..=MAX_INITIAL_SCALE).contains(&initial_scale) { - return Err(format!( - "Initial scale must be between {MIN_INITIAL_SCALE} and {MAX_INITIAL_SCALE}" - )); - } - - android_set_initial_scale(initial_scale) -} - -#[cfg(not(target_os = "android"))] -fn android_get_initial_scale() -> Result { - Ok(DEFAULT_INITIAL_SCALE) -} - -#[cfg(not(target_os = "android"))] -fn android_set_initial_scale(_: i32) -> Result<(), String> { - Ok(()) -} - -#[cfg(target_os = "android")] -mod android { - use std::sync::OnceLock; - - use jni::{ - jni_sig, jni_str, - objects::{Global, JClass, JObject, JValue}, - Env, EnvUnowned, JavaVM, - }; - - struct Host { - vm: JavaVM, - context: Global>, - bridge: Global>, - } - - static HOST: OnceLock = OnceLock::new(); - - fn attach(env: &mut Env, context: JObject) -> Result<(), String> { - if HOST.get().is_some() { - return Ok(()); - } - - let class = env - .find_class(jni_str!("net/tensamin/client/NativeAccessibilityBridge")) - .map_err(|error| error.to_string())?; - let bridge = env - .get_static_field( - class, - jni_str!("INSTANCE"), - jni_sig!("Lnet/tensamin/client/NativeAccessibilityBridge;"), - ) - .and_then(|value| value.l()) - .map_err(|error| error.to_string())?; - - HOST.set(Host { - vm: env.get_java_vm().map_err(|error| error.to_string())?, - context: env - .new_global_ref(context) - .map_err(|error| error.to_string())?, - bridge: env - .new_global_ref(bridge) - .map_err(|error| error.to_string())?, - }) - .map_err(|_| "Android accessibility host is already attached".to_string()) - } - - fn with_env(call: impl FnOnce(&mut Env, &Host) -> Result) -> Result { - let host = HOST - .get() - .ok_or("Android accessibility host is not attached")?; - host.vm - .attach_current_thread(|env| Ok::<_, jni::errors::Error>(call(env, host))) - .map_err(|error| error.to_string())? - } - - pub fn get_initial_scale() -> Result { - with_env(|env, host| { - env.call_method( - host.bridge.as_obj(), - jni_str!("getInitialScale"), - jni_sig!("(Landroid/content/Context;)I"), - &[JValue::Object(host.context.as_obj())], - ) - .and_then(|value| value.i()) - .map_err(|error| error.to_string()) - }) - } - - pub fn set_initial_scale(initial_scale: i32) -> Result<(), String> { - with_env(|env, host| { - env.call_method( - host.bridge.as_obj(), - jni_str!("setInitialScale"), - jni_sig!("(Landroid/content/Context;I)V"), - &[ - JValue::Object(host.context.as_obj()), - JValue::Int(initial_scale), - ], - ) - .map_err(|error| error.to_string())?; - Ok(()) - }) - } - - #[no_mangle] - pub extern "system" fn Java_net_tensamin_client_NativeAccessibilityBridge_nativeAttach< - 'caller, - >( - mut env: EnvUnowned<'caller>, - _class: JClass, - context: JObject<'caller>, - ) { - let _ = env.with_env(|env| { - let _ = attach(env, context); - Ok::<_, jni::errors::Error>(()) - }); - } -} - -#[cfg(target_os = "android")] -use android::{ - get_initial_scale as android_get_initial_scale, set_initial_scale as android_set_initial_scale, -}; diff --git a/apps/tauri/src-tauri/src/lib.rs b/apps/tauri/src-tauri/src/lib.rs index e81a830..8131b57 100644 --- a/apps/tauri/src-tauri/src/lib.rs +++ b/apps/tauri/src-tauri/src/lib.rs @@ -1,4 +1,3 @@ -mod accessibility_backend; mod mtp_backend; #[cfg_attr(mobile, tauri::mobile_entry_point)] @@ -20,8 +19,6 @@ pub fn run() { let app = builder .invoke_handler(tauri::generate_handler![ - accessibility_backend::accessibility_get_initial_scale, - accessibility_backend::accessibility_set_initial_scale, mtp_backend::mtp_request, mtp_backend::mtp_status, mtp_backend::mtp_store_credentials, diff --git a/apps/tauri/src-tauri/src/mtp_backend.rs b/apps/tauri/src-tauri/src/mtp_backend.rs index b343337..09fa249 100644 --- a/apps/tauri/src-tauri/src/mtp_backend.rs +++ b/apps/tauri/src-tauri/src/mtp_backend.rs @@ -372,13 +372,9 @@ async fn connect(config: &MtpConfig) -> Result<(MTPConnection, Value), String> { .with_max_missed_pings(3); #[cfg(target_os = "android")] let client_config = client_config.with_pinned_pem(android_root_certificates().clone()); - let connection = tokio::time::timeout( - Duration::from_secs(30), - MTPClient::auth_connect(client_config, &keyring, &host_key), - ) - .await - .map_err(|_| "transport authentication timed out".to_string())? - .map_err(|error| format!("transport authentication failed: {error}"))?; + let connection = MTPClient::auth_connect(client_config, &keyring, &host_key) + .await + .map_err(|error| format!("transport authentication failed: {error}"))?; manager().log(2, "Native MTP authentication completed", None); let connected = CommunicationValue::new(CommunicationType::ClientConnected) @@ -389,13 +385,10 @@ async fn connect(config: &MtpConfig) -> Result<(MTPConnection, Value), String> { .add_typed_default(DataType::VersionNumber, DataValue::UnsignedNumber(0)) .add_typed_default(DataType::CacheValid, DataValue::BoolFalse) .add_typed_default(DataType::CacheSchemaVersion, DataValue::UnsignedNumber(0)); - let state = tokio::time::timeout( - Duration::from_secs(30), - connection.request(&connected, None), - ) - .await - .map_err(|_| "initial state synchronization timed out".to_string())? - .map_err(|error| format!("initial state synchronization failed: {error}"))?; + let state = connection + .request(&connected, None) + .await + .map_err(|error| format!("initial state synchronization failed: {error}"))?; if !state.is_type(CommunicationType::ClientStateSync) { return Err(format!( "expected ClientStateSync, received {}", @@ -413,9 +406,9 @@ async fn connect(config: &MtpConfig) -> Result<(MTPConnection, Value), String> { let ack = CommunicationValue::new(CommunicationType::ClientStateAck) .add_typed_default(DataType::SessionId, number_to_data(session_id)) .add_typed_default(DataType::VersionNumber, number_to_data(version)); - let response = tokio::time::timeout(Duration::from_secs(30), connection.request(&ack, None)) + let response = connection + .request(&ack, None) .await - .map_err(|_| "state acknowledgement timed out".to_string())? .map_err(|error| format!("state acknowledgement failed: {error}"))?; if response .get_type_name() @@ -440,19 +433,7 @@ async fn resolve_endpoint(config: &MtpConfig) -> Result<(String, String), String public_key: String, } let root = config.omega_url.trim_end_matches('/'); - let client = reqwest::Client::builder() - .connect_timeout(Duration::from_secs(10)) - .timeout(Duration::from_secs(20)); - #[cfg(target_os = "android")] - let client = client.tls_certs_only( - reqwest::Certificate::from_pem_bundle(android_root_certificates()) - .map_err(|error| format!("invalid bundled root certificates: {error}"))?, - ); - let response = client - .build() - .map_err(|error| error.to_string())? - .get(format!("{root}/api/get/omikron/{}", config.user_id)) - .send() + let response = reqwest::get(format!("{root}/api/get/omikron/{}", config.user_id)) .await .map_err(|error| error.to_string())?; if !response.status().is_success() { diff --git a/apps/web/index.html b/apps/web/index.html index 01335eb..eef61d9 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -2,7 +2,7 @@ - + Tensamin diff --git a/apps/web/package.json b/apps/web/package.json index 15a4c00..107c6f7 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,7 +6,7 @@ "scripts": { "format": "pnpm exec prettier --write .", "lint": "eslint src", - "dev": "vite", + "dev": "vite --port 3000 --host 0.0.0.0", "test": "vitest run --passWithNoTests", "build": "pnpm run test && tsc -b && vite build", "preview": "cd dist && nix-shell -p python3 --run 'python3 -m http.server 3000' && cd .." diff --git a/apps/web/src/components/screens/login/form.tsx b/apps/web/src/components/screens/login/form.tsx index 72db8f7..0bbb850 100644 --- a/apps/web/src/components/screens/login/form.tsx +++ b/apps/web/src/components/screens/login/form.tsx @@ -76,6 +76,11 @@ function parseTuFileContent(rawFileContent: string): { throw new Error("Invalid file"); } + console.log({ + domain, + userId, + }); + return { userId, privateKey, domain }; } diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 5e1d120..464f57b 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -70,9 +70,9 @@ export default defineConfig({ ], }, server: { - port: 3000, + port: 5173, strictPort: true, - host: "0.0.0.0", + host: host || "0.0.0.0", hmr: host ? { protocol: "ws", diff --git a/packages/mtp/src/context.tsx b/packages/mtp/src/context.tsx index af06ee0..a86fa57 100644 --- a/packages/mtp/src/context.tsx +++ b/packages/mtp/src/context.tsx @@ -777,49 +777,40 @@ function TauriProvider(props: { let disposed = false; let unlisten: UnlistenFn | undefined; void (async () => { - try { - const nextUnlisten = await listen< - | { kind: "state"; snapshot: NativeSnapshot } - | { kind: "message"; generation: number; message: unknown } - | { - kind: "log"; - level: number; - message: string; - details?: unknown; - } - >("mtp://event", ({ payload }) => { - if (disposed) return; - if (payload.kind === "state") { - applySnapshot(payload.snapshot); - return; + unlisten = await listen< + | { kind: "state"; snapshot: NativeSnapshot } + | { kind: "message"; generation: number; message: unknown } + | { + kind: "log"; + level: number; + message: string; + details?: unknown; } - if (payload.kind === "message") { - if (payload.generation === generationRef.current) { - dispatchMessage(payload.message); - } - return; + >("mtp://event", ({ payload }) => { + if (disposed) return; + if (payload.kind === "state") { + applySnapshot(payload.snapshot); + return; + } + if (payload.kind === "message") { + if (payload.generation === generationRef.current) { + dispatchMessage(payload.message); } - log( - payload.level, - "android", - "orange", - payload.message, - payload.details, - ); - }); - if (disposed) nextUnlisten(); - else unlisten = nextUnlisten; - } catch (error) { - log(0, "mtp", "red", "Failed to subscribe to native MTP events", error); - } - - try { - const current = await invoke("mtp_status"); - if (!disposed) applySnapshot(current); - } catch (error) { - log(0, "mtp", "red", "Failed to load native MTP status", error); - } - })(); + return; + } + log( + payload.level, + "android", + "orange", + payload.message, + payload.details, + ); + }); + const current = await invoke("mtp_status"); + if (!disposed) applySnapshot(current); + })().catch((error) => { + log(0, "mtp", "red", "Failed to initialize native MTP bridge", error); + }); return () => { disposed = true; unlisten?.(); diff --git a/packages/settings/package.json b/packages/settings/package.json index d281b7f..f3833a9 100644 --- a/packages/settings/package.json +++ b/packages/settings/package.json @@ -14,7 +14,6 @@ "dependencies": { "@methanium/ui": "*", "@tanstack/react-router": "^1.170.21", - "@tauri-apps/api": "^2.11.1", "@tensamin/cache": "workspace:*", "@tensamin/hotkeys": "workspace:*", "@tensamin/mtp": "workspace:*", diff --git a/packages/settings/src/manifest.ts b/packages/settings/src/manifest.ts index 41fe14a..2daf8ff 100644 --- a/packages/settings/src/manifest.ts +++ b/packages/settings/src/manifest.ts @@ -1,4 +1,3 @@ -import Accessibility from "./pages/accessibility"; import Cache from "./pages/cache"; import Call from "./pages/call"; import Chat from "./pages/chat"; @@ -27,12 +26,6 @@ export const settingsPages = [ { category: "general", path: "call", label: "Call", component: Call }, { category: "application", path: "cache", label: "Cache", component: Cache }, { category: "application", path: "theme", label: "Theme", component: Theme }, - { - category: "application", - path: "accessibility", - label: "Accessibility", - component: Accessibility, - }, { category: "application", path: "hotkeys", diff --git a/packages/settings/src/pages/accessibility.tsx b/packages/settings/src/pages/accessibility.tsx deleted file mode 100644 index 026c3b1..0000000 --- a/packages/settings/src/pages/accessibility.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Button, Label, Slider } from "@methanium/ui"; -import { invoke, isTauri } from "@tauri-apps/api/core"; -import { RotateCcw } from "lucide-react"; -import { useEffect, useState } from "react"; - -const DEFAULT_INITIAL_SCALE = 290; -const MIN_INITIAL_SCALE = 210; -const isAndroid = isTauri() && /Android/.test(navigator.userAgent); - -export default function Page() { - const [initialScale, setInitialScale] = useState(DEFAULT_INITIAL_SCALE); - const [loading, setLoading] = useState(isAndroid); - - useEffect(() => { - if (!isAndroid) return; - - let active = true; - void invoke("accessibility_get_initial_scale") - .then((scale) => { - if (active) setInitialScale(scale); - }) - .catch((error: unknown) => { - console.error("Failed to load the Android initial scale", error); - }) - .finally(() => { - if (active) setLoading(false); - }); - - return () => { - active = false; - }; - }, []); - - if (!isAndroid) return null; - - function updateInitialScale(nextScale: number) { - setInitialScale(nextScale); - void invoke("accessibility_set_initial_scale", { - initialScale: nextScale, - }).catch((error: unknown) => { - console.error("Failed to update the Android initial scale", error); - }); - } - - return ( -
-
- - - {initialScale}% - -
-
- { - const nextScale = Array.isArray(value) ? value[0] : value; - if (nextScale !== undefined) updateInitialScale(nextScale); - }} - /> - -
-
- ); -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 38033b2..bbfb6de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -509,9 +509,6 @@ importers: '@tanstack/react-router': specifier: ^1.170.21 version: 1.170.23(react-dom@19.2.8(react@19.2.8))(react@19.2.8) - '@tauri-apps/api': - specifier: ^2.11.1 - version: 2.11.1 '@tensamin/cache': specifier: workspace:* version: link:../cache