(qol): add delete mobile app script
All checks were successful
/ deploy (push) Successful in 14m53s

(qol): updated todos
(fix): small px-2 that shouldn't be there
(feat): turn focus reconnect into a continuous reconnect
This commit is contained in:
Alois 2026-05-10 00:08:54 +02:00
commit 30722b6168
14 changed files with 93 additions and 9 deletions

View file

@ -4573,6 +4573,18 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-plugin-app-events"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e625f35abcfc422c7c4af8b348d2069cdf387a39c12429fdce570137d02f069"
dependencies = [
"serde",
"tauri",
"tauri-plugin",
"thiserror 1.0.69",
]
[[package]]
name = "tauri-plugin-barcode-scanner"
version = "2.4.4"
@ -4834,6 +4846,7 @@ dependencies = [
"serde_json",
"tauri",
"tauri-build 2.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"tauri-plugin-app-events",
"tauri-plugin-barcode-scanner",
"tauri-plugin-deep-link",
"tauri-plugin-opener",

View file

@ -50,6 +50,7 @@ default-features = false
[target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies]
tauri-plugin-barcode-scanner = "2"
tauri-plugin-app-events = "0.2"
[patch.crates-io.tauri]
git = "https://github.com/tauri-apps/tauri"

View file

@ -9,6 +9,7 @@
],
"permissions": [
"deep-link:default",
"app-events:default",
"barcode-scanner:default",
"barcode-scanner:allow-scan",
"barcode-scanner:allow-cancel"

View file

@ -1,3 +1,5 @@
import com.android.build.gradle.LibraryExtension
buildscript {
repositories {
google()
@ -16,7 +18,16 @@ allprojects {
}
}
subprojects {
afterEvaluate {
plugins.withId("com.android.library") {
extensions.configure<LibraryExtension>("android") {
compileSdk = 36
}
}
}
}
tasks.register("clean").configure {
delete("build")
}

View file

@ -206,6 +206,9 @@ pub fn run() {
#[cfg(any(target_os = "ios", target_os = "android"))]
let builder = builder.plugin(tauri_plugin_barcode_scanner::init());
#[cfg(any(target_os = "ios", target_os = "android"))]
let builder = builder.plugin(tauri_plugin_app_events::init());
if let Err(error) = builder
.setup(|_app| {
#[cfg(any(target_os = "linux", windows))]

View file

@ -42,6 +42,7 @@
"tailwind-merge": "^3.5.0",
"tailwind-scrollbar-hide": "^4.0.0",
"tailwindcss": "^4.2.4",
"tauri-plugin-app-events-api": "^0.2.0",
"tw-animate-css": "^1.4.0",
"zod": "^4.3.6"
},

View file

@ -76,6 +76,7 @@
"tailwind-merge": "^3.5.0",
"tailwind-scrollbar-hide": "^4.0.0",
"tailwindcss": "^4.2.4",
"tauri-plugin-app-events-api": "^0.2.0",
"tw-animate-css": "^1.4.0",
"zod": "^4.3.6",
},
@ -228,6 +229,7 @@
"version": "0.0.0",
"dependencies": {
"@tanstack/react-router": "^1.0.0",
"@tauri-apps/api": "^2",
"@tensamin/crypto": "workspace:*",
"@tensamin/shared": "workspace:*",
"@tensamin/storage": "workspace:*",
@ -235,6 +237,7 @@
"@tensamin/ui": "*",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"tauri-plugin-app-events-api": "^0.2.0",
"zod": "^4.3.6",
},
"devDependencies": {
@ -1497,6 +1500,8 @@
"tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="],
"tauri-plugin-app-events-api": ["tauri-plugin-app-events-api@0.2.0", "", { "dependencies": { "@tauri-apps/api": "^2.0.3" } }, "sha512-CnlAeucWhT+Rgx6CCsqUpq2D3pqgx0fhjSPKomH7O2t1rGVu5kGLMkYvaCX6gqVTUYpIWX5BLV7LGY2DRri0QA=="],
"tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
"tinyexec": ["tinyexec@1.1.2", "", {}, "sha512-dAqSqE/RabpBKI8+h26GfLq6Vb3JVXs30XYQjdMjaj/c2tS8IYYMbIzP599KtRj7c57/wYApb3QjgRgXmrCukA=="],

View file

@ -22,7 +22,8 @@
"dev:mobile": "cd apps/tauri && bun dev:mobile",
"build:mobile": "cd apps/tauri && bun run build:mobile",
"dev:desktop": "cd apps/tauri && bun dev:desktop",
"build:desktop": "cd apps/tauri && bun run build:desktop"
"build:desktop": "cd apps/tauri && bun run build:desktop",
"delete:mobile": "cd apps/tauri && nix develop --command adb uninstall net.tensamin.client"
},
"devDependencies": {
"@eslint/js": "^10.0.1",

View file

@ -431,7 +431,7 @@ export default function Screen() {
}
return (
<div className="relative flex h-full min-h-0 w-full flex-col overflow-hidden px-2">
<div className="relative flex h-full min-h-0 w-full flex-col overflow-hidden">
<div
ref={scrollRef}
id="chat_container"

View file

@ -0,0 +1 @@
- Improve the Input box

View file

@ -1 +1,2 @@
- Add `notifications: number` to contacts
- Store private key in a device bound session

1
packages/tauth/todo.md Normal file
View file

@ -0,0 +1 @@
- Finish TAuth SDK

View file

@ -18,8 +18,10 @@
"@tensamin/storage": "workspace:*",
"@tensamin/shared": "workspace:*",
"@tensamin/ui": "*",
"@tauri-apps/api": "^2",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"tauri-plugin-app-events-api": "^0.2.0",
"zod": "^4.3.6"
},
"devDependencies": {

View file

@ -16,6 +16,8 @@ import {
READY_STATE,
type BoundSendFn,
} from "@tensamin/ttp-core";
import { isTauri } from "@tauri-apps/api/core";
import { onResume } from "tauri-plugin-app-events-api";
import type { PushHandler } from "@tensamin/ttp-core";
import {
PING_INTERVAL,
@ -141,6 +143,10 @@ function getProtocolErrorDetails(error: unknown) {
};
}
function isTauriMobile() {
return isTauri() && /Android|iPhone|iPad|iPod/.test(navigator.userAgent);
}
type ContextType = {
send: BoundSendFn<Schemas>;
subscribePush: (handler: PushHandler) => () => void;
@ -186,7 +192,6 @@ export function Provider(props: {
typeof createTransportClient<Schemas>
> | null>(null);
const identificationStartedRef = useRef(false);
const reconnectExhaustedRef = useRef(false);
/**
* Sends typed protocol messages through the active transport client.
@ -266,6 +271,8 @@ export function Provider(props: {
let reconnectResetTimer: ReturnType<typeof setTimeout> | null = null;
let reconnectScheduled = false;
let disposed = false;
let resumeListenerRegistered = false;
let currentReadyState: number = READY_STATE.CLOSED;
/**
* Clears any scheduled reconnect timeout and resets scheduling flags.
@ -316,14 +323,12 @@ export function Provider(props: {
return;
}
if (reconnectExhaustedRef.current || attempts >= RECONNECT_TRIES) {
reconnectExhaustedRef.current = true;
if (attempts >= RECONNECT_TRIES) {
setError("Connection Failed");
setErrorDescription(
"Unable to connect to the server after multiple attempts. Please check your internet connection or try again later.",
);
log(0, "ttp", "red", "Reconnection attempts exhausted", reason);
void transportClient?.close("reconnect-exhausted");
return;
}
@ -340,12 +345,12 @@ export function Provider(props: {
? createTransportClient(schemas, {
url: TRANSPORT_URL,
onReadyStateChange: (state) => {
currentReadyState = state;
setReadyState(state);
if (state === READY_STATE.OPEN) {
clearReconnectTimer();
scheduleReconnectReset();
reconnectExhaustedRef.current = false;
identificationStartedRef.current = false;
setConnected(true);
setIdentified(false);
@ -383,7 +388,7 @@ export function Provider(props: {
* @returns Promise that resolves after one connection attempt.
*/
async function connect() {
if (disposed || reconnectExhaustedRef.current) {
if (disposed) {
return;
}
@ -399,18 +404,56 @@ export function Provider(props: {
}
}
/**
* Starts a reconnect after resume only when the transport is disconnected.
* @returns Promise that resolves after any needed resume reconnect starts.
*/
async function reconnectAfterResume() {
if (disposed || !transportClient) {
return;
}
if (
currentReadyState === READY_STATE.OPEN ||
currentReadyState === READY_STATE.CONNECTING
) {
return;
}
clearReconnectTimer();
clearReconnectResetTimer();
attempts = 0;
reconnectScheduled = false;
setError("");
setErrorDescription("");
await connect();
}
void connect();
if (!props.blockConnection && isTauriMobile()) {
resumeListenerRegistered = true;
onResume(() => {
void reconnectAfterResume();
});
}
return () => {
disposed = true;
clearReconnectTimer();
clearReconnectResetTimer();
if (resumeListenerRegistered) {
onResume();
}
if (clientRef.current === transportClient) {
clientRef.current = null;
}
void transportClient?.close("context-dispose");
currentReadyState = READY_STATE.CLOSED;
setReadyState(READY_STATE.CLOSED);
setConnected(false);
setIdentified(false);