feat: implement browser extension UI with WebAssembly integration

This commit is contained in:
Sameh Abouel-saad
2025-05-22 11:53:32 +03:00
parent 13945a8725
commit ed76ba3d8d
74 changed files with 7054 additions and 577 deletions

View File

@@ -26,8 +26,7 @@ use async_trait::async_trait;
use idb::{Database, TransactionMode, Factory};
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsValue;
#[cfg(target_arch = "wasm32")]
use js_sys::Uint8Array;
// use wasm-bindgen directly for Uint8Array if needed
#[cfg(target_arch = "wasm32")]
use std::rc::Rc;
@@ -47,6 +46,7 @@ impl WasmStore {
let mut open_req = factory.open(name, None)
.map_err(|e| KVError::Other(format!("IndexedDB factory open error: {e:?}")))?;
open_req.on_upgrade_needed(|event| {
use idb::DatabaseEvent;
let db = event.database().expect("Failed to get database in upgrade event");
if !db.store_names().iter().any(|n| n == STORE_NAME) {
db.create_object_store(STORE_NAME, Default::default()).unwrap();
@@ -66,11 +66,13 @@ impl KVStore for WasmStore {
let store = tx.object_store(STORE_NAME)
.map_err(|e| KVError::Other(format!("idb object_store error: {e:?}")))?;
use idb::Query;
let val = store.get(Query::from(JsValue::from_str(key))).await
.map_err(|e| KVError::Other(format!("idb get await error: {e:?}")))?;
let val = store.get(Query::from(JsValue::from_str(key)))?.await
.map_err(|e| KVError::Other(format!("idb get error: {e:?}")))?;
if let Some(jsval) = val {
let arr = Uint8Array::new(&jsval);
Ok(Some(arr.to_vec()))
match jsval.into_serde::<Vec<u8>>() {
Ok(bytes) => Ok(Some(bytes)),
Err(_) => Ok(None),
}
} else {
Ok(None)
}
@@ -80,8 +82,9 @@ impl KVStore for WasmStore {
.map_err(|e| KVError::Other(format!("idb transaction error: {e:?}")))?;
let store = tx.object_store(STORE_NAME)
.map_err(|e| KVError::Other(format!("idb object_store error: {e:?}")))?;
store.put(&Uint8Array::from(value).into(), Some(&JsValue::from_str(key))).await
.map_err(|e| KVError::Other(format!("idb put await error: {e:?}")))?;
let js_value = JsValue::from_serde(&value).map_err(|e| KVError::Other(format!("serde error: {e:?}")))?;
store.put(&js_value, Some(&JsValue::from_str(key)))?.await
.map_err(|e| KVError::Other(format!("idb put error: {e:?}")))?;
Ok(())
}
async fn remove(&self, key: &str) -> Result<()> {
@@ -90,8 +93,8 @@ impl KVStore for WasmStore {
let store = tx.object_store(STORE_NAME)
.map_err(|e| KVError::Other(format!("idb object_store error: {e:?}")))?;
use idb::Query;
store.delete(Query::from(JsValue::from_str(key))).await
.map_err(|e| KVError::Other(format!("idb delete await error: {e:?}")))?;
store.delete(Query::from(JsValue::from_str(key)))?.await
.map_err(|e| KVError::Other(format!("idb delete error: {e:?}")))?;
Ok(())
}
async fn contains_key(&self, key: &str) -> Result<bool> {
@@ -103,12 +106,11 @@ impl KVStore for WasmStore {
.map_err(|e| KVError::Other(format!("idb transaction error: {e:?}")))?;
let store = tx.object_store(STORE_NAME)
.map_err(|e| KVError::Other(format!("idb object_store error: {e:?}")))?;
let js_keys = store.get_all_keys(None, None).await
let js_keys = store.get_all_keys(None, None)?.await
.map_err(|e| KVError::Other(format!("idb get_all_keys error: {e:?}")))?;
let arr = js_sys::Array::from(&JsValue::from(js_keys));
let mut keys = Vec::new();
for i in 0..arr.length() {
if let Some(s) = arr.get(i).as_string() {
for key in js_keys.iter() {
if let Some(s) = key.as_string() {
keys.push(s);
}
}
@@ -120,7 +122,7 @@ impl KVStore for WasmStore {
.map_err(|e| KVError::Other(format!("idb transaction error: {e:?}")))?;
let store = tx.object_store(STORE_NAME)
.map_err(|e| KVError::Other(format!("idb object_store error: {e:?}")))?;
store.clear().await
store.clear()?.await
.map_err(|e| KVError::Other(format!("idb clear error: {e:?}")))?;
Ok(())
}