209 lines
5.0 KiB
Rust

use crate::util;
use leptos::*;
use leptos_use::{core::ConnectionReadyState, use_websocket, UseWebsocketReturn};
use serde::{Deserialize, Serialize};
use serde_json::json;
use std::rc::Rc;
#[derive(Serialize)]
struct SurrealRequest {
id: u32,
method: String,
params: Vec<SurrealParams>,
}
#[derive(Serialize)]
#[serde(untagged)]
enum SurrealParams {
Participant,
SigninParam(SigninParam),
CreatePersonParam(CreatePersonParam),
String(String),
}
#[derive(Serialize)]
struct SigninParam {
user: String,
pass: String,
}
#[derive(Serialize)]
struct CreatePersonParam {
name: String,
group: String,
}
#[derive(Clone, Debug)]
pub struct Participant {
name: String,
group: String,
}
#[derive(Clone, Debug)]
pub struct ParticipantsContext(pub ReadSignal<Vec<Participant>>);
#[derive(Clone)]
pub struct SurrealContext {
pub message: Signal<Option<String>>,
send: Rc<dyn Fn(&str)>,
pub ready_state: Signal<ConnectionReadyState>,
pub authenticated: ReadSignal<bool>,
pub set_authenticated: WriteSignal<bool>,
}
#[derive(Serialize, Deserialize)]
struct SurrealResponse {
id: u32,
result: SurrealResult,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum SurrealResult {
String(String),
Null,
}
impl SurrealContext {
pub fn new(
message: Signal<Option<String>>,
send: Rc<dyn Fn(&str)>,
ready_state: Signal<ConnectionReadyState>,
authenticated: ReadSignal<bool>,
set_authenticated: WriteSignal<bool>,
) -> Self {
Self {
message,
send,
ready_state,
authenticated,
set_authenticated,
}
}
/// Send a string to surrealDB
#[inline(always)]
pub fn send(&self, message: &str) {
(self.send)(message)
}
/// sigin SurrealDB
pub fn signin(&self, pass: String) {
log::debug!("Signing into surrealdb");
let request = SurrealRequest {
id: 0,
method: String::from("signin"),
params: vec![SurrealParams::SigninParam(SigninParam {
user: String::from("root"),
pass,
})],
};
self.send(&json!(request).to_string());
}
pub fn add_person(&self, name: String, group: String) -> Result<(), String> {
if name.is_empty() {
return Err(String::from("Name cannot be empty"));
}
let request = SurrealRequest {
id: 1,
method: String::from("create"),
params: vec![
SurrealParams::String(String::from("person")),
SurrealParams::CreatePersonParam(CreatePersonParam {
name,
group: "group:".to_owned() + &group,
}),
],
};
Ok(self.send(&json!(request).to_string()))
}
}
pub fn init_surrealdb() {
// Initialize a connection to surrealDB
let UseWebsocketReturn {
ready_state,
message,
send,
..
} = use_websocket("ws://localhost:80/rpc");
// Create reactive signals for the websocket connection to surrealDB
let (participants, _set_participants) = create_signal::<Vec<Participant>>(vec![]);
let (authenticated, set_authenticated) = create_signal::<bool>(false);
// Bind the websocket connection to a context
let websocket = SurrealContext::new(
message,
Rc::new(send.clone()),
ready_state,
authenticated,
set_authenticated,
);
provide_context(websocket);
provide_context(ParticipantsContext(participants));
// Watch for a message recieved from the surrealDB connection
create_effect(move |prev_value| {
let msg = message.get();
if prev_value != Some(msg.clone()) {
match msg {
Some(ref text) => {
log::debug!("{:?}", text);
surrealdb_response(text.to_string());
}
None => (),
}
}
msg
});
}
/// Function to execute when SurrealDB returns a message
fn surrealdb_response(response: String) {
let response: SurrealResponse = match serde_json::from_str(&response) {
Ok(res) => res,
Err(err) => {
log::warn!("{}", err);
return;
}
};
match response.id {
0 => use_surrealdb(response),
1 => log::debug!("Succesfully execute use wrb timings"),
_ => return,
}
}
/// Function to execute when DB signin is succesful
fn use_surrealdb(_response: SurrealResponse) {
util::toast::add_toast(
"Succesfully signed into DB".to_string(),
"success".to_string(),
);
let websocket = expect_context::<SurrealContext>();
websocket.set_authenticated.set(true);
let request = SurrealRequest {
id: 1,
method: String::from("use"),
params: vec![
SurrealParams::String(String::from("wrb")),
SurrealParams::String(String::from("timings")),
],
};
websocket.send(&json!(request).to_string())
}