tauri-plugin-deeprespond-im 1.0.0-alpha

深应智能 IM 的 Tauri 插件:本地存储、安全存储、窗口间的锁与消息、系统事件、通知、角标、文件
//! 本地存储的命令(协议见《4.实现与测试》第 4 节):参数一律 snake_case。读写都在数据库的线程中执行,
//! 命令只等回复。写事务只接受引擎窗口;db_delete 只接受引擎。

use std::sync::Arc;

use serde_json::{json, Value};
use tauri::{Runtime, State, Webview};

use super::keys::KeyRangeArg;
use super::{Caller, OpenRequest, Opened, ReadRequest, ReadResult, StoreSchema, WriteOp};
use crate::error::Result;
use crate::Shared;

/// 调用方的页面实例(必须先 hello)。
fn who<R: Runtime>(shared: &Shared, webview: &Webview<R>) -> Result<Caller> {
    let instance = crate::commands::caller(shared, webview)?;
    Ok(Caller { label: instance.label.clone(), instance: instance.id, engine: instance.engine })
}

#[tauri::command(rename_all = "snake_case")]
pub async fn db_open<R: Runtime>(
    webview: Webview<R>,
    state: State<'_, Arc<Shared>>,
    app_key: String,
    username: String,
    version: u32,
    schema: Vec<StoreSchema>,
    encrypt: Option<bool>,
) -> Result<Opened> {
    let caller = who(&state, &webview)?;
    let req = OpenRequest { app_key, username, version, schema, encrypt: encrypt.unwrap_or(false) };
    state.store.open(&caller, req).await
}

#[tauri::command(rename_all = "snake_case")]
pub fn db_close<R: Runtime>(webview: Webview<R>, state: State<'_, Arc<Shared>>, db: u64) -> Result<()> {
    let caller = who(&state, &webview)?;
    state.store.close(&caller, db);
    Ok(())
}

/// 删除一个用户的数据库和附件(引擎专用),之后通知全部页面“数据库已更换”。
#[tauri::command(rename_all = "snake_case")]
pub async fn db_delete<R: Runtime>(webview: Webview<R>, state: State<'_, Arc<Shared>>, app_key: String, username: String) -> Result<()> {
    crate::commands::require_engine(&webview)?;
    state.store.delete(&app_key, &username).await?;
    state.hub.broadcast(json!({ "t": "db_deleted", "app_key": app_key, "username": username.to_lowercase() }));
    Ok(())
}

#[tauri::command(rename_all = "snake_case")]
pub async fn tx_begin<R: Runtime>(
    webview: Webview<R>,
    state: State<'_, Arc<Shared>>,
    db: u64,
    stores: Vec<String>,
    mode: String,
    durability: Option<String>,
) -> Result<Value> {
    let caller = who(&state, &webview)?;
    let tx = state.store.begin(&caller, db, stores, &mode, durability.as_deref()).await?;
    Ok(json!({ "tx": tx }))
}

#[allow(clippy::too_many_arguments)]
#[tauri::command(rename_all = "snake_case")]
pub async fn tx_read<R: Runtime>(
    webview: Webview<R>,
    state: State<'_, Arc<Shared>>,
    tx: u64,
    op: String,
    store: String,
    key: Option<Value>,
    index: Option<String>,
    range: Option<KeyRangeArg>,
    limit: Option<u64>,
    direction: Option<String>,
    cursor: Option<String>,
) -> Result<ReadResult> {
    let caller = who(&state, &webview)?;
    let req = ReadRequest { op, store, key, index, range, limit, direction, cursor };
    state.store.read(&caller, tx, req).await
}

#[tauri::command(rename_all = "snake_case")]
pub async fn tx_write<R: Runtime>(webview: Webview<R>, state: State<'_, Arc<Shared>>, tx: u64, ops: Vec<WriteOp>) -> Result<()> {
    let caller = who(&state, &webview)?;
    state.store.write(&caller, tx, ops).await
}

#[tauri::command(rename_all = "snake_case")]
pub async fn tx_commit<R: Runtime>(webview: Webview<R>, state: State<'_, Arc<Shared>>, tx: u64, ops: Option<Vec<WriteOp>>) -> Result<()> {
    let caller = who(&state, &webview)?;
    state.store.commit(&caller, tx, ops.unwrap_or_default()).await
}

#[tauri::command(rename_all = "snake_case")]
pub fn tx_abort<R: Runtime>(webview: Webview<R>, state: State<'_, Arc<Shared>>, tx: u64) -> Result<()> {
    let caller = who(&state, &webview)?;
    state.store.abort(&caller, tx);
    Ok(())
}