From 1e90171ee9347408642c6d8efd85cfd4e7e3352f Mon Sep 17 00:00:00 2001 From: Alois Date: Tue, 9 Jun 2026 18:44:30 +0200 Subject: [PATCH] (feat): add embeds --- apps/tauri/package.json | 1 + apps/tauri/src-tauri/Cargo.lock | 290 ++++++++++++++++++ apps/tauri/src-tauri/Cargo.toml | 1 + .../tauri/src-tauri/capabilities/default.json | 3 +- apps/tauri/src-tauri/capabilities/mobile.json | 3 +- apps/tauri/src-tauri/src/lib.rs | 43 ++- apps/tauri/src-tauri/src/main.rs | 5 +- apps/web/src/features/settings/components.tsx | 142 ++++++++- apps/web/src/routes/settings/chat.tsx | 3 +- bun.lock | 3 + packages/chat/src/components/media.tsx | 42 +++ packages/chat/src/components/message.tsx | 20 +- packages/shared/src/data.ts | 2 + 13 files changed, 549 insertions(+), 9 deletions(-) create mode 100644 packages/chat/src/components/media.tsx diff --git a/apps/tauri/package.json b/apps/tauri/package.json index 80b8b3a..3835cd1 100644 --- a/apps/tauri/package.json +++ b/apps/tauri/package.json @@ -30,6 +30,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-barcode-scanner": "~2", "@tauri-apps/plugin-deep-link": "~2", + "@tauri-apps/plugin-log": "~2", "@tauri-apps/plugin-notification": "~2", "@tensamin/shared": "workspace:*", "@tensamin/ui": "*", diff --git a/apps/tauri/src-tauri/Cargo.lock b/apps/tauri/src-tauri/Cargo.lock index 386b3fc..ab48eea 100644 --- a/apps/tauri/src-tauri/Cargo.lock +++ b/apps/tauri/src-tauri/Cargo.lock @@ -8,6 +8,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.17", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -32,6 +43,23 @@ dependencies = [ "alloc-no-stdlib", ] +[[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.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbb4e440d04be07da1f1bf44fb4495ebd58669372fe0cffa6e48595ac5bd88a3" +dependencies = [ + "android_log-sys", + "env_filter", + "log", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -47,6 +75,12 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "asn1-rs" version = "0.7.2" @@ -326,6 +360,18 @@ dependencies = [ "serde_core", ] +[[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-buffer" version = "0.10.4" @@ -366,6 +412,30 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate 3.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "brotli" version = "8.0.3" @@ -402,6 +472,40 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byte-unit" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6d47a4e2961fb8721bcfc54feae6455f2f64e7054f9bc67e875f0e77f4c58d" +dependencies = [ + "rust_decimal", + "schemars 1.2.1", + "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.25.0" @@ -1069,6 +1173,16 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "env_filter" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +dependencies = [ + "log", + "regex", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1132,6 +1246,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" @@ -1218,6 +1341,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -1604,6 +1733,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" @@ -2186,6 +2318,9 @@ name = "log" version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a" +dependencies = [ + "value-bag", +] [[package]] name = "lru-slab" @@ -2395,6 +2530,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "objc2" version = "0.6.4" @@ -2986,6 +3130,26 @@ dependencies = [ "unicode-ident", ] +[[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 = "quick-xml" version = "0.37.5" @@ -3081,6 +3245,12 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.8.6" @@ -3228,6 +3398,15 @@ version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +[[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.13.4" @@ -3276,6 +3455,35 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rkyv" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "rust-ini" version = "0.21.3" @@ -3286,6 +3494,23 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust_decimal" +version = "1.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.6", + "rkyv", + "serde", + "serde_json", + "wasm-bindgen", +] + [[package]] name = "rustc-hash" version = "2.1.2" @@ -3469,6 +3694,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 = "security-framework" version = "3.7.0" @@ -3724,6 +3955,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "siphasher" version = "1.0.3" @@ -3878,6 +4115,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] @@ -3976,6 +4214,12 @@ dependencies = [ "syn 2.0.117", ] +[[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" @@ -4175,6 +4419,28 @@ dependencies = [ "windows-result 0.3.4", ] +[[package]] +name = "tauri-plugin-log" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7545bd67f070a4500432c826e2e0682146a1d6712aee22a2786490156b574d93" +dependencies = [ + "android_logger", + "byte-unit", + "fern", + "log", + "objc2", + "objc2-foundation", + "serde", + "serde_json", + "serde_repr", + "swift-rs", + "tauri", + "tauri-plugin", + "thiserror 2.0.18", + "time", +] + [[package]] name = "tauri-plugin-notification" version = "2.3.3" @@ -4394,6 +4660,7 @@ dependencies = [ "tauri-plugin-app-events", "tauri-plugin-barcode-scanner", "tauri-plugin-deep-link", + "tauri-plugin-log", "tauri-plugin-notification", "tauri-plugin-opener", "ttp-core", @@ -4448,7 +4715,9 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde_core", "time-core", @@ -4922,6 +5191,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8-width" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -4940,6 +5215,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "value-bag" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ba6f5989077681266825251a52748b8c1d8a4ad098cc37e440103d0ea717fc0" + [[package]] name = "version-compare" version = "0.2.1" @@ -5888,6 +6169,15 @@ dependencies = [ "url", ] +[[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/apps/tauri/src-tauri/Cargo.toml b/apps/tauri/src-tauri/Cargo.toml index ba011c1..5bc6890 100644 --- a/apps/tauri/src-tauri/Cargo.toml +++ b/apps/tauri/src-tauri/Cargo.toml @@ -25,6 +25,7 @@ tauri-plugin-deep-link = "2" tauri-plugin-notification = "2" ttp-core = { git = "https://git.methanium.net/tensamin/ttp.git", package = "ttp-core" } ttp-native = { git = "https://git.methanium.net/tensamin/ttp.git", package = "ttp-native" } +tauri-plugin-log = "2" [target.'cfg(target_os = "android")'.dependencies.tauri] version = "2" diff --git a/apps/tauri/src-tauri/capabilities/default.json b/apps/tauri/src-tauri/capabilities/default.json index 02d2627..c82ae30 100644 --- a/apps/tauri/src-tauri/capabilities/default.json +++ b/apps/tauri/src-tauri/capabilities/default.json @@ -15,6 +15,7 @@ "core:window:allow-minimize", "core:event:default", "deep-link:default", - "notification:default" + "notification:default", + "log:default" ] } \ No newline at end of file diff --git a/apps/tauri/src-tauri/capabilities/mobile.json b/apps/tauri/src-tauri/capabilities/mobile.json index ceee8f7..9681447 100644 --- a/apps/tauri/src-tauri/capabilities/mobile.json +++ b/apps/tauri/src-tauri/capabilities/mobile.json @@ -13,6 +13,7 @@ "barcode-scanner:default", "barcode-scanner:allow-scan", "barcode-scanner:allow-cancel", - "notification:default" + "notification:default", + "log:default" ] } \ No newline at end of file diff --git a/apps/tauri/src-tauri/src/lib.rs b/apps/tauri/src-tauri/src/lib.rs index f01b2ad..b3e103f 100644 --- a/apps/tauri/src-tauri/src/lib.rs +++ b/apps/tauri/src-tauri/src/lib.rs @@ -1,6 +1,47 @@ +use tauri::{AppHandle, ipc::Channel}; +use serde::Serialize; + +#[derive(Clone, Serialize)] +#[serde(rename_all = "camelCase", rename_all_fields = "camelCase", tag = "event", content = "data")] +enum DownloadEvent<'a> { + Started { + url: &'a str, + download_id: usize, + content_length: usize, + }, + Progress { + download_id: usize, + chunk_length: usize, + }, + Finished { + download_id: usize, + }, +} + +#[tauri::command] +fn download(app: AppHandle, url: String, on_event: Channel) { + let content_length = 1000; + let download_id = 1; + + on_event.send(DownloadEvent::Started { + url: &url, + download_id, + content_length, + }).unwrap(); + + for chunk_length in [15, 150, 35, 500, 300] { + on_event.send(DownloadEvent::Progress { + download_id, + chunk_length, + }).unwrap(); + } + + on_event.send(DownloadEvent::Finished { download_id }).unwrap(); +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - let builder = tauri::Builder::default().plugin(tauri_plugin_notification::init()); + let builder = tauri::Builder::default().plugin(tauri_plugin_log::Builder::new().level(tauri_plugin_log::log::LevelFilter::Info).build()).plugin(tauri_plugin_notification::init()); let builder = builder .plugin(tauri_plugin_deep_link::init()) diff --git a/apps/tauri/src-tauri/src/main.rs b/apps/tauri/src-tauri/src/main.rs index a9346de..e78a26a 100644 --- a/apps/tauri/src-tauri/src/main.rs +++ b/apps/tauri/src-tauri/src/main.rs @@ -1,6 +1,9 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use lib::log; + fn main() { - mobile_lib::run() + mobile_lib::run(); + log("Test test 123") } diff --git a/apps/web/src/features/settings/components.tsx b/apps/web/src/features/settings/components.tsx index b9f2967..240eeaf 100644 --- a/apps/web/src/features/settings/components.tsx +++ b/apps/web/src/features/settings/components.tsx @@ -1,8 +1,17 @@ -import { Label } from "@tensamin/ui"; -import { Switch as UISwitch } from "@tensamin/ui"; +import { + Button, + Checkbox, + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuTrigger, + Input, + Label, + Switch as UISwitch, +} from "@tensamin/ui"; import { useEffect, useState } from "react"; -import type { Storage } from "@tensamin/shared/data"; +import { storageDefaults, type Storage } from "@tensamin/shared/data"; import { settingsStorageDefaults } from "@tensamin/shared/settings"; import { useStorage } from "@tensamin/storage/context"; @@ -10,6 +19,13 @@ type BooleanStorageKey = { [K in keyof Storage]: Storage[K] extends boolean ? K : never; }[keyof Storage]; +type ListStorageKey = { + [K in keyof Storage]: Storage[K] extends (string | number)[] ? K : never; +}[keyof Storage]; + +type ListStorageItem = + Storage[K] extends Array ? Item : never; + export function Switch({ label, id, @@ -38,3 +54,123 @@ export function Switch({ ); } + +export function List({ + label, + id, +}: { + label: React.ReactNode; + id: K; +}) { + const { save, load } = useStorage(); + const [items, setItems] = useState(storageDefaults[id]); + const [inputValue, setInputValue] = useState(""); + const [selectedItems, setSelectedItems] = useState>(new Set()); + + useEffect(() => { + load(id).then((value) => setItems(value)); + }, [id, load]); + + const persistItems = (nextItems: Storage[K]) => { + setItems(nextItems); + save(id, nextItems); + }; + + const toStorageItem = (value: string): ListStorageItem => { + const referenceItem = items[0] ?? storageDefaults[id][0]; + + if (typeof referenceItem === "number") { + return Number(value) as ListStorageItem; + } + + return value as ListStorageItem; + }; + + const addItem = () => { + const trimmedValue = inputValue.trim(); + if (!trimmedValue) return; + + const nextItem = toStorageItem(trimmedValue); + if (typeof nextItem === "number" && Number.isNaN(nextItem)) return; + + persistItems([...items, nextItem] as Storage[K]); + setInputValue(""); + }; + + const deleteItems = (indexes: Set) => { + const nextItems = items.filter((_, index) => !indexes.has(index)) as Storage[K]; + + setItems(nextItems); + setSelectedItems(new Set()); + save(id, nextItems); + }; + + return ( +
+ +
+
+ setInputValue(event.target.value)} + onKeyDown={(event) => { + if (event.key === "Enter") addItem(); + }} + /> + +
+
+ {items.map((item, index) => { + const labelId = `${String(id)}-${index}`; + const selected = selectedItems.has(index); + const deletingSelectedItems = selectedItems.size > 1; + + return ( + + + { + setSelectedItems((previous) => { + const nextSelected = new Set(previous); + + if (checked) { + nextSelected.add(index); + } else { + nextSelected.delete(index); + } + + return nextSelected; + }); + }} + /> + +
+
+ } + /> + + + deleteItems( + deletingSelectedItems + ? selectedItems + : new Set([index]), + ) + } + > + {deletingSelectedItems ? "Delete Selected" : "Delete"} + + +
+ ); + })} +
+
+
+ ); +} diff --git a/apps/web/src/routes/settings/chat.tsx b/apps/web/src/routes/settings/chat.tsx index f67a2c6..9f070df 100644 --- a/apps/web/src/routes/settings/chat.tsx +++ b/apps/web/src/routes/settings/chat.tsx @@ -1,4 +1,4 @@ -import { Switch } from "@/features/settings/components"; +import { List, Switch } from "@/features/settings/components"; import { Kbd } from "@tensamin/ui"; export default function Page() { @@ -25,6 +25,7 @@ export default function Page() { label="Sidebar message preview" id="settings.show_start_of_last_message_in_sidebar" /> + ); } diff --git a/bun.lock b/bun.lock index dc7cf4b..71acf11 100644 --- a/bun.lock +++ b/bun.lock @@ -43,6 +43,7 @@ "@tauri-apps/api": "^2", "@tauri-apps/plugin-barcode-scanner": "~2", "@tauri-apps/plugin-deep-link": "~2", + "@tauri-apps/plugin-log": "~2", "@tauri-apps/plugin-notification": "~2", "@tensamin/shared": "workspace:*", "@tensamin/ui": "*", @@ -719,6 +720,8 @@ "@tauri-apps/plugin-deep-link": ["@tauri-apps/plugin-deep-link@2.4.9", "", { "dependencies": { "@tauri-apps/api": "^2.11.0" } }, "sha512-u0SKOUHnJ1wqeqXsDFq2+kASCBj9xxbG0g9XZWPy9SOmU4wXtp6b/wiYpm6oH6/5fBTQsLqnLhIvqLBRpgHJlA=="], + "@tauri-apps/plugin-log": ["@tauri-apps/plugin-log@2.8.0", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-a+7rOq3MJwpTOLLKbL8d0qGZ85hgHw5pNOWusA9o3cf7cEgtYHiGY/+O8fj8MvywQIGqFv0da2bYQDlrqLE7rw=="], + "@tauri-apps/plugin-notification": ["@tauri-apps/plugin-notification@2.3.3", "", { "dependencies": { "@tauri-apps/api": "^2.8.0" } }, "sha512-Zw+ZH18RJb41G4NrfHgIuofJiymusqN+q8fGUIIV7vyCH+5sSn5coqRv/MWB9qETsUs97vmU045q7OyseCV3Qg=="], "@tensamin/call": ["@tensamin/call@workspace:packages/call"], diff --git a/packages/chat/src/components/media.tsx b/packages/chat/src/components/media.tsx new file mode 100644 index 0000000..a800897 --- /dev/null +++ b/packages/chat/src/components/media.tsx @@ -0,0 +1,42 @@ +import Text from "@tensamin/markdown/text"; +import { useStorage } from "@tensamin/storage/context"; +import { Tooltip, TooltipContent, TooltipTrigger } from "@tensamin/ui"; +import { TriangleAlert } from "lucide-react"; +import { useState, useMemo, useEffect } from "react"; + +export default function Media({ link }: { link: string }) { + const { load } = useStorage(); + + const [trustedDomains, setTrustedDomains] = useState([]); + const [hidden, setHidden] = useState(true); + const hostname = useMemo(() => new URL(link).hostname, [link]); + + useEffect(() => { + load("chat_trusted_domains").then(setTrustedDomains); + }, [load]); + + return trustedDomains.includes(hostname) ? ( + <> + {hidden && } + setHidden(false)} + className="max-h-70 max-w-70" + /> + + ) : ( +
+ + } + /> + + Link embeds can expose your ip address. You can configure trusted + domains in the settings. + + + +
+ ); +} diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx index 60afa75..824c287 100644 --- a/packages/chat/src/components/message.tsx +++ b/packages/chat/src/components/message.tsx @@ -2,6 +2,7 @@ import * as React from "react"; import type { RawMessage } from "../values"; import Text from "@tensamin/markdown/text"; import { AlertTriangle } from "lucide-react"; +import { useEffect, useState } from "react"; import { Avatar, @@ -15,6 +16,7 @@ import { import Wrapper from "@tensamin/user/wrapper"; import { useChat } from "../context"; import MessageContextMenu from "./messageContextMenu"; +import Media from "./media"; function MessageComponent({ grouped, @@ -28,6 +30,18 @@ function MessageComponent({ const { userId } = useChat(); const actuallyFailed = message.failed && message.message_state === "awaiting"; + const [isValidURL, setIsValidURL] = useState(false); + useEffect(() => { + try { + if (message.content.split(" ").length > 1) throw new Error(); + + new URL(message.content); + setIsValidURL(true); + } catch { + setIsValidURL(false); + } + }, [message.content]); + return (
)} - + {isValidURL ? ( + + ) : ( + + )} )} diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts index 2210192..a3518db 100644 --- a/packages/shared/src/data.ts +++ b/packages/shared/src/data.ts @@ -259,6 +259,7 @@ export interface Storage extends SettingsStorageDefaults { ttp_url: string; call_mute_range_start: number; call_mute_range_end: number; + chat_trusted_domains: string[]; } export const storageDefaults: Storage = { @@ -294,6 +295,7 @@ export const storageDefaults: Storage = { ttp_url: "https://tensamin.net:959", call_mute_range_start: -55, call_mute_range_end: -45, + chat_trusted_domains: ["tenor.com", "c.tenor.com"], }; // User Status