-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Shared editing with collaborative notebook model. (#10118)
* initial skeleton for a shared model package * integrity * more shared types * use shared namespace * rename shared-model to nbmodel * rename shared-model to nbmodel * add lumino signals with delta content * add lumino signals with delta content * better signals + utils skeleton * Implement nbmodel.SharedModel with Yjs * add tests and revamp ymodel API * nbmodel integration - sync text source * implement suggestions * nbmodel integration - sync codemirror with codemirrorbinding * implement suggestions * only dispose ycodemirror binding if enabled * pin yjs versions * yeditorBinding field can be null * pin y-codemirror version * add nbmodel path to tsconfig * Fix yjs imports * fix cdemirror package tests * Add more test and factore the cell factory into a namespace * use static factory methods for cell creation * add updateMetadata on notebook interface * Sync notebook celllist with nbmodel * docprovider package skeleton * docprovider package skeleton * test for the docprovider skeleton * fix issues when syncing remote changes * add yjs ws server * integrate docprovider into docregistry * make notebook-context collaborative * test services * Document.IModel: rename attributed nbmodel to nbnotebook as it is has a ISharedNotebook type * rename nbmodelSwitched to nbcellSwitched to be more specific on the effective action * nbmodel: remove unused utils * make cell metadata shareable * fix package.json * fix tsconfig.json * more typings for cell metadata * ensure with manage metadata not defined in nbformat * debug issue * Check if notebook is initialized befor creating an empty cell * Adds documentation * reverts #20 * fix tests by reverting yjs_echo_server, metadata, and cell-duplication fix * add awareness & yjs_ws_server * enable back the shared cell metadata * Add docprovider and nbmodel to singletons * Y.UndoManager integration * fix completer * lint * fix switching cell-type * fix type issue * Added new optional argument to IModelFactory * Docstrings * Review and lint * Quick pass on the lab code style * More style formatting * Prefix remote-caret CSS class * Lint * Docstrings ISharedNotebook * docstring api * Improve documentation for isStandalone * docstring ymodel * docstring create cell methods * Unobserve on dispose * Added ymodel to YNotebook * Add source to nbcell * upgrade nbmodel and docprovider package to 3.1.0-alpha.4 * temporary disable splice tests * better comment out splice_source test * Added file content type to the guid of the provider * Make ycellMapping private in nbmodel * add docs for nbmodel & docprovider * add cell id and fix undo-tests * rebase to upstream * re-enable services tests * fix moving cells * refactor to use shared-models package to implement different document models * initialize * separate FileModel/DocumentModel from Notebook model * rework import of es modules * fix notebook tests * rename nbmodel imports to models * Modify YCodeCell * Changed ymodel * Changed CodeCellModel * review * fix remove cell * fix output move and display issues * fix overwriting remote content when loading another window * fix syncing outputs initially * Add copyright header to yjs_echo_ws.py * Fix None checks * Add --collaborative option to activate collaboration * Default outputs to [] * bump version of shared-models & docprovider to match other packages * package.json integrity update Co-authored-by: Eric Charles <eric@datalayer.io> Co-authored-by: hbcarlos <carlosherrerocontact@gmail.com> Co-authored-by: Jeremy Tuloup <jeremy.tuloup@gmail.com>
- Loading branch information
1 parent
b9ee4f6
commit 16cba94
Showing
67 changed files
with
3,290 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
"""Echo WebSocket handler for real time collaboration with Yjs""" | ||
|
||
# Copyright (c) Jupyter Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||
|
||
import uuid | ||
import time | ||
|
||
from tornado.ioloop import IOLoop | ||
from tornado.websocket import WebSocketHandler | ||
|
||
acquireLockMessageType = 127 | ||
releaseLockMessageType = 126 | ||
requestInitializedContentMessageType = 125 | ||
putInitializedContentMessageType = 124 | ||
|
||
class YjsRoom: | ||
def __init__(self): | ||
self.lock = None | ||
self.clients = {} | ||
self.content = bytes([]) | ||
|
||
class YJSEchoWS(WebSocketHandler): | ||
rooms = {} | ||
|
||
def open(self, guid): | ||
#print("[YJSEchoWS]: open", guid) | ||
cls = self.__class__ | ||
self.id = str(uuid.uuid4()) | ||
self.room_id = guid | ||
room = cls.rooms.get(self.room_id) | ||
if room is None: | ||
room = YjsRoom() | ||
cls.rooms[self.room_id] = room | ||
room.clients[self.id] = ( IOLoop.current(), self.hook_send_message ) | ||
# Send SyncStep1 message (based on y-protocols) | ||
self.write_message(bytes([0, 0, 1, 0]), binary=True) | ||
|
||
def on_message(self, message): | ||
#print("[YJSEchoWS]: message, ", message) | ||
cls = self.__class__ | ||
room = cls.rooms.get(self.room_id) | ||
if message[0] == acquireLockMessageType: # tries to acquire lock | ||
now = int(time.time()) | ||
if room.lock is None or now - room.lock > 15: # no lock or timeout | ||
room.lock = now | ||
# print('Acquired new lock: ', room.lock) | ||
# return acquired lock | ||
self.write_message(bytes([acquireLockMessageType]) + room.lock.to_bytes(4, byteorder = 'little'), binary=True) | ||
elif message[0] == releaseLockMessageType: | ||
releasedLock = int.from_bytes(message[1:], byteorder = 'little') | ||
# print("trying release lock: ", releasedLock) | ||
if room.lock == releasedLock: | ||
# print('released lock: ', room.lock) | ||
room.lock = None | ||
elif message[0] == requestInitializedContentMessageType: | ||
# print("client requested initial content") | ||
self.write_message(bytes([requestInitializedContentMessageType]) + room.content, binary=True) | ||
elif message[0] == putInitializedContentMessageType: | ||
# print("client put initialized content") | ||
room.content = message[1:] | ||
elif room: | ||
for client_id, (loop, hook_send_message) in room.clients.items() : | ||
if self.id != client_id : | ||
loop.add_callback(hook_send_message, message) | ||
|
||
def on_close(self): | ||
# print("[YJSEchoWS]: close") | ||
cls = self.__class__ | ||
room = cls.rooms.get(self.room_id) | ||
room.clients.pop(self.id) | ||
if len(room.clients) == 0 : | ||
cls.rooms.pop(self.room_id) | ||
# print("[YJSEchoWS]: close room " + self.room_id) | ||
|
||
return True | ||
|
||
def check_origin(self, origin): | ||
#print("[YJSEchoWS]: check origin") | ||
return True | ||
|
||
def hook_send_message(self, msg): | ||
self.write_message(msg, binary=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.