mirror of
https://github.com/hexedtech/codemp.git
synced 2024-11-22 07:14:50 +01:00
commit
f03995c9d6
5 changed files with 107 additions and 16 deletions
|
@ -8,6 +8,8 @@ use crate::buffer::controller::BufferController;
|
||||||
#[napi]
|
#[napi]
|
||||||
impl BufferController {
|
impl BufferController {
|
||||||
|
|
||||||
|
/// Register a callback to be invoked every time a new event is available to consume
|
||||||
|
/// There can only be one callback registered at any given time.
|
||||||
#[napi(js_name = "callback", ts_args_type = "fun: (event: BufferController) => void")]
|
#[napi(js_name = "callback", ts_args_type = "fun: (event: BufferController) => void")]
|
||||||
pub fn js_callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
pub fn js_callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
||||||
let tsfn : ThreadsafeFunction<crate::buffer::controller::BufferController, Fatal> =
|
let tsfn : ThreadsafeFunction<crate::buffer::controller::BufferController, Fatal> =
|
||||||
|
@ -17,46 +19,51 @@ impl BufferController {
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
self.callback(move |controller : BufferController| {
|
self.callback(move |controller : BufferController| {
|
||||||
|
tsfn.call(controller.clone(), ThreadsafeFunctionCallMode::Blocking);
|
||||||
tsfn.call(controller.clone(), ThreadsafeFunctionCallMode::Blocking); //check this with tracing also we could use Ok(event) to get the error
|
//check this with tracing also we could use Ok(event) to get the error
|
||||||
// If it blocks the main thread too many time we have to change this
|
// If it blocks the main thread too many time we have to change this
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove registered buffer callback
|
||||||
#[napi(js_name = "clear_callback")]
|
#[napi(js_name = "clear_callback")]
|
||||||
pub fn js_clear_callback(&self) {
|
pub fn js_clear_callback(&self) {
|
||||||
self.clear_callback();
|
self.clear_callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get buffer path
|
||||||
#[napi(js_name = "get_path")]
|
#[napi(js_name = "get_path")]
|
||||||
pub fn js_path(&self) -> &str {
|
pub fn js_path(&self) -> &str {
|
||||||
self.path()
|
self.path()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Block until next buffer event without returning it
|
||||||
#[napi(js_name = "poll")]
|
#[napi(js_name = "poll")]
|
||||||
pub async fn js_poll(&self) -> napi::Result<()>{
|
pub async fn js_poll(&self) -> napi::Result<()>{
|
||||||
Ok(self.poll().await?)
|
Ok(self.poll().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return next buffer event if present
|
||||||
#[napi(js_name = "try_recv")]
|
#[napi(js_name = "try_recv")]
|
||||||
pub async fn js_try_recv(&self) -> napi::Result<Option<TextChange>> {
|
pub async fn js_try_recv(&self) -> napi::Result<Option<TextChange>> {
|
||||||
Ok(self.try_recv().await?)
|
Ok(self.try_recv().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Wait for next buffer event and return it
|
||||||
#[napi(js_name = "recv")]
|
#[napi(js_name = "recv")]
|
||||||
pub async fn js_recv(&self) -> napi::Result<TextChange> {
|
pub async fn js_recv(&self) -> napi::Result<TextChange> {
|
||||||
Ok(self.recv().await?)
|
Ok(self.recv().await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send a buffer update to workspace
|
||||||
#[napi(js_name = "send")]
|
#[napi(js_name = "send")]
|
||||||
pub async fn js_send(&self, op: TextChange) -> napi::Result<()> {
|
pub async fn js_send(&self, op: TextChange) -> napi::Result<()> {
|
||||||
Ok(self.send(op).await?)
|
Ok(self.send(op).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return buffer whole content
|
||||||
#[napi(js_name = "content")]
|
#[napi(js_name = "content")]
|
||||||
pub async fn js_content(&self) -> napi::Result<String> {
|
pub async fn js_content(&self) -> napi::Result<String> {
|
||||||
Ok(self.content().await?)
|
Ok(self.content().await?)
|
||||||
|
|
|
@ -1,6 +1,31 @@
|
||||||
use napi_derive::napi;
|
use napi_derive::napi;
|
||||||
use crate::{Client, Workspace};
|
use crate::{Client, Workspace};
|
||||||
|
|
||||||
|
#[napi(object, js_name = "User")]
|
||||||
|
pub struct JsUser {
|
||||||
|
pub uuid: String,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<JsUser> for crate::api::User {
|
||||||
|
type Error = <uuid::Uuid as std::str::FromStr>::Err;
|
||||||
|
fn try_from(value: JsUser) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Self {
|
||||||
|
id: value.uuid.parse()?,
|
||||||
|
name: value.name,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<crate::api::User> for JsUser {
|
||||||
|
fn from(value: crate::api::User) -> Self {
|
||||||
|
Self {
|
||||||
|
uuid: value.id.to_string(),
|
||||||
|
name: value.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
/// connect to codemp servers and return a client session
|
/// connect to codemp servers and return a client session
|
||||||
pub async fn connect(config: crate::api::Config) -> napi::Result<crate::Client>{
|
pub async fn connect(config: crate::api::Config) -> napi::Result<crate::Client>{
|
||||||
|
@ -51,10 +76,10 @@ impl Client {
|
||||||
self.get_workspace(&workspace)
|
self.get_workspace(&workspace)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(js_name = "user_id")]
|
#[napi(js_name = "user")]
|
||||||
/// return current sessions's user id
|
/// return current sessions's user id
|
||||||
pub fn js_user_id(&self) -> String {
|
pub fn js_user(&self) -> JsUser {
|
||||||
self.user().id.to_string()
|
self.user().clone().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[napi(js_name = "active_workspaces")]
|
#[napi(js_name = "active_workspaces")]
|
||||||
|
|
|
@ -4,7 +4,6 @@ use napi::threadsafe_function::{ThreadsafeFunction, ThreadSafeCallContext, Threa
|
||||||
use crate::api::Controller;
|
use crate::api::Controller;
|
||||||
use crate::cursor::controller::CursorController;
|
use crate::cursor::controller::CursorController;
|
||||||
|
|
||||||
|
|
||||||
#[napi(object, js_name = "Cursor")]
|
#[napi(object, js_name = "Cursor")]
|
||||||
pub struct JsCursor {
|
pub struct JsCursor {
|
||||||
/// range of text change, as char indexes in buffer previous state
|
/// range of text change, as char indexes in buffer previous state
|
||||||
|
@ -26,6 +25,7 @@ impl From<JsCursor> for crate::api::Cursor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<crate::api::Cursor> for JsCursor {
|
impl From<crate::api::Cursor> for JsCursor {
|
||||||
fn from(value: crate::api::Cursor) -> Self {
|
fn from(value: crate::api::Cursor) -> Self {
|
||||||
JsCursor {
|
JsCursor {
|
||||||
|
@ -44,6 +44,8 @@ impl From<crate::api::Cursor> for JsCursor {
|
||||||
#[napi]
|
#[napi]
|
||||||
impl CursorController {
|
impl CursorController {
|
||||||
|
|
||||||
|
/// Register a callback to be called on receive.
|
||||||
|
/// There can only be one callback registered at any given time.
|
||||||
#[napi(js_name = "callback", ts_args_type = "fun: (event: CursorController) => void")]
|
#[napi(js_name = "callback", ts_args_type = "fun: (event: CursorController) => void")]
|
||||||
pub fn js_callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
pub fn js_callback(&self, fun: napi::JsFunction) -> napi::Result<()>{
|
||||||
let tsfn : ThreadsafeFunction<crate::cursor::controller::CursorController, Fatal> =
|
let tsfn : ThreadsafeFunction<crate::cursor::controller::CursorController, Fatal> =
|
||||||
|
@ -53,29 +55,35 @@ impl CursorController {
|
||||||
}
|
}
|
||||||
)?;
|
)?;
|
||||||
self.callback(move |controller : CursorController| {
|
self.callback(move |controller : CursorController| {
|
||||||
|
tsfn.call(controller.clone(), ThreadsafeFunctionCallMode::Blocking);
|
||||||
tsfn.call(controller.clone(), ThreadsafeFunctionCallMode::Blocking); //check this with tracing also we could use Ok(event) to get the error
|
//check this with tracing also we could use Ok(event) to get the error
|
||||||
// If it blocks the main thread too many time we have to change this
|
// If it blocks the main thread too many time we have to change this
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clear the registered callback
|
||||||
|
#[napi(js_name = "clear_callback")]
|
||||||
|
pub fn js_clear_callback(&self) {
|
||||||
|
self.clear_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Send a new cursor event to remote
|
||||||
#[napi(js_name = "send")]
|
#[napi(js_name = "send")]
|
||||||
pub async fn js_send(&self, pos: JsCursor) -> napi::Result<()> {
|
pub async fn js_send(&self, pos: JsCursor) -> napi::Result<()> {
|
||||||
Ok(self.send(crate::api::Cursor::from(pos)).await?)
|
Ok(self.send(crate::api::Cursor::from(pos)).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get next cursor event if available without blocking
|
||||||
#[napi(js_name= "try_recv")]
|
#[napi(js_name= "try_recv")]
|
||||||
pub async fn js_try_recv(&self) -> napi::Result<Option<JsCursor>> {
|
pub async fn js_try_recv(&self) -> napi::Result<Option<JsCursor>> {
|
||||||
Ok(self.try_recv().await?
|
Ok(self.try_recv().await?
|
||||||
.map(JsCursor::from))
|
.map(JsCursor::from))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Block until next
|
||||||
#[napi(js_name= "recv")]
|
#[napi(js_name= "recv")]
|
||||||
pub async fn js_recv(&self) -> napi::Result<JsCursor> {
|
pub async fn js_recv(&self) -> napi::Result<JsCursor> {
|
||||||
Ok(self.recv().await?.into())
|
Ok(self.recv().await?.into())
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use napi_derive::napi;
|
use napi_derive::napi;
|
||||||
|
|
||||||
|
|
||||||
|
/// Hash function
|
||||||
#[napi(js_name = "hash")]
|
#[napi(js_name = "hash")]
|
||||||
pub fn js_hash(data: String) -> i64 {
|
pub fn js_hash(data: String) -> i64 {
|
||||||
crate::ext::hash(data)
|
crate::ext::hash(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get the current version of the client
|
||||||
#[napi(js_name = "version")]
|
#[napi(js_name = "version")]
|
||||||
pub fn js_version() -> String {
|
pub fn js_version() -> String {
|
||||||
crate::version()
|
crate::version()
|
||||||
|
|
|
@ -2,6 +2,7 @@ use napi_derive::napi;
|
||||||
use crate::Workspace;
|
use crate::Workspace;
|
||||||
use crate::buffer::controller::BufferController;
|
use crate::buffer::controller::BufferController;
|
||||||
use crate::cursor::controller::CursorController;
|
use crate::cursor::controller::CursorController;
|
||||||
|
use crate::ffi::js::client::JsUser;
|
||||||
|
|
||||||
#[napi(object, js_name = "Event")]
|
#[napi(object, js_name = "Event")]
|
||||||
pub struct JsEvent {
|
pub struct JsEvent {
|
||||||
|
@ -21,48 +22,95 @@ impl From<crate::api::Event> for JsEvent {
|
||||||
|
|
||||||
#[napi]
|
#[napi]
|
||||||
impl Workspace {
|
impl Workspace {
|
||||||
|
/// Get the unique workspace id
|
||||||
#[napi(js_name = "id")]
|
#[napi(js_name = "id")]
|
||||||
pub fn js_id(&self) -> String {
|
pub fn js_id(&self) -> String {
|
||||||
self.id()
|
self.id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List all available buffers in this workspace
|
||||||
#[napi(js_name = "filetree")]
|
#[napi(js_name = "filetree")]
|
||||||
pub fn js_filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
pub fn js_filetree(&self, filter: Option<&str>, strict: bool) -> Vec<String> {
|
||||||
self.filetree(filter, strict)
|
self.filetree(filter, strict)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List all user names currently in this workspace
|
||||||
#[napi(js_name = "user_list")]
|
#[napi(js_name = "user_list")]
|
||||||
pub fn js_user_list(&self) -> Vec<String> {
|
pub fn js_user_list(&self) -> Vec<String> {
|
||||||
self.user_list()
|
self.user_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// List all currently active buffers
|
||||||
|
#[napi(js_name = "buffer_list")]
|
||||||
|
pub fn js_buffer_list(&self) -> Vec<String> {
|
||||||
|
self.buffer_list()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get workspace's Cursor Controller
|
||||||
#[napi(js_name = "cursor")]
|
#[napi(js_name = "cursor")]
|
||||||
pub fn js_cursor(&self) -> CursorController {
|
pub fn js_cursor(&self) -> CursorController {
|
||||||
self.cursor()
|
self.cursor()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a buffer controller by its name (path)
|
||||||
#[napi(js_name = "buffer_by_name")]
|
#[napi(js_name = "buffer_by_name")]
|
||||||
pub fn js_buffer_by_name(&self, path: String) -> Option<BufferController> {
|
pub fn js_buffer_by_name(&self, path: String) -> Option<BufferController> {
|
||||||
self.buffer_by_name(&path)
|
self.buffer_by_name(&path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a new buffer in the current workspace
|
||||||
#[napi(js_name = "create")]
|
#[napi(js_name = "create")]
|
||||||
pub async fn js_create(&self, path: String) -> napi::Result<()> {
|
pub async fn js_create(&self, path: String) -> napi::Result<()> {
|
||||||
Ok(self.create(&path).await?)
|
Ok(self.create(&path).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Attach to a workspace buffer, starting a BufferController
|
||||||
#[napi(js_name = "attach")]
|
#[napi(js_name = "attach")]
|
||||||
pub async fn js_attach(&self, path: String) -> napi::Result<BufferController> {
|
pub async fn js_attach(&self, path: String) -> napi::Result<BufferController> {
|
||||||
Ok(self.attach(&path).await?)
|
Ok(self.attach(&path).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Delete a buffer from workspace
|
||||||
#[napi(js_name = "delete")]
|
#[napi(js_name = "delete")]
|
||||||
pub async fn js_delete(&self, path: String) -> napi::Result<()> {
|
pub async fn js_delete(&self, path: String) -> napi::Result<()> {
|
||||||
Ok(self.delete(&path).await?)
|
Ok(self.delete(&path).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Detach from an active buffer, stopping its underlying worker
|
||||||
|
/// this method returns true if no reference or last reference was held, false if there are still
|
||||||
|
/// dangling references to clear
|
||||||
|
#[napi(js_name = "detach")]
|
||||||
|
pub async fn js_detach(&self, path: String) -> bool {
|
||||||
|
self.detach(&path)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wait for next workspace event and return it
|
||||||
#[napi(js_name = "event")]
|
#[napi(js_name = "event")]
|
||||||
pub async fn js_event(&self) -> napi::Result<JsEvent> {
|
pub async fn js_event(&self) -> napi::Result<JsEvent> {
|
||||||
Ok(JsEvent::from(self.event().await?))
|
Ok(JsEvent::from(self.event().await?))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Re-fetch remote buffer list
|
||||||
|
#[napi(js_name = "fetch_buffers")]
|
||||||
|
pub async fn js_fetch_buffers(&self) -> napi::Result<()> {
|
||||||
|
Ok(self.fetch_buffers().await?)
|
||||||
|
}
|
||||||
|
/// Re-fetch the list of all users in the workspace.
|
||||||
|
#[napi(js_name = "fetch_users")]
|
||||||
|
pub async fn js_fetch_users(&self) -> napi::Result<()> {
|
||||||
|
Ok(self.fetch_users().await?)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// List users attached to a specific buffer
|
||||||
|
#[napi(js_name = "list_buffer_users")]
|
||||||
|
pub async fn js_list_buffer_users(&self, path: String) -> napi::Result<Vec<JsUser>> {
|
||||||
|
Ok(
|
||||||
|
self
|
||||||
|
.list_buffer_users(&path)
|
||||||
|
.await?
|
||||||
|
.into_iter()
|
||||||
|
.map(JsUser::from)
|
||||||
|
.collect())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue