diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..90e4844 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Changelog + +## Unreleased - 11.9.2023 + +### Added + +- `YRoomMessage.has_edits: bool` flag indicating data changes have occurred. + +## v0.0.8 diff --git a/README.md b/README.md index c7275bf..282b1f3 100644 --- a/README.md +++ b/README.md @@ -15,3 +15,11 @@ pip install yroom ## API See `yroom.pyi`. + +## Development + +[Maturin](https://www.maturin.rs) can be used to build `Yroom` inside a virtual environment. + +``` +maturin develop +``` diff --git a/src/roomsync.rs b/src/roomsync.rs index e4fd8b6..9dfbb58 100644 --- a/src/roomsync.rs +++ b/src/roomsync.rs @@ -235,6 +235,8 @@ pub struct YRoomMessage { pub payloads: PyObject, #[pyo3(get)] pub broadcast_payloads: PyObject, + #[pyo3(get)] + pub has_edits: PyObject, } fn make_payloads(py: Python, payloads: &[Vec]) -> PyObject { @@ -242,17 +244,18 @@ fn make_payloads(py: Python, payloads: &[Vec]) -> PyObject { } impl YRoomMessage { - fn from_payloads(payloads: &[Vec], broadcast_payloads: &[Vec]) -> YRoomMessage { + fn from_payloads(payloads: &[Vec], broadcast_payloads: &[Vec], has_edits: bool) -> YRoomMessage { Python::with_gil(|py| YRoomMessage { payloads: make_payloads(py, payloads), broadcast_payloads: make_payloads(py, broadcast_payloads), + has_edits: has_edits.into_py(py), }) } } impl Default for YRoomMessage { fn default() -> Self { - YRoomMessage::from_payloads(&[], &[]) + YRoomMessage::from_payloads(&[], &[], false) } } @@ -260,8 +263,8 @@ impl Default for YRoomMessage { impl YRoomMessage { pub fn __str__(&self) -> String { format!( - "YRoomMessage(payloads: {}, broadcast_payloads: {})", - self.payloads, self.broadcast_payloads + "YRoomMessage(payloads: {}, broadcast_payloads: {}, has_edits: {})", + self.payloads, self.broadcast_payloads, self.has_edits ) } @@ -360,7 +363,7 @@ impl YRoomManager { pub fn disconnect(&mut self, room: String, conn_id: u64) -> YRoomMessage { let broadcast_payload = self.get_room(&room).disconnect(conn_id); - YRoomMessage::from_payloads(&[], &broadcast_payload) + YRoomMessage::from_payloads(&[], &broadcast_payload, false) } pub fn has_room(&self, room: String) -> bool { @@ -534,6 +537,7 @@ impl YRoom { Python::with_gil(|py| YRoomMessage { payloads: make_payloads(py, &payloads), broadcast_payloads: make_payloads(py, &[]), + has_edits: false.into_py(py), }) } @@ -563,6 +567,7 @@ impl YRoom { self.settings.disable_pipelining, decoder.document_name.clone(), ); + let mut has_edits = false; decoder.for_each(|message_result| match message_result { Ok(message) => match message { @@ -598,6 +603,7 @@ impl YRoom { } Err(e) => log::error!("Error decoding sync step 2: {}", e), } + has_edits = true; } Message::Sync(SyncMessage::Update(data)) => { let update = Update::decode_v1(&data); @@ -610,6 +616,7 @@ impl YRoom { } Err(e) => log::error!("Error decoding update: {}", e), } + has_edits = true; } Message::Auth(_) => { // TODO: check this. Always reply with permission granted @@ -657,7 +664,7 @@ impl YRoom { log::warn!("Bad message from connection {}: {:?}", conn_id, err); } }); - YRoomMessage::from_payloads(&sync_encoder.to_vecs(), &update_encoder.to_vecs()) + YRoomMessage::from_payloads(&sync_encoder.to_vecs(), &update_encoder.to_vecs(), has_edits) } pub fn disconnect(&mut self, conn_id: u64) -> Vec> { diff --git a/yroom.pyi b/yroom.pyi index 3ebea0e..e8c67fc 100644 --- a/yroom.pyi +++ b/yroom.pyi @@ -6,10 +6,12 @@ class YRoomMessage: `payload` is a message that should be sent to the connection that sent the message. `broadcast_payload` is a message that should be sent to all connections in the room. Either or both of the members can be of zero length and then must not be sent. + `has_edits` flag indicates if data changes occurred. Does not include awareness updates. """ payloads: List[bytes] broadcast_payloads: List[bytes] + has_edits: bool class YRoomSettings(TypedDict): wire_version: int # The Yjs encoding/decoding version to use (1 or 2, default: 1)