Browse Source

20.2.0 release

David Benson 3 years ago
parent
commit
cd024abfc1

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+22-JUL-2022: 20.2.0
+
+- Changes real-time collaboration CF worker to use the same DO for multiple files
+
 21-JUL-2022: 20.1.4
 
 - Fixes dark mode switch overlaps embed buttons

+ 1 - 1
VERSION

@@ -1 +1 @@
-20.1.4
+20.2.0

File diff suppressed because it is too large
+ 771 - 770
src/main/webapp/js/app.min.js


+ 23 - 11
src/main/webapp/js/diagramly/DrawioFileSync.js

@@ -870,21 +870,27 @@ DrawioFileSync.prototype.doSendLocalChanges = function(changes)
 	if (!this.file.ignorePatches(changes))
 	{
 		var changeId = this.clientId + '.' + (this.syncChangeCounter++);
-		var msg = {a: 'change', c: changes, id: changeId, t: Date.now()};
-		var data = encodeURIComponent(
-			this.objectToString(
-			this.createMessage(msg)));
+		var msg = this.createMessage({a: 'change', c: changes,
+			id: changeId, t: Date.now()});
 		var skipped = false;
 		
 		if (this.p2pCollab != null)
 		{
-			this.p2pCollab.sendDiff(data);
+			this.p2pCollab.sendDiff(msg);
 		}
-		else if (urlParams['dev'] == '1' &&
-			(this.maxSyncMessageSize == 0 ||
-			data.length < this.maxSyncMessageSize))
+		else if (urlParams['dev'] == '1')
 		{
-			mxUtils.post(EditorUi.cacheUrl, this.getIdParameters() + '&msg=' + data);
+			var data = encodeURIComponent(this.objectToString(msg));
+
+			if (this.maxSyncMessageSize == 0 ||
+				data.length < this.maxSyncMessageSize)
+			{
+				mxUtils.post(EditorUi.cacheUrl, this.getIdParameters() + '&msg=' + data);
+			}
+			else
+			{
+				skipped = true;
+			}
 		}
 		else
 		{
@@ -892,8 +898,7 @@ DrawioFileSync.prototype.doSendLocalChanges = function(changes)
 		}
 
 		EditorUi.debug('DrawioFileSync.doSendLocalChanges', [this],
-			'changes', changes, data.length, 'bytes',
-			skipped ? '(skipped)' : '');
+			'changes', changes, skipped ? '(skipped)' : '');
 	}
 };
 
@@ -1992,6 +1997,12 @@ DrawioFileSync.prototype.stop = function()
 		
 		this.pusher.disconnect();
 		this.pusher = null;
+
+		if (this.p2pCollab != null)
+		{
+			this.p2pCollab.destroy();
+			this.p2pCollab = null;
+		}
 	}
 	
 	this.updateOnlineState();
@@ -2061,6 +2072,7 @@ DrawioFileSync.prototype.destroy = function()
 		this.collaboratorsElement = null;
 	}
 
+	// This is not needed now as stop already destroyed it
 	if (this.p2pCollab != null)
 	{
 		this.p2pCollab.destroy();

+ 1 - 1
src/main/webapp/js/diagramly/Editor.js

@@ -194,7 +194,7 @@
 	/**
 	 * Disables fast real time collaboration while keeping slower real time collaboration enabled.
 	 */
-	Editor.enableRealtime = false;
+	Editor.enableRealtime = true;
 
 	/**
 	 * Specifies if XML files should be compressed. Default is true.

+ 203 - 161
src/main/webapp/js/diagramly/P2PCollab.js

@@ -1,6 +1,7 @@
 function P2PCollab(ui, sync, channelId)
 {
 	var graph = ui.editor.graph;
+	var encrypted = true; // global flag to encrypt all messages
 	var sessionCount = 0;
 	var socket = null;
 	var colors = [
@@ -59,49 +60,67 @@ function P2PCollab(ui, sync, channelId)
 
 	function sendMessage(type, data)
 	{
-		if (destroyed) return;
+		try
+		{
+			if (destroyed) return;
 
-		var user = sync.file.getCurrentUser();
+			var user = sync.file.getCurrentUser();
 
-		if (!fileJoined || user == null || user.email == null) return;
-		
-		//Converting to a string such that webRTC works also
-		var msg = JSON.stringify({from: myClientId, id: messageId,
-			type: type, sessionId: sync.clientId, userId: user.id,
-			username: user.displayName, data: data,
-			protocol: DrawioFileSync.PROTOCOL,
-			editor: EditorUi.VERSION});
-		
-		if (NO_P2P && type != 'cursor')
-		{
-			EditorUi.debug('P2PCollab: sending to socket server', [msg]);
-		}
+			if (!fileJoined || user == null || user.email == null) return;
+			
+			//Converting to a string such that webRTC works also
+			var msg = {from: myClientId, id: messageId,
+				type: type, sessionId: sync.clientId, userId: user.id,
+				username: user.displayName, data: data,
+				protocol: DrawioFileSync.PROTOCOL,
+				editor: EditorUi.VERSION};
+
+			if (encrypted)
+			{
+				// data is needed for old server to not drop messages
+				msg = {bytes: sync.objectToString(msg), data: 'aes'};
+			}
+
+			msg = JSON.stringify(msg);
+			
+			if (NO_P2P && type != 'cursor')
+			{
+				EditorUi.debug('P2PCollab: sending to socket server', [msg]);
+			}
 
-		messageId++;
-		var p2pOnlyMsgs = !NO_P2P && (type == 'cursor' || type == 'selectionChange');
+			messageId++;
+			var p2pOnlyMsgs = !NO_P2P && (type == 'cursor' || type == 'selectionChange');
 
-		if (useSocket && !p2pOnlyMsgs)
-		{
-			sendReply('message', msg);
+			if (useSocket && !p2pOnlyMsgs)
+			{
+				sendReply('message', msg);
+			}
+			
+			//TODO Currently, we only send cursor & selection messages via P2P
+			if (p2pOnlyMsgs)
+			{
+				for (p2pId in p2pClients)
+				{
+					p2pClients[p2pId].send(msg);
+				}
+			}
 		}
-		
-		//TODO Currently, we only send cursor & selection messages via P2P
-		if (p2pOnlyMsgs)
+		catch (e)
 		{
-			for (p2pId in p2pClients)
+			if (window.console != null)
 			{
-				p2pClients[p2pId].send(msg);
+				console.log('Error:', e);
 			}
 		}
 	};
 	
 	this.sendMessage = sendMessage;
 	
-	this.sendDiff = function(diff)
+	this.sendDiff = function(msg)
 	{
-		this.sendMessage('diff', {
-			patch: diff
-		});
+		this.sendMessage('diff', (encrypted) ?
+			{diff: msg} : {patch: encodeURIComponent(
+				sync.objectToString(msg))});
 	};
 
 	this.getState = function()
@@ -275,171 +294,194 @@ function P2PCollab(ui, sync, channelId)
 
 	function processMsg(msg, fromCId)
 	{
-		if (destroyed) return;
-
-		msg = JSON.parse(msg);
-		
-		if (NO_P2P && msg.type != 'cursor')
+		try
 		{
-			EditorUi.debug('P2PCollab: msg received', [msg]);
-		}
+			if (destroyed) return;
 
-		//Exclude P2P messages from duplicate messages test since p2p can arrive before socket and interrupt delivery
-		if (fromCId != null)
-		{
-			//Safeguard from duplicate messages or receiving my own messages
-			if (msg.from == myClientId || clientLastMsgId[msg.from] >= msg.id)
+			msg = JSON.parse(msg);
+
+			if (msg.bytes != null)
 			{
-				EditorUi.debug('P2PCollab: Dropped Message', msg, myClientId, clientLastMsgId[msg.from])
-				return;
+				msg = sync.stringToObject(msg.bytes);
 			}
 			
-			clientLastMsgId[msg.from] = msg.id;
-		}
-		
-		var username = msg.username? msg.username : 'Anonymous';
-		var sessionId = msg.sessionId;
-		var cursor, selection;
-
-		function createCursor()
-		{
-			if (connectedSessions[sessionId] == null)
+			if (NO_P2P && msg.type != 'cursor')
 			{
-				var clrIndex = sessionColors[sessionId];
+				EditorUi.debug('P2PCollab: msg received', [msg]);
+			}
 
-				if (clrIndex == null)
+			//Exclude P2P messages from duplicate messages test since p2p can arrive before socket and interrupt delivery
+			if (fromCId != null)
+			{
+				//Safeguard from duplicate messages or receiving my own messages
+				if (msg.from == myClientId || clientLastMsgId[msg.from] >= msg.id)
 				{
-					clrIndex = sessionCount % colors.length;
-					sessionColors[sessionId] = clrIndex;
-					sessionCount++;
+					EditorUi.debug('P2PCollab: Dropped Message', msg, myClientId, clientLastMsgId[msg.from])
+					return;
 				}
-
-				var clr = colors[clrIndex];
-				var lblClr = clrIndex > 11? 'black' : 'white';
-
-				connectedSessions[sessionId] = {
-					cursor: document.createElement('div'),
-					color: clr,
-					selection: {}
-				};
-				
-				clientsToSessions[fromCId] = sessionId;
-				cursor = connectedSessions[sessionId].cursor;
 				
-				cursor.style.pointerEvents = 'none';
-				cursor.style.position = 'absolute';
-				cursor.style.display = 'none';
-				cursor.style.opacity = '0.9';
-				var img = document.createElement('img');
-				mxUtils.setPrefixedStyle(img.style, 'transform', 'rotate(-45deg)translateX(-14px)');
-				img.setAttribute('src', createCursorImage(clr));
-				img.style.width = '10px';
-				cursor.appendChild(img);
-				
-				var name = document.createElement('div');
-				name.style.backgroundColor = clr;
-				name.style.color = lblClr;
-				name.style.fontSize = '9pt';
-				name.style.padding = '3px 7px';
-				name.style.marginTop = '8px';
-				name.style.borderRadius = '10px';
-				name.style.maxWidth = '100px';
-				name.style.overflow = 'hidden';
-				name.style.textOverflow = 'ellipsis';
-				name.style.whiteSpace = 'nowrap';
-				
-				mxUtils.write(name, username);
-				cursor.appendChild(name);
-
-				ui.diagramContainer.appendChild(cursor);
-				selection = connectedSessions[sessionId].selection;
-			}
-			else
-			{
-				cursor = connectedSessions[sessionId].cursor;
-				selection = connectedSessions[sessionId].selection;
+				clientLastMsgId[msg.from] = msg.id;
 			}
-		};
+			
+			var username = msg.username? msg.username : 'Anonymous';
+			var sessionId = msg.sessionId;
+			var cursor, selection;
 
-		if (connectedSessions[sessionId] != null)
-		{
-			clearTimeout(connectedSessions[sessionId].inactiveTO);
-			connectedSessions[sessionId].inactiveTO = setTimeout(function()
+			function createCursor()
 			{
-				clientLeft(null, sessionId);
-			}, INACTIVE_TIMEOUT);
-		}
-
-		var msgData = msg.data;
-		
-		switch (msg.type)
-		{
-			case 'cursor':
-				createCursor();
-				connectedSessions[sessionId].lastCursor = msgData;
-				updateCursor(connectedSessions[sessionId], true);
-			break;
-			case 'diff':
-				try
+				if (connectedSessions[sessionId] == null)
 				{
-					var msg = sync.stringToObject(decodeURIComponent(msgData.patch));
-					sync.receiveRemoteChanges(msg.d);
+					var clrIndex = sessionColors[sessionId];
+
+					if (clrIndex == null)
+					{
+						clrIndex = sessionCount % colors.length;
+						sessionColors[sessionId] = clrIndex;
+						sessionCount++;
+					}
+
+					var clr = colors[clrIndex];
+					var lblClr = clrIndex > 11? 'black' : 'white';
+
+					connectedSessions[sessionId] = {
+						cursor: document.createElement('div'),
+						color: clr,
+						selection: {}
+					};
+					
+					clientsToSessions[fromCId] = sessionId;
+					cursor = connectedSessions[sessionId].cursor;
+					
+					cursor.style.pointerEvents = 'none';
+					cursor.style.position = 'absolute';
+					cursor.style.display = 'none';
+					cursor.style.opacity = '0.9';
+					var img = document.createElement('img');
+					mxUtils.setPrefixedStyle(img.style, 'transform', 'rotate(-45deg)translateX(-14px)');
+					img.setAttribute('src', createCursorImage(clr));
+					img.style.width = '10px';
+					cursor.appendChild(img);
+					
+					var name = document.createElement('div');
+					name.style.backgroundColor = clr;
+					name.style.color = lblClr;
+					name.style.fontSize = '9pt';
+					name.style.padding = '3px 7px';
+					name.style.marginTop = '8px';
+					name.style.borderRadius = '10px';
+					name.style.maxWidth = '100px';
+					name.style.overflow = 'hidden';
+					name.style.textOverflow = 'ellipsis';
+					name.style.whiteSpace = 'nowrap';
+					
+					mxUtils.write(name, username);
+					cursor.appendChild(name);
+
+					ui.diagramContainer.appendChild(cursor);
+					selection = connectedSessions[sessionId].selection;
 				}
-				catch (e)
+				else
 				{
-					EditorUi.debug('P2PCollab: Diff msg error', e);
+					cursor = connectedSessions[sessionId].cursor;
+					selection = connectedSessions[sessionId].selection;
 				}
-			break;
-			case 'selectionChange':
-				if (urlParams['remote-selection'] != '0')
+			};
+
+			if (connectedSessions[sessionId] != null)
+			{
+				clearTimeout(connectedSessions[sessionId].inactiveTO);
+				connectedSessions[sessionId].inactiveTO = setTimeout(function()
 				{
-					var pageId = (ui.currentPage != null) ?
-						ui.currentPage.getId() : null;
-					
-					if (pageId == null ||
-						(msgData.pageId != null &&
-						msgData.pageId == pageId))
+					clientLeft(null, sessionId);
+				}, INACTIVE_TIMEOUT);
+			}
+
+			var msgData = msg.data;
+			
+			switch (msg.type)
+			{
+				case 'cursor':
+					createCursor();
+					connectedSessions[sessionId].lastCursor = msgData;
+					updateCursor(connectedSessions[sessionId], true);
+				break;
+				case 'diff':
+					try
 					{
-						createCursor();
+						if (msgData.patch != null)
+						{
+							msg = sync.stringToObject(decodeURIComponent(msgData.patch));
+						}
+						else
+						{
+							msg = msgData.diff;
+						}
 
-						for (var i = 0; i < msgData.removed.length; i++)
+						sync.receiveRemoteChanges(msg.d);
+					}
+					catch (e)
+					{
+						EditorUi.debug('P2PCollab: Diff msg error', e);
+					}
+				break;
+				case 'selectionChange':
+					if (urlParams['remote-selection'] != '0')
+					{
+						var pageId = (ui.currentPage != null) ?
+							ui.currentPage.getId() : null;
+						
+						if (pageId == null ||
+							(msgData.pageId != null &&
+							msgData.pageId == pageId))
 						{
-							var id = msgData.removed[i];
+							createCursor();
 
-							if (id != null)
+							for (var i = 0; i < msgData.removed.length; i++)
 							{
-								var handler = selection[id];
-								delete selection[id];
-								
-								if (handler != null)
+								var id = msgData.removed[i];
+
+								if (id != null)
 								{
-									handler.destroy();
+									var handler = selection[id];
+									delete selection[id];
+									
+									if (handler != null)
+									{
+										handler.destroy();
+									}
 								}
 							}
-						}
-						
-						for (var i = 0; i < msgData.added.length; i++)
-						{
-							var id = msgData.added[i];
-
-							if (id != null)
+							
+							for (var i = 0; i < msgData.added.length; i++)
 							{
-								var cell = graph.model.getCell(id);
+								var id = msgData.added[i];
 
-								if (cell != null)
-								{	
-									selection[id] = graph.highlightCell(cell,
-										connectedSessions[sessionId].color, 60000,
-										SELECTION_OPACITY, 3);
+								if (id != null)
+								{
+									var cell = graph.model.getCell(id);
+
+									if (cell != null)
+									{	
+										selection[id] = graph.highlightCell(cell,
+											connectedSessions[sessionId].color, 60000,
+											SELECTION_OPACITY, 3);
+									}
 								}
 							}
 						}
 					}
-				}
-			break;
-		}
+				break;
+			}
 
-		sync.file.fireEvent(new mxEventObject('realtimeMessage', 'message', msg));
+			sync.file.fireEvent(new mxEventObject('realtimeMessage', 'message', msg));
+		}
+		catch (e)
+		{
+			if (window.console != null)
+			{
+				console.log('Error:', e);
+			}
+		}
 	};
 	
 	function createPeer(id, initiator)

File diff suppressed because it is too large
+ 6 - 6
src/main/webapp/js/integrate.min.js


File diff suppressed because it is too large
+ 3 - 3
src/main/webapp/js/viewer-static.min.js


File diff suppressed because it is too large
+ 3 - 3
src/main/webapp/js/viewer.min.js


File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/mxgraph/mxClient.js


File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/service-worker.js


File diff suppressed because it is too large
+ 1 - 1
src/main/webapp/service-worker.js.map