mirror of
https://github.com/xevidos/codiad.git
synced 2024-12-22 22:02:15 +01:00
Added storing of cursor position so you do not get kicked to the beginning or end of file on join
This commit is contained in:
parent
2f4727aad3
commit
397b656c87
3 changed files with 462 additions and 88 deletions
307
plugins/Codiad-Collaborative-master/file_db.php
Executable file
307
plugins/Codiad-Collaborative-master/file_db.php
Executable file
|
@ -0,0 +1,307 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) Luc Verdier & Florent Galland, distributed
|
||||||
|
* as-is and without warranty under the MIT License. See
|
||||||
|
* [root]/license.txt for more. This information must remain intact.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Suppose a user wants to register as a collaborator of file '/test/test.js'.
|
||||||
|
* He registers to a specific file by creating a marker file
|
||||||
|
* 'data/_test_test.js%%filename%%username%%registered', and he can
|
||||||
|
* unregister by deleting this file. Then his current selection will be in
|
||||||
|
* file 'data/_test_test.js%%username%%selection'.
|
||||||
|
* The collaborative editing algorithm is based on the differential synchronization
|
||||||
|
* algorithm by Neil Fraser. The text shadow and server text are stored
|
||||||
|
* respectively in 'data/_test_test.js%%filename%%username%%shadow' and
|
||||||
|
* 'data/_test_test.js%%filename%%text'.
|
||||||
|
* At regular time intervals, the user send an heartbeat which is stored in
|
||||||
|
* 'data/_test_test.js%%username%%heartbeat' .
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* */
|
||||||
|
class file_db {
|
||||||
|
|
||||||
|
/* They should be the same as those
|
||||||
|
* in the file_db_entry class. */
|
||||||
|
private $separator = '|';
|
||||||
|
private $separator_regex = '\|';
|
||||||
|
private $key_value_separator = ':';
|
||||||
|
private $key_value_separator_regex = '\:';
|
||||||
|
|
||||||
|
private $index_name = 'index.db';
|
||||||
|
private $base_path;
|
||||||
|
|
||||||
|
function __construct($base_path) {
|
||||||
|
$this->base_path = $base_path;
|
||||||
|
if(!is_dir($base_path)) {
|
||||||
|
mkdir($base_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new entry into the data base. */
|
||||||
|
public function create($query, $group=null) {
|
||||||
|
$query = $this->_normalize_query($query);
|
||||||
|
|
||||||
|
if(!$this->_is_direct_query($query)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$base_path = $this->base_path;
|
||||||
|
if($group != null) {
|
||||||
|
$base_path .= '/' . $group;
|
||||||
|
}
|
||||||
|
$index_file = $base_path . '/' . $this->index_name;
|
||||||
|
|
||||||
|
if(!is_dir($base_path)) {
|
||||||
|
mkdir($base_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry_name = $this->_make_entry_name($query);
|
||||||
|
$entry_hash = md5($entry_name);
|
||||||
|
$entry_file = $base_path . '/' . $entry_hash;
|
||||||
|
|
||||||
|
if(!file_exists($entry_file)) {
|
||||||
|
if(!file_exists($index_file)) {
|
||||||
|
touch($index_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = $entry_name . '>' . $entry_hash . '>' . PHP_EOL;
|
||||||
|
file_put_contents($index_file, $entry, FILE_APPEND | LOCK_EX);
|
||||||
|
touch($entry_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry = new file_db_entry($entry_name, $entry_file, $index_file, $group);
|
||||||
|
$entry->clear();
|
||||||
|
|
||||||
|
if(file_exists($entry_file)) {
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the content for the given query. */
|
||||||
|
public function select($query, $group=null) {
|
||||||
|
$query = $this->_normalize_query($query);
|
||||||
|
|
||||||
|
$base_path = $this->base_path;
|
||||||
|
if($group != null) {
|
||||||
|
$base_path .= '/' . $group;
|
||||||
|
}
|
||||||
|
$index_file = $base_path . '/' . $this->index_name;
|
||||||
|
|
||||||
|
if($this->_is_direct_query($query)) {
|
||||||
|
$entry_name = $this->_make_entry_name($query);
|
||||||
|
$entry_hash = md5($entry_name);
|
||||||
|
$entry_file = $base_path . '/' . $entry_hash;
|
||||||
|
|
||||||
|
if(file_exists($entry_file)) {
|
||||||
|
return new file_db_entry($entry_name, $entry_file, $index_file, $group);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entries = array();
|
||||||
|
if(file_exists($index_file)) {
|
||||||
|
$regex = $this->_make_regex($query);
|
||||||
|
$file = fopen($index_file, 'r');
|
||||||
|
while(!feof($file)) {
|
||||||
|
$line = fgets($file);
|
||||||
|
if (preg_match($regex, $line, $matches)) {
|
||||||
|
$entry_file = $base_path . '/' . $matches[2];
|
||||||
|
if(file_exists($entry_file)) {
|
||||||
|
$entries[] = new file_db_entry($matches[1], $entry_file, $index_file, $group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Select all entries into the given group. */
|
||||||
|
public function select_group($group) {
|
||||||
|
$entries = array();
|
||||||
|
|
||||||
|
$base_path = $this->base_path . '/' . $group;
|
||||||
|
$index_file = $base_path . '/' . $this->index_name;
|
||||||
|
|
||||||
|
if(file_exists($index_file)) {
|
||||||
|
$sep = $this->separator_regex;
|
||||||
|
$regex = '/(' . $sep . '.*?' . $sep . ')\>(.*?)\>/';
|
||||||
|
$file = fopen($index_file, 'r');
|
||||||
|
while(!feof($file)) {
|
||||||
|
$line = fgets($file);
|
||||||
|
if (preg_match($regex, $line, $matches)) {
|
||||||
|
$entry_file = $base_path . '/' . $matches[2];
|
||||||
|
$entries[] = new file_db_entry($matches[1], $entry_file, $index_file, $group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make the regex for the given query. */
|
||||||
|
private function _make_regex($query) {
|
||||||
|
$regex = '/(' . $this->separator_regex;
|
||||||
|
foreach($query as $key => $value) {
|
||||||
|
$regex .= $key . $this->key_value_separator_regex;
|
||||||
|
if($value == '%2A') { // %2A=*
|
||||||
|
$regex .= '.*?';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$regex .= $value;
|
||||||
|
}
|
||||||
|
$regex .= $this->separator_regex;
|
||||||
|
}
|
||||||
|
$regex .= ')' . '\>(.*?)\>' . '/';
|
||||||
|
return $regex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make an entry name from the given normalized query. */
|
||||||
|
private function _make_entry_name($query) {
|
||||||
|
$filename = $this->separator;
|
||||||
|
foreach($query as $key => $value) {
|
||||||
|
$filename .= $key . $this->key_value_separator . $value;
|
||||||
|
$filename .= $this->separator;
|
||||||
|
}
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if the given query is a direct query. */
|
||||||
|
private function _is_direct_query($query) {
|
||||||
|
foreach($query as $key => $value) {
|
||||||
|
if($value == '%2A'){ // %2A=*
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Normalize the given query. */
|
||||||
|
private function &_normalize_query(&$query) {
|
||||||
|
ksort($query);
|
||||||
|
foreach($query as $key => $value) {
|
||||||
|
$query[$key] = rawurlencode($value);
|
||||||
|
}
|
||||||
|
return $query;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
class file_db_entry {
|
||||||
|
|
||||||
|
/* They should be the same as those
|
||||||
|
* in the file_db class. */
|
||||||
|
private $separator = '|';
|
||||||
|
private $separator_regex = '\|';
|
||||||
|
private $key_value_separator = ':';
|
||||||
|
private $key_value_separator_regex = '\:';
|
||||||
|
|
||||||
|
private $entry_name;
|
||||||
|
private $entry_hash;
|
||||||
|
private $entry_file;
|
||||||
|
private $index_file;
|
||||||
|
private $group;
|
||||||
|
|
||||||
|
private $handler;
|
||||||
|
|
||||||
|
/* Construct the entry with the given filename. */
|
||||||
|
public function __construct($entry_name, $entry_file, $index_file, $group) {
|
||||||
|
$this->entry_name = $entry_name;
|
||||||
|
$this->entry_file = $entry_file;
|
||||||
|
$this->index_file = $index_file;
|
||||||
|
$this->group = $group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the value of the field with the given name. */
|
||||||
|
public function get_field($name) {
|
||||||
|
$regex = '/'
|
||||||
|
. $this->separator_regex
|
||||||
|
. rawurlencode($name)
|
||||||
|
. $this->key_value_separator_regex
|
||||||
|
. '(.*?)' . $this->separator_regex
|
||||||
|
. '/';
|
||||||
|
if(preg_match($regex, $this->entry_name, $matches)) {
|
||||||
|
return rawurldecode($matches[1]);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the group name of the entry. */
|
||||||
|
public function get_group() {
|
||||||
|
return $this->group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the value of the entry. */
|
||||||
|
public function put_value($value) {
|
||||||
|
file_put_contents($this->entry_file, serialize($value), LOCK_EX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the value of the entry. */
|
||||||
|
public function get_value() {
|
||||||
|
if(file_exists($this->entry_file)) {
|
||||||
|
return unserialize(file_get_contents($this->entry_file));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove the entry. */
|
||||||
|
public function remove() {
|
||||||
|
$success = false;
|
||||||
|
if(file_exists($this->index_file)) {
|
||||||
|
$lines = file($this->index_file, FILE_SKIP_EMPTY_LINES);
|
||||||
|
|
||||||
|
$file = fopen($this->index_file, 'w');
|
||||||
|
flock($file, LOCK_EX);
|
||||||
|
|
||||||
|
foreach($lines as $line) {
|
||||||
|
if (strpos($line, $this->entry_name) !== 0) {
|
||||||
|
fwrite($file, $line);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$success = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flock($file, LOCK_UN);
|
||||||
|
fclose($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($success && file_exists($this->entry_file)) {
|
||||||
|
unlink($this->entry_file);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear the value of the entry. */
|
||||||
|
public function clear() {
|
||||||
|
$this->put_value('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lock the entry. */
|
||||||
|
public function lock() {
|
||||||
|
$lock = $this->entry_file . '.lock';
|
||||||
|
while(file_exists($lock)) {
|
||||||
|
usleep(100);
|
||||||
|
}
|
||||||
|
touch($this->entry_file . '.lock');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlock the entry. */
|
||||||
|
public function unlock() {
|
||||||
|
$lock = $this->entry_file . '.lock';
|
||||||
|
if(file_exists($lock)) {
|
||||||
|
unlink($lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -9,20 +9,21 @@
|
||||||
var codiad = global.codiad,
|
var codiad = global.codiad,
|
||||||
scripts = document.getElementsByTagName('script'),
|
scripts = document.getElementsByTagName('script'),
|
||||||
path = scripts[scripts.length-1].src.split('?')[0],
|
path = scripts[scripts.length-1].src.split('?')[0],
|
||||||
curpath = path.split('/').slice(0, -1).join('/')+'/';
|
curpath = path.split( '/' ).slice( 0, -1 ).join( '/ ') + '/';
|
||||||
|
|
||||||
var site_id = codiad.system.site_id;
|
|
||||||
var session_id = window.session_id;
|
|
||||||
var editor = null;
|
|
||||||
var collaborator = null;
|
|
||||||
var buffer_dumped = false;
|
var buffer_dumped = false;
|
||||||
var last_applied_change = null;
|
var collaborator = null;
|
||||||
var just_cleared_buffer = null;
|
|
||||||
var current_editor = codiad.active.getPath();
|
var current_editor = codiad.active.getPath();
|
||||||
var just_opened = false;
|
var cursor = null;
|
||||||
var loaded = false;
|
var editor = null;
|
||||||
var initial = false;
|
var initial = false;
|
||||||
|
var just_cleared_buffer = null;
|
||||||
|
var just_opened = false;
|
||||||
|
var last_applied_change = null;
|
||||||
|
var loaded = false;
|
||||||
var loading = true;
|
var loading = true;
|
||||||
|
var session_id = codiad.system.session_id;
|
||||||
|
var site_id = codiad.system.site_id;
|
||||||
|
|
||||||
function Collaborator( file_path, session_id ) {
|
function Collaborator( file_path, session_id ) {
|
||||||
|
|
||||||
|
@ -58,26 +59,45 @@
|
||||||
if ( delta.initial === true ) {
|
if ( delta.initial === true ) {
|
||||||
|
|
||||||
console.log( 'Setting initial content...' );
|
console.log( 'Setting initial content...' );
|
||||||
codiad.editor.setContent( '' );
|
//codiad.editor.setContent( '' );
|
||||||
codiad.editor.setContent( delta.content )
|
codiad.editor.setContent( delta.content )
|
||||||
inital = false;
|
inital = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setTimeout(function(){
|
||||||
|
if( cursor !== null ) {
|
||||||
|
console.log( 'Going to position: ' + cursor.row + ", " + cursor.column );
|
||||||
|
editor.gotoLine( cursor.row, cursor.column, true );
|
||||||
|
}
|
||||||
|
}, 256);
|
||||||
|
|
||||||
}.bind() );
|
}.bind() );
|
||||||
|
|
||||||
this.collaboration_socket.on( "recieve_content", function( ) {
|
this.collaboration_socket.on( "recieve_content", function( ) {
|
||||||
|
|
||||||
console.log( 'Someone is joining...' );
|
console.log( 'Someone is joining ...' );
|
||||||
|
console.log( 'Cursor is at ' + cursor.row + ", " + cursor.column );
|
||||||
|
|
||||||
// Remove change callback
|
// Remove change callback
|
||||||
editor.removeEventListener( "change", handle_change );
|
editor.removeEventListener( "change", handle_change );
|
||||||
|
|
||||||
codiad.editor.disableEditing();
|
codiad.editor.disableEditing();
|
||||||
codiad.editor.setContent( '' );
|
codiad.editor.setContent( '' );
|
||||||
collaborator.dump_buffer();
|
collaborator.dump_buffer()
|
||||||
|
|
||||||
// registering change callback
|
// registering change callback
|
||||||
editor.addEventListener( "change", handle_change );
|
editor.addEventListener( "change", handle_change );
|
||||||
setTimeout(function(){codiad.editor.enableEditing();}, 500);
|
}.bind() );
|
||||||
|
|
||||||
|
this.collaboration_socket.on( "unlock", function( ) {
|
||||||
|
|
||||||
|
console.log( 'Unlocking editors and going to ' + cursor.row + ", " + cursor.column );
|
||||||
|
|
||||||
|
codiad.editor.enableEditing();
|
||||||
|
setTimeout(function(){
|
||||||
|
if( cursor !== null ) {
|
||||||
|
console.log( 'Going to position: ' + cursor.row + ", " + cursor.column );
|
||||||
|
editor.gotoLine( cursor.row, cursor.column, true );
|
||||||
|
}
|
||||||
|
}, 256);
|
||||||
}.bind() );
|
}.bind() );
|
||||||
|
|
||||||
window.collaboration_socket = this.collaboration_socket;
|
window.collaboration_socket = this.collaboration_socket;
|
||||||
|
@ -107,6 +127,13 @@
|
||||||
function handle_change( e ) {
|
function handle_change( e ) {
|
||||||
|
|
||||||
// TODO, we could make things more efficient and not likely to conflict by keeping track of change IDs
|
// TODO, we could make things more efficient and not likely to conflict by keeping track of change IDs
|
||||||
|
coords = editor.getCursorPosition();
|
||||||
|
if( coords.row !== 0 && coords.column !== 0 ) {
|
||||||
|
cursor = editor.getCursorPosition();
|
||||||
|
cursor.row = cursor.row + 1
|
||||||
|
console.log( 'Cursor at: ' + cursor.row + ", " + cursor.column );
|
||||||
|
}
|
||||||
|
|
||||||
if( last_applied_change!=e && !just_cleared_buffer ) {
|
if( last_applied_change!=e && !just_cleared_buffer ) {
|
||||||
|
|
||||||
collaborator.change( JSON.stringify(e) );
|
collaborator.change( JSON.stringify(e) );
|
||||||
|
@ -166,6 +193,7 @@
|
||||||
|
|
||||||
collaborator = new Collaborator( session_id );
|
collaborator = new Collaborator( session_id );
|
||||||
|
|
||||||
|
//codiad.editor.disableEditing();
|
||||||
//collaborator.open_file( )
|
//collaborator.open_file( )
|
||||||
content = codiad.editor.getContent()
|
content = codiad.editor.getContent()
|
||||||
codiad.editor.setContent( '' )
|
codiad.editor.setContent( '' )
|
||||||
|
@ -201,9 +229,29 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
$(window).blur(function() {
|
$(window).blur(function() {
|
||||||
|
|
||||||
|
if( editor !== null ) {
|
||||||
|
coords = editor.getCursorPosition();
|
||||||
|
if( coords.row !== 0 && coords.column !== 0 ) {
|
||||||
|
cursor = editor.getCursorPosition();
|
||||||
|
cursor.row = cursor.row + 1
|
||||||
|
console.log( 'Cursor at: ' + cursor.row + ", " + cursor.column );
|
||||||
|
}
|
||||||
|
}
|
||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* When the window is clicked get the cursor position.
|
||||||
|
$(window).click(function () {
|
||||||
|
|
||||||
|
coords = editor.getCursorPosition();
|
||||||
|
if( coords.row !== 0 && coords.column !== 0 ) {
|
||||||
|
//cursor = editor.getCursorPosition();
|
||||||
|
//cursor.row = cursor.row + 1
|
||||||
|
//console.log( 'Cursor at: ' + cursor.row + ", " + cursor.column );
|
||||||
|
}
|
||||||
|
});*/
|
||||||
|
|
||||||
/* Subscribe to know when a file become active. */
|
/* Subscribe to know when a file become active. */
|
||||||
amplify.subscribe('active.onFocus', function (path) {
|
amplify.subscribe('active.onFocus', function (path) {
|
||||||
|
|
||||||
|
@ -211,7 +259,8 @@
|
||||||
|
|
||||||
if( current_editor !== codiad.active.getPath() && current_editor !== null ) {
|
if( current_editor !== codiad.active.getPath() && current_editor !== null ) {
|
||||||
|
|
||||||
console.log( 'Closing Socket' );+
|
cursor = null;
|
||||||
|
console.log( 'Closing Socket' );
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
console.log( 'Last Editor: ' + current_editor );
|
console.log( 'Last Editor: ' + current_editor );
|
||||||
|
@ -222,6 +271,13 @@
|
||||||
body_loaded();
|
body_loaded();
|
||||||
}
|
}
|
||||||
console.log( 'Focused Editor: ' + codiad.active.getPath() );
|
console.log( 'Focused Editor: ' + codiad.active.getPath() );
|
||||||
|
|
||||||
|
coords = editor.getCursorPosition();
|
||||||
|
if( coords.row !== 0 && coords.column !== 0 ) {
|
||||||
|
cursor = editor.getCursorPosition();
|
||||||
|
cursor.row = cursor.row + 1
|
||||||
|
console.log( 'Cursor at: ' + cursor.row + ", " + cursor.column );
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
@ -234,6 +290,8 @@
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
codiad.collaborative = {
|
codiad.collaborative = {
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
})(this, jQuery);
|
})(this, jQuery);
|
|
@ -1,19 +1,19 @@
|
||||||
// config variables
|
// config variables
|
||||||
verbose = false ;
|
verbose = false ;
|
||||||
session_directory = "./sessions" ; // it has to exist
|
session_directory = "./sessions"; // it has to exist
|
||||||
|
|
||||||
/* https specific */
|
/* https specific */
|
||||||
var https = require('https'),
|
var https = require( 'https' ),
|
||||||
fs = require('fs');
|
fs = require( 'fs' );
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
key: fs.readFileSync('/etc/letsencrypt/live/local.telaaedifex.com/privkey.pem'),
|
key: fs.readFileSync( '/etc/letsencrypt/live/local.telaaedifex.com/privkey.pem' ),
|
||||||
cert: fs.readFileSync('/etc/letsencrypt/live/local.telaaedifex.com/fullchain.pem'),
|
cert: fs.readFileSync( '/etc/letsencrypt/live/local.telaaedifex.com/fullchain.pem' ),
|
||||||
ca: fs.readFileSync('/etc/letsencrypt/live/local.telaaedifex.com/chain.pem')
|
ca: fs.readFileSync( '/etc/letsencrypt/live/local.telaaedifex.com/chain.pem' )
|
||||||
};
|
};
|
||||||
var app = https.createServer(options);
|
var app = https.createServer( options );
|
||||||
io = require('socket.io').listen(app); //socket.io server listens to https connections
|
io = require( 'socket.io' ).listen( app ); //socket.io server listens to https connections
|
||||||
app.listen(1337, "0.0.0.0");
|
app.listen( 1337, "0.0.0.0" );
|
||||||
|
|
||||||
// will use the following for file IO
|
// will use the following for file IO
|
||||||
var fs = require( "fs" ) ;
|
var fs = require( "fs" ) ;
|
||||||
|
@ -27,10 +27,10 @@ socket_id_to_session_id = [] ;
|
||||||
|
|
||||||
io.sockets.on('connection', function(socket) {
|
io.sockets.on('connection', function(socket) {
|
||||||
|
|
||||||
|
init = false
|
||||||
var file = socket.handshake.query.file;
|
var file = socket.handshake.query.file;
|
||||||
//var session_id = socket.handshake.query.session_id;
|
//var session_id = socket.handshake.query.session_id;
|
||||||
var session_id = socket.handshake.query.file;
|
var session_id = socket.handshake.query.file;
|
||||||
|
|
||||||
socket_id_to_session_id[socket.id] = session_id ;
|
socket_id_to_session_id[socket.id] = session_id ;
|
||||||
|
|
||||||
if( verbose ) { console.log( session_id + "connected on socket" + socket.id ) ; }
|
if( verbose ) { console.log( session_id + "connected on socket" + socket.id ) ; }
|
||||||
|
@ -42,7 +42,7 @@ io.sockets.on('connection', function(socket) {
|
||||||
if( verbose ) { console.log( "session terminated previously, pulling back from filesystem" ); }
|
if( verbose ) { console.log( "session terminated previously, pulling back from filesystem" ); }
|
||||||
|
|
||||||
var data = read_file( session_directory + "/" + session_id );
|
var data = read_file( session_directory + "/" + session_id );
|
||||||
if( data!==false ) {
|
if( data !== false ) {
|
||||||
|
|
||||||
init = false;
|
init = false;
|
||||||
collaborations[session_id] = {'cached_instructions':JSON.parse(data), 'participants':[]};
|
collaborations[session_id] = {'cached_instructions':JSON.parse(data), 'participants':[]};
|
||||||
|
@ -59,23 +59,31 @@ io.sockets.on('connection', function(socket) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
var i = 0;
|
||||||
|
|
||||||
|
for( i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
||||||
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
||||||
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "recieve_content" );
|
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "recieve_content" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collaborations[session_id]['participants'].push( socket.id );
|
collaborations[session_id]['participants'].push( socket.id );
|
||||||
|
|
||||||
|
for( i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
||||||
|
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
||||||
|
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "unlock" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
socket.on('change', function( delta ) {
|
socket.on('change', function( delta ) {
|
||||||
if( verbose ) { console.log( "change " + socket_id_to_session_id[socket.id] + " " + delta ) ; }
|
if( verbose ) { console.log( "change " + socket_id_to_session_id[socket.id] + " " + delta ) ; }
|
||||||
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
||||||
collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'].push( ["change", delta, Date.now()] ) ;
|
collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'].push( ["change", delta, Date.now()] ) ;
|
||||||
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
||||||
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
||||||
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "change", delta ) ;
|
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "change", delta ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
||||||
}
|
}
|
||||||
|
@ -85,13 +93,13 @@ io.sockets.on('connection', function(socket) {
|
||||||
socket.on('change_selection', function( selections ) {
|
socket.on('change_selection', function( selections ) {
|
||||||
if( verbose ) { console.log( "change_selection " + socket_id_to_session_id[socket.id] + " " + selections ) ; }
|
if( verbose ) { console.log( "change_selection " + socket_id_to_session_id[socket.id] + " " + selections ) ; }
|
||||||
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
||||||
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
||||||
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
||||||
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "change_selection", selections ) ;
|
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "change_selection", selections ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -99,26 +107,27 @@ io.sockets.on('connection', function(socket) {
|
||||||
socket.on('clear_buffer', function() {
|
socket.on('clear_buffer', function() {
|
||||||
if( verbose ) { console.log( "clear_buffer " + socket_id_to_session_id[socket.id] ) ; }
|
if( verbose ) { console.log( "clear_buffer " + socket_id_to_session_id[socket.id] ) ; }
|
||||||
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
||||||
collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'] = [] ;
|
collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'] = [] ;
|
||||||
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
for( var i=0 ; i<collaborations[session_id]['participants'].length ; i++ ) {
|
||||||
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
if( socket.id!=collaborations[session_id]['participants'][i] ) {
|
||||||
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "clear_buffer" ) ;
|
io.sockets.connected[collaborations[session_id]['participants'][i]].emit( "clear_buffer" ) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
socket.on('dump_buffer', function() {
|
socket.on('dump_buffer', function() {
|
||||||
if( verbose ) { console.log( "dump_buffer " + socket_id_to_session_id[socket.id] ) ; }
|
if( verbose ) { console.log( "dump_buffer " + socket_id_to_session_id[socket.id] ) ; }
|
||||||
|
|
||||||
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
||||||
for( var i=0 ; i<collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'].length ; i++ ) {
|
for( var i=0 ; i<collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'].length ; i++ ) {
|
||||||
socket.emit( collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'][i][0], collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'][i][1] ) ;
|
socket.emit( collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'][i][0], collaborations[socket_id_to_session_id[socket.id]]['cached_instructions'][i][1] ) ;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
if( verbose ) { console.log( "WARNING: could not tie socket_id to any collaboration" ) ; }
|
||||||
}
|
}
|
||||||
socket.emit( "buffer_dumped" ) ;
|
socket.emit( "buffer_dumped" ) ;
|
||||||
});
|
});
|
||||||
|
@ -128,20 +137,20 @@ io.sockets.on('connection', function(socket) {
|
||||||
console.log( socket_id_to_session_id[socket.id] + " disconnected" ) ;
|
console.log( socket_id_to_session_id[socket.id] + " disconnected" ) ;
|
||||||
var found_and_removed = false ;
|
var found_and_removed = false ;
|
||||||
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
if( socket_id_to_session_id[socket.id] in collaborations ) {
|
||||||
//var index = collaborations[socket_id_to_session_id[socket.id]].participants.indexOf( socket.id ) ;
|
//var index = collaborations[socket_id_to_session_id[socket.id]].participants.indexOf( socket.id ) ;
|
||||||
var index = collaborations[socket_id_to_session_id[socket.id]]['participants'].indexOf( socket.id ) ;
|
var index = collaborations[socket_id_to_session_id[socket.id]]['participants'].indexOf( socket.id ) ;
|
||||||
if( index>-1 ) {
|
if( index>-1 ) {
|
||||||
//collaborations[socket_id_to_session_id[socket.id]].participants.splice( index, 1 ) ;
|
//collaborations[socket_id_to_session_id[socket.id]].participants.splice( index, 1 ) ;
|
||||||
collaborations[socket_id_to_session_id[socket.id]]['participants'].splice( index, 1 ) ;
|
collaborations[socket_id_to_session_id[socket.id]]['participants'].splice( index, 1 ) ;
|
||||||
found_and_removed = true ;
|
found_and_removed = true ;
|
||||||
//if( collaborations[socket_id_to_session_id[socket.id]].participants.length==0 ) {
|
//if( collaborations[socket_id_to_session_id[socket.id]].participants.length==0 ) {
|
||||||
if( collaborations[socket_id_to_session_id[socket.id]]['participants'].length==0 ) {
|
if( collaborations[socket_id_to_session_id[socket.id]]['participants'].length==0 ) {
|
||||||
if( verbose ) { console.log( "last participant in collaboration, committing to disk & removing from memory" ) ; }
|
if( verbose ) { console.log( "last participant in collaboration, committing to disk & removing from memory" ) ; }
|
||||||
// no one is left in this session, we commit it to disk & remove it from memory
|
// no one is left in this session, we commit it to disk & remove it from memory
|
||||||
write_file( session_directory + "/" + socket_id_to_session_id[socket.id], JSON.stringify(collaborations[socket_id_to_session_id[socket.id]]['cached_instructions']) ) ;
|
write_file( session_directory + "/" + socket_id_to_session_id[socket.id], JSON.stringify(collaborations[socket_id_to_session_id[socket.id]]['cached_instructions']) ) ;
|
||||||
delete collaborations[socket_id_to_session_id[socket.id]] ;
|
delete collaborations[socket_id_to_session_id[socket.id]] ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( !found_and_removed ) {
|
if( !found_and_removed ) {
|
||||||
console.log( "WARNING: could not tie socket_id to any collaboration" ) ;
|
console.log( "WARNING: could not tie socket_id to any collaboration" ) ;
|
||||||
|
@ -163,34 +172,34 @@ io.sockets.on('connection', function(socket) {
|
||||||
|
|
||||||
|
|
||||||
function write_file( path, data ) {
|
function write_file( path, data ) {
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync( path, data ) ;
|
fs.writeFileSync( path, data ) ;
|
||||||
return true ;
|
return true ;
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function read_file( path ) {
|
function read_file( path ) {
|
||||||
try {
|
try {
|
||||||
var data = fs.readFileSync( path ) ;
|
var data = fs.readFileSync( path ) ;
|
||||||
return data ;
|
return data ;
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function file_exists( path ) {
|
function file_exists( path ) {
|
||||||
try {
|
try {
|
||||||
stats = fs.lstatSync( path ) ;
|
stats = fs.lstatSync( path ) ;
|
||||||
if (stats.isFile()) {
|
if (stats.isFile()) {
|
||||||
return true ;
|
return true ;
|
||||||
}
|
}
|
||||||
} catch( e ) {
|
} catch( e ) {
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
||||||
// we should not reach that point
|
// we should not reach that point
|
||||||
return false ;
|
return false ;
|
||||||
}
|
}
|
Loading…
Reference in a new issue