Add API for propagating cursor locations #61
6 changed files with 28 additions and 16 deletions
Send spans instead of indexes
commit
a628ff348e
|
|
@ -15,17 +15,24 @@ pub struct WebSocketHandshake {
|
||||||
pub last_seen_vault_update_id: Option<VaultUpdateId>,
|
pub last_seen_vault_update_id: Option<VaultUpdateId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(TS, Serialize, Deserialize, Clone, Debug)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct CursorSpan {
|
||||||
|
pub start: usize,
|
||||||
|
pub end: usize,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(TS, Deserialize, Clone, Debug)]
|
#[derive(TS, Deserialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CursorPositionFromClient {
|
pub struct CursorPositionFromClient {
|
||||||
pub document_to_cursors: HashMap<String, Vec<usize>>,
|
pub document_to_cursors: HashMap<String, Vec<CursorSpan>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(TS, Serialize, Clone, Debug)]
|
#[derive(TS, Serialize, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ClientCursors {
|
pub struct ClientCursors {
|
||||||
pub device_id: DeviceId,
|
pub device_id: DeviceId,
|
||||||
pub cursors: HashMap<String, Vec<usize>>,
|
pub cursors: HashMap<String, Vec<CursorSpan>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(TS, Serialize, Clone, Debug)]
|
#[derive(TS, Serialize, Clone, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,9 @@ async fn websocket(
|
||||||
stream: WebSocket,
|
stream: WebSocket,
|
||||||
vault_id: VaultId,
|
vault_id: VaultId,
|
||||||
) -> Result<(), SyncServerError> {
|
) -> Result<(), SyncServerError> {
|
||||||
let (mut sender, mut receiver) = stream.split();
|
let (mut sender, mut websocket_receiver) = stream.split();
|
||||||
|
|
||||||
let handshake = if let Some(Ok(message)) = receiver.next().await {
|
let handshake = if let Some(Ok(message)) = websocket_receiver.next().await {
|
||||||
get_handshake(&state, &vault_id, message)?
|
get_handshake(&state, &vault_id, message)?
|
||||||
} else {
|
} else {
|
||||||
return Err(unauthenticated_error(anyhow::anyhow!(
|
return Err(unauthenticated_error(anyhow::anyhow!(
|
||||||
|
|
@ -69,7 +69,7 @@ async fn websocket(
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut rx = state.broadcasts.get_receiver(vault_id.clone()).await;
|
let mut broadcast_receiver = state.broadcasts.get_receiver(vault_id.clone()).await;
|
||||||
|
|
||||||
send_update_over_websocket(
|
send_update_over_websocket(
|
||||||
&WebSocketServerMessage::VaultUpdate(WebSocketVaultUpdate {
|
&WebSocketServerMessage::VaultUpdate(WebSocketVaultUpdate {
|
||||||
|
|
@ -91,7 +91,7 @@ async fn websocket(
|
||||||
|
|
||||||
let device_id = handshake.device_id.clone();
|
let device_id = handshake.device_id.clone();
|
||||||
let mut send_task = tokio::spawn(async move {
|
let mut send_task = tokio::spawn(async move {
|
||||||
while let Ok(update) = rx.recv().await {
|
while let Ok(update) = broadcast_receiver.recv().await {
|
||||||
if Some(&device_id) == update.origin_device_id.as_ref() {
|
if Some(&device_id) == update.origin_device_id.as_ref() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -103,10 +103,10 @@ async fn websocket(
|
||||||
});
|
});
|
||||||
|
|
||||||
let device_id = handshake.device_id.clone();
|
let device_id = handshake.device_id.clone();
|
||||||
let mut recv_task = tokio::spawn(async move {
|
let mut receive_task = tokio::spawn(async move {
|
||||||
while let Some(Ok(Message::Text(message))) = receiver.next().await {
|
while let Some(Ok(Message::Text(message))) = websocket_receiver.next().await {
|
||||||
let message: WebSocketClientMessage = serde_json::from_str(&message)
|
let message: WebSocketClientMessage = serde_json::from_str(&message)
|
||||||
.context("Failed to parse message")
|
.context("Failed to parse WebSocket message from client")
|
||||||
.map_err(server_error)?;
|
.map_err(server_error)?;
|
||||||
|
|
||||||
match message {
|
match message {
|
||||||
|
|
@ -128,8 +128,8 @@ async fn websocket(
|
||||||
});
|
});
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = &mut send_task => recv_task.abort(),
|
_ = &mut send_task => receive_task.abort(),
|
||||||
_ = &mut recv_task => send_task.abort(),
|
_ = &mut receive_task => send_task.abort(),
|
||||||
};
|
};
|
||||||
|
|
||||||
send_task
|
send_task
|
||||||
|
|
@ -137,7 +137,7 @@ async fn websocket(
|
||||||
.context("WebSocket send task failed")
|
.context("WebSocket send task failed")
|
||||||
.map_err(server_error)??;
|
.map_err(server_error)??;
|
||||||
|
|
||||||
recv_task
|
receive_task
|
||||||
.await
|
.await
|
||||||
.context("WebSocket receive task failed")
|
.context("WebSocket receive task failed")
|
||||||
.map_err(server_error)??;
|
.map_err(server_error)??;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { CursorSpan } from "./CursorSpan";
|
||||||
|
|
||||||
export type ClientCursors = { deviceId: string, cursors: { [key in string]?: Array<number> }, };
|
export type ClientCursors = { deviceId: string, cursors: { [key in string]?: Array<CursorSpan> }, };
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
import type { CursorSpan } from "./CursorSpan";
|
||||||
|
|
||||||
export type CursorPositionFromClient = { documentToCursors: { [key in string]?: Array<number> }, };
|
export type CursorPositionFromClient = { documentToCursors: { [key in string]?: Array<CursorSpan> }, };
|
||||||
|
|
|
||||||
3
frontend/sync-client/src/services/types/CursorSpan.ts
Normal file
3
frontend/sync-client/src/services/types/CursorSpan.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
|
export type CursorSpan = { start: number; end: number };
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
./scripts/utils/wait-for-server.sh
|
|
||||||
|
|
||||||
rm -rf backend/sync_server/bindings
|
rm -rf backend/sync_server/bindings
|
||||||
cd backend
|
cd backend
|
||||||
cargo test export_bindings
|
cargo test export_bindings
|
||||||
|
|
@ -11,5 +9,7 @@ cd -
|
||||||
|
|
||||||
cp -r backend/sync_server/bindings/* frontend/sync-client/src/services/types/
|
cp -r backend/sync_server/bindings/* frontend/sync-client/src/services/types/
|
||||||
|
|
||||||
|
./scripts/utils/wait-for-server.sh
|
||||||
|
|
||||||
npm install -g openapi-typescript
|
npm install -g openapi-typescript
|
||||||
openapi-typescript http://localhost:3000/api.json --output frontend/sync-client/src/services/types/http-api.ts
|
openapi-typescript http://localhost:3000/api.json --output frontend/sync-client/src/services/types/http-api.ts
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue