Apply changes from team members in own editor

This commit is contained in:
kiragrammel
2023-08-16 18:36:42 +02:00
committed by Sebastian Serth
parent 69ba7270dd
commit 89afb599e4
8 changed files with 127 additions and 4 deletions

View File

@@ -0,0 +1,38 @@
$(document).on('turbolinks:load', function () {
if (window.location.pathname.includes('/implement')) {
const editor = $('#editor');
const exercise_id = editor.data('exercise-id');
const current_user_id = editor.data('user-id');
const current_contributor_id = editor.data('contributor-id');
if ($.isController('exercises') && current_user_id !== current_contributor_id) {
App.synchronized_editor = App.cable.subscriptions.create({
channel: "SynchronizedEditorChannel", exercise_id: exercise_id
}, {
connected() {
// Called when the subscription is ready for use on the server
},
disconnected() {
// Called when the subscription has been terminated by the server
},
received(data) {
// Called when there's incoming data on the websocket for this channel
if (current_user_id !== data['current_user_id']) {
CodeOceanEditor.applyChanges(data['delta']['data']);
}
},
send_changes(delta) {
const delta_with_user_id = {current_user_id: current_user_id, delta: delta}
this.perform('send_changes', {delta_with_user_id: delta_with_user_id});
}
});
}
}
});

View File

@@ -29,6 +29,7 @@ var CodeOceanEditor = {
running: false,
lastCopyText: null,
lastDeltaObject: null,
<% self.class.include Rails.application.routes.url_helpers %>
<% @config ||= CodeOcean::Config.new(:code_ocean).read(erb: false) %>
@@ -334,6 +335,12 @@ var CodeOceanEditor = {
// listener for autosave
session.on("change", function (deltaObject, session) {
if (this.compareDeltaObjects(deltaObject, CodeOceanEditor.lastDeltaObject)) {
CodeOceanEditor.lastDeltaObject = null;
return;
}
App.synchronized_editor?.send_changes(deltaObject);
// TODO: This is a workaround for a bug in Ace. Remove when upgrading Ace.
this.handleUTF16Surrogates(deltaObject, session);
this.resetSaveTimer();
@@ -1015,6 +1022,27 @@ var CodeOceanEditor = {
}
},
applyChanges: function (delta) {
this.lastDeltaObject = delta;
this.editors[0].session.doc.applyDeltas([delta]);
},
compareDeltaObjects: function (delta, last_delta) {
if (delta === null || last_delta === null) {
return false;
}
const delta_data = delta.data
// We need this manual comparison because the range uses two different classes
// and there is no function to compare these two objects.
return delta_data.action === last_delta.action &&
delta_data.range.start.row === last_delta.range.start.row &&
delta_data.range.start.column === last_delta.range.start.column &&
delta_data.range.end.row === last_delta.range.end.row &&
delta_data.range.end.column === last_delta.range.end.column &&
delta_data.text === last_delta.text;
},
initializeEverything: function () {
CodeOceanEditor.editors = [];
this.initializeRegexes();