2023-04-17 14:57:06 +02:00
|
|
|
use std::{collections::HashMap, sync::Mutex};
|
|
|
|
|
2023-04-19 04:18:22 +02:00
|
|
|
use tokio::sync::broadcast;
|
2023-04-19 19:18:48 +02:00
|
|
|
use tracing::{error, debug, warn};
|
2023-04-19 04:18:22 +02:00
|
|
|
|
2023-04-17 14:57:06 +02:00
|
|
|
use crate::proto::CursorMov;
|
|
|
|
|
|
|
|
/// Note that this differs from any hashmap in its put method: no &mut!
|
|
|
|
pub trait CursorStorage {
|
2023-07-01 20:22:39 +02:00
|
|
|
fn get(&self, id: &str) -> Option<Cursor>;
|
2023-04-17 14:57:06 +02:00
|
|
|
fn put(&self, id: String, val: Cursor);
|
|
|
|
|
|
|
|
fn update(&self, event: CursorMov) -> Option<Cursor> {
|
|
|
|
let mut cur = self.get(&event.user)?;
|
|
|
|
cur.buffer = event.path;
|
|
|
|
cur.start = (event.row, event.col).into();
|
|
|
|
self.put(event.user, cur.clone());
|
|
|
|
Some(cur)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-19 04:18:22 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Default)]
|
2023-04-17 14:57:06 +02:00
|
|
|
pub struct Position {
|
2023-04-19 04:18:22 +02:00
|
|
|
pub row: i64,
|
|
|
|
pub col: i64,
|
2023-04-17 14:57:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl From::<(i64, i64)> for Position {
|
|
|
|
fn from((row, col): (i64, i64)) -> Self {
|
|
|
|
Position { row, col }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-04-19 04:18:22 +02:00
|
|
|
#[derive(Clone, Debug, Default)]
|
2023-04-17 14:57:06 +02:00
|
|
|
pub struct Cursor {
|
2023-04-19 04:18:22 +02:00
|
|
|
pub buffer: String,
|
|
|
|
pub start: Position,
|
|
|
|
pub end: Position,
|
2023-04-17 14:57:06 +02:00
|
|
|
}
|
|
|
|
|
2023-07-02 23:59:04 +02:00
|
|
|
#[derive(Debug)]
|
2023-04-17 14:57:06 +02:00
|
|
|
pub struct CursorController {
|
|
|
|
users: Mutex<HashMap<String, Cursor>>,
|
2023-04-19 04:18:22 +02:00
|
|
|
bus: broadcast::Sender<(String, Cursor)>,
|
|
|
|
_bus_keepalive: Mutex<broadcast::Receiver<(String, Cursor)>>,
|
2023-04-17 14:57:06 +02:00
|
|
|
}
|
|
|
|
|
2023-07-01 20:22:39 +02:00
|
|
|
impl Default for CursorController {
|
|
|
|
fn default() -> Self {
|
2023-04-19 04:18:22 +02:00
|
|
|
let (tx, _rx) = broadcast::channel(64);
|
|
|
|
CursorController {
|
|
|
|
users: Mutex::new(HashMap::new()),
|
|
|
|
bus: tx,
|
|
|
|
_bus_keepalive: Mutex::new(_rx),
|
|
|
|
}
|
|
|
|
}
|
2023-07-01 20:22:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CursorController {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
CursorController::default()
|
|
|
|
}
|
2023-04-19 04:18:22 +02:00
|
|
|
|
|
|
|
pub fn sub(&self) -> broadcast::Receiver<(String, Cursor)> {
|
|
|
|
self.bus.subscribe()
|
2023-04-17 14:57:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CursorStorage for CursorController {
|
2023-04-19 04:18:22 +02:00
|
|
|
fn update(&self, event: CursorMov) -> Option<Cursor> {
|
|
|
|
debug!("processing cursor event: {:?}", event);
|
|
|
|
let mut cur = self.get(&event.user).unwrap_or(Cursor::default());
|
|
|
|
cur.buffer = event.path;
|
|
|
|
cur.start = (event.row, event.col).into();
|
|
|
|
cur.end = (event.row, event.col).into();
|
|
|
|
self.put(event.user.clone(), cur.clone());
|
|
|
|
if let Err(e) = self.bus.send((event.user, cur.clone())) {
|
|
|
|
error!("could not broadcast cursor event: {}", e);
|
|
|
|
} else { // this is because once there are no receivers, nothing else can be sent
|
|
|
|
if let Err(e) = self._bus_keepalive.lock().unwrap().try_recv() {
|
|
|
|
warn!("could not consume event: {}", e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(cur)
|
|
|
|
}
|
|
|
|
|
2023-07-01 20:22:39 +02:00
|
|
|
fn get(&self, id: &str) -> Option<Cursor> {
|
2023-04-17 14:57:06 +02:00
|
|
|
Some(self.users.lock().unwrap().get(id)?.clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn put(&self, id: String, val: Cursor) {
|
|
|
|
self.users.lock().unwrap().insert(id, val);
|
|
|
|
}
|
|
|
|
}
|