Merge branch 'dev' of ssh://git.methanium.net/Tensamin/Client into dev

This commit is contained in:
Alex 2026-08-07 23:09:03 +02:00
commit c182f2e9ac
Signed by: alex
SSH key fingerprint: SHA256:D1+Ub8o0v4K5y1JNivW8IxEOelqLSvPmUzBbDIoZkRQ
27 changed files with 1950 additions and 793 deletions

View file

@ -33,7 +33,7 @@
"@types/node": "^25.9.1",
"electron": "^39.2.7",
"electron-builder": "^26.0.12",
"esbuild": "^0.25.11",
"esbuild": "^0.28.0",
"typescript": "~6.0.3"
},
"build": {

View file

@ -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"
@ -1128,11 +1162,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",
]
@ -1976,7 +2025,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]]
@ -2273,7 +2332,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]]
@ -2636,6 +2704,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"
@ -4234,7 +4313,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",
@ -4863,7 +4961,7 @@ dependencies = [
"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",
@ -4898,6 +4996,26 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-build"
version = "2.6.3"
source = "git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390#c0bd0d5a61eedba5c4783add24455c5028c6f390"
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=c0bd0d5a61eedba5c4783add24455c5028c6f390)",
"tauri-winres",
"walkdir",
]
[[package]]
name = "tauri-codegen"
version = "2.6.3"
@ -5106,11 +5224,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",
@ -5142,11 +5260,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",
@ -5170,6 +5288,42 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-utils"
version = "2.9.3"
source = "git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390#c0bd0d5a61eedba5c4783add24455c5028c6f390"
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"
@ -5216,17 +5370,17 @@ dependencies = [
[[package]]
name = "tensamin"
version = "0.0.0"
version = "0.0.11"
dependencies = [
"base64 0.22.1",
"jni 0.21.1",
"jni 0.22.4",
"mtp",
"mtp-transport",
"reqwest 0.12.28",
"serde",
"serde_json",
"tauri",
"tauri-build",
"tauri-build 2.6.3 (git+https://github.com/tauri-apps/tauri?rev=c0bd0d5a61eedba5c4783add24455c5028c6f390)",
"tauri-plugin-barcode-scanner",
"tauri-plugin-deep-link",
"tauri-plugin-log",
@ -6451,7 +6605,7 @@ dependencies = [
"cookie",
"crossbeam-channel",
"dirs",
"dom_query",
"dom_query 0.27.0",
"dpi",
"dunce",
"gdkx11",

View file

@ -15,7 +15,7 @@ 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 = "c0bd0d5a61eedba5c4783add24455c5028c6f390", features = [] }
[dependencies]
tauri-plugin-opener = "2"
@ -37,7 +37,7 @@ features = []
default-features = true
[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21"
jni = "0.22"
[target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies]
tauri-plugin-barcode-scanner = "2"

View file

@ -74,13 +74,13 @@ rust {
}
dependencies {
implementation("androidx.webkit:webkit:1.14.0")
implementation("androidx.webkit:webkit:1.16.0")
implementation("androidx.appcompat:appcompat:1.7.1")
implementation("androidx.activity:activity-ktx:1.10.1")
implementation("com.google.android.material:material:1.12.0")
implementation("androidx.activity:activity-ktx:1.13.0")
implementation("com.google.android.material:material:1.14.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.4")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
androidTestImplementation("androidx.test.ext:junit:1.3.0")
androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
}
apply(from = "tauri.build.gradle.kts")
apply(from = "tauri.build.gradle.kts")

View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

View file

@ -8,15 +8,30 @@ import android.app.Service
import android.content.Context
import android.content.Intent
import android.content.pm.ServiceInfo
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import android.os.IBinder
import androidx.core.app.NotificationCompat
class MtpForegroundService : Service() {
private var started = false
private val networkCallback = object : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) = refreshNotification()
override fun onLost(network: Network) = refreshNotification()
override fun onCapabilitiesChanged(network: Network, capabilities: NetworkCapabilities) =
refreshNotification()
}
override fun onBind(intent: Intent?): IBinder? = null
override fun onCreate() {
super.onCreate()
getSystemService(ConnectivityManager::class.java)
.registerDefaultNetworkCallback(networkCallback)
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
if (intent?.action == ACTION_STOP) {
MtpSecureStore.setEnabled(this, false)
@ -28,7 +43,8 @@ class MtpForegroundService : Service() {
if (started) return START_STICKY
createChannel(this)
val notification = buildNotification(this, "Connecting")
connectionStatus = "Connecting"
val notification = buildNotification(this, displayedStatus(this))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
startForeground(
NOTIFICATION_ID,
@ -65,20 +81,37 @@ class MtpForegroundService : Service() {
}
override fun onDestroy() {
getSystemService(ConnectivityManager::class.java).unregisterNetworkCallback(networkCallback)
if (!MtpSecureStore.isEnabled(this)) NativeMtpBridge.nativeStop()
super.onDestroy()
}
private fun refreshNotification() {
updateNotification(this, connectionStatus)
}
companion object {
private const val CHANNEL_ID = "tensamin-connection"
private const val NOTIFICATION_ID = 2201
private const val ACTION_STOP = "net.tensamin.client.STOP_MTP"
@Volatile private var connectionStatus = "Connecting"
fun updateNotification(context: Context, status: String) {
if (!MtpSecureStore.isEnabled(context)) return
connectionStatus = status
createChannel(context)
context.getSystemService(NotificationManager::class.java)
.notify(NOTIFICATION_ID, buildNotification(context, status))
.notify(NOTIFICATION_ID, buildNotification(context, displayedStatus(context)))
}
private fun displayedStatus(context: Context): String {
val connectivity = context.getSystemService(ConnectivityManager::class.java)
val network = connectivity.activeNetwork ?: return "No network"
val capabilities = connectivity.getNetworkCapabilities(network) ?: return "No network"
return if (
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) &&
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
) connectionStatus else "No network"
}
private fun createChannel(context: Context) {

View file

@ -6,8 +6,8 @@ buildscript {
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:8.11.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.25")
classpath("com.android.tools.build:gradle:8.13.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:2.1.20")
}
}

View file

@ -18,6 +18,6 @@ repositories {
dependencies {
compileOnly(gradleApi())
implementation("com.android.tools.build:gradle:8.11.0")
implementation("com.android.tools.build:gradle:8.13.2")
}

View file

@ -108,10 +108,10 @@
"react-remove-scroll-bar": "^2.3.7",
"react-resizable-panels": "^4.11.2",
"react-style-singleton": "^2.2.3",
"recharts": "3.8.1",
"recharts": "3.10.1",
"redux": "^5.0.0",
"redux-thunk": "^3.1.0",
"reselect": "5.1.1",
"reselect": "5.2.0",
"scheduler": "^0.27.0",
"seroval": "^1.5.4",
"seroval-plugins": "^1.5.4",
@ -136,7 +136,7 @@
"@types/react": "^19.2.2",
"@types/react-dom": "^19.2.2",
"@vitejs/plugin-react": "^6.0.1",
"esbuild": "^0.25.11",
"esbuild": "^0.28.0",
"eslint": "^10.0.3",
"globals": "^17.4.0",
"typescript": "~6.0.3",