mirror of
https://github.com/coderaiser/cloudcmd.git
synced 2026-01-24 03:05:41 +00:00
491 lines
16 KiB
JavaScript
491 lines
16 KiB
JavaScript
var CloudCmd, Util, DOM, CloudFunc, io, Zip, Format, MenuIO, edward, restafary;
|
|
(function(CloudCmd, Util, DOM, CloudFunc) {
|
|
'use strict';
|
|
|
|
CloudCmd.Edit = EditProto;
|
|
|
|
function EditProto(callback) {
|
|
var Name = 'Edit',
|
|
Loading = true,
|
|
|
|
Info = DOM.CurrentInfo,
|
|
Files = DOM.Files,
|
|
Storage = DOM.Storage,
|
|
exec = Util.exec,
|
|
join = CloudCmd.join,
|
|
FileName,
|
|
Value,
|
|
Edit = this,
|
|
Diff,
|
|
|
|
Menu,
|
|
|
|
Dialog = DOM.Dialog,
|
|
Images = DOM.Images,
|
|
Element,
|
|
ConfigView = {
|
|
beforeClose: function() {
|
|
isChanged();
|
|
exec.ifExist(Menu, 'hide');
|
|
},
|
|
afterShow: function() {
|
|
edward
|
|
.clearSelection()
|
|
.moveCursorTo(0, 0)
|
|
.focus();
|
|
}
|
|
};
|
|
|
|
function init(callback) {
|
|
var element = createElement();
|
|
|
|
element.addEventListener('contextmenu', setMenu);
|
|
|
|
exec.series([
|
|
CloudCmd.View,
|
|
function(callback) {
|
|
loadFiles(element, callback);
|
|
},
|
|
function(callback) {
|
|
DOM.loadSocket(initSocket);
|
|
callback();
|
|
},
|
|
function(callback) {
|
|
Edit.create(element)
|
|
.show(callback);
|
|
|
|
}, callback]);
|
|
}
|
|
|
|
function getHost() {
|
|
var l = location,
|
|
href = l.origin || l.protocol + '//' + l.host;
|
|
|
|
return href;
|
|
}
|
|
|
|
function initSocket(error) {
|
|
var socket,
|
|
href = getHost(),
|
|
FIVE_SECONDS = 5000,
|
|
patch = function(name, data) {
|
|
socket.emit('patch', name, data);
|
|
};
|
|
|
|
if (!error) {
|
|
socket = io.connect(href + '/edit', {
|
|
'max reconnection attempts' : Math.pow(2, 32),
|
|
'reconnection limit' : FIVE_SECONDS
|
|
});
|
|
|
|
socket.on('connect', function() {
|
|
Edit.save.patch = patch;
|
|
});
|
|
|
|
socket.on('message', function(msg) {
|
|
onSave(null, msg);
|
|
});
|
|
|
|
socket.on('patch', function(name, data, hash) {
|
|
if (name === FileName)
|
|
loadDiff(function(error) {
|
|
if (error)
|
|
console.error(error);
|
|
else
|
|
DOM.Storage.get(name + '-hash', function(error, hashLocal) {
|
|
var cursor, value;
|
|
|
|
if (hash === hashLocal) {
|
|
cursor = edward.getCursor(),
|
|
value = edward.getValue();
|
|
value = Diff.applyPatch(value, data);
|
|
|
|
edward.setValue(value);
|
|
|
|
edward.sha(function(error, hash) {
|
|
DOM.saveDataToStorage(name, value, hash);
|
|
edward
|
|
.clearSelection()
|
|
.moveCursorTo(cursor.row, cursor.column)
|
|
.scrollToLine(cursor.row, true);
|
|
});
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
socket.on('disconnect', function() {
|
|
Edit.save.patch = patchHttp;
|
|
});
|
|
|
|
socket.on('err', function(error) {
|
|
Dialog.alert(error);
|
|
});
|
|
}
|
|
}
|
|
|
|
function createElement() {
|
|
var element = DOM.load({
|
|
name : 'div',
|
|
style :
|
|
'width : 100%;' +
|
|
'height : 100%;' +
|
|
'font : 16px "Droid Sans Mono";' +
|
|
'position : absolute;',
|
|
notAppend : true
|
|
});
|
|
|
|
return element;
|
|
}
|
|
|
|
this.show = function(callback) {
|
|
var isDir = Info.isDir,
|
|
name = Info.name;
|
|
|
|
FileName = Info.path;
|
|
|
|
Images.show.load();
|
|
|
|
if (callback)
|
|
ConfigView.beforeShow = callback;
|
|
|
|
if (isDir)
|
|
edward.setMode('json');
|
|
else
|
|
edward.setModeForPath(name);
|
|
|
|
Info.getData(function(error, data) {
|
|
if (error) {
|
|
alert(error);
|
|
} else {
|
|
Edit.setValueFirst(data);
|
|
CloudCmd.View.show(Element, ConfigView);
|
|
}
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
this.setValueFirst = function(value) {
|
|
Value = value;
|
|
edward.setValueFirst(value);
|
|
};
|
|
|
|
this.hide = function() {
|
|
CloudCmd.View.hide();
|
|
};
|
|
|
|
this.goToLine = function() {
|
|
edward.goToLine();
|
|
};
|
|
|
|
function isChanged() {
|
|
var is,
|
|
value = edward.getValue(),
|
|
isEqual = value === Value,
|
|
msg = 'Do you want to save changes to ' + name + '?';
|
|
|
|
if (!isEqual) {
|
|
is = Dialog.confirm(msg);
|
|
|
|
if (is)
|
|
Edit.save();
|
|
}
|
|
}
|
|
|
|
this.create = function(element) {
|
|
Element = element;
|
|
|
|
edward.addCommand({
|
|
name : 'hide',
|
|
bindKey : { win: 'Esc', mac: 'Esc' },
|
|
exec : function () {
|
|
Edit.hide();
|
|
}
|
|
});
|
|
|
|
edward.addCommand({
|
|
name : 'goToLine',
|
|
bindKey : { win: 'Ctrl-G', mac: 'Command-G' },
|
|
exec : function () {
|
|
Edit.goToLine();
|
|
}
|
|
});
|
|
|
|
edward.addCommand({
|
|
name : 'save',
|
|
bindKey : { win: 'Ctrl-S', mac: 'Command-S' },
|
|
exec : function() {
|
|
Edit.save();
|
|
}
|
|
});
|
|
|
|
edward.addCommand({
|
|
name : 'saveMC',
|
|
bindKey : { win: 'F2', mac: 'F2' },
|
|
exec : function() {
|
|
Edit.save();
|
|
}
|
|
});
|
|
|
|
edward.addCommand({
|
|
name : 'beautify',
|
|
bindKey : { win: 'Ctrl-B', mac: 'Command-B' },
|
|
exec : function() {
|
|
Edit.beautify();
|
|
}
|
|
});
|
|
|
|
edward.addCommand({
|
|
name : 'minify',
|
|
bindKey : { win: 'Ctrl-M', mac: 'Command-M' },
|
|
exec : function() {
|
|
Edit.minify();
|
|
}
|
|
});
|
|
|
|
return this;
|
|
};
|
|
|
|
Edit.save = function() {
|
|
var value = edward.getValue();
|
|
|
|
Files.get('config', function(error, config) {
|
|
var isDiff = config.diff,
|
|
isZip = config.zip;
|
|
|
|
exec.if(!isDiff, function(patch) {
|
|
var query = '',
|
|
MAX_SIZE = CloudFunc.MAX_FILE_SIZE,
|
|
patchLength = patch && patch.length || 0,
|
|
length = Value.length,
|
|
isLessMaxLength = length < MAX_SIZE,
|
|
isLessLength = isLessMaxLength && patchLength < length,
|
|
isStr = typeof patch === 'string',
|
|
isPatch = patch && isStr && isLessLength;
|
|
|
|
Value = value;
|
|
|
|
exec.if(!isZip || isPatch, function(equal, data) {
|
|
var result = data || Value;
|
|
|
|
if (isPatch)
|
|
Edit.save.patch(FileName, patch);
|
|
else
|
|
Edit.save.write(FileName + query, result);
|
|
}, function(func) {
|
|
zip(value, function(error, data) {
|
|
if (error)
|
|
console.error(error);
|
|
|
|
query = '?unzip';
|
|
func(null, data);
|
|
});
|
|
});
|
|
|
|
}, exec.with(doDiff, FileName));
|
|
});
|
|
};
|
|
|
|
Edit.save.patch = patchHttp;
|
|
Edit.save.write = writeHttp;
|
|
|
|
function patchHttp(path, patch) {
|
|
restafary.patch(path, patch, onSave);
|
|
}
|
|
|
|
function writeHttp(path, result) {
|
|
restafary.write(path, result, onSave);
|
|
}
|
|
|
|
function doDiff(path, callback) {
|
|
var value = edward.getValue();
|
|
|
|
diff(value, function(patch) {
|
|
var isAllowed = Storage.isAllowed();
|
|
|
|
exec.if(!isAllowed, callback, function(func) {
|
|
DOM.checkStorageHash(path, function(error, equal) {
|
|
if (!equal)
|
|
patch = '';
|
|
|
|
func(patch);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function diff(newValue, callback) {
|
|
loadDiff(function(error) {
|
|
var patch,
|
|
isAllowed = Storage.isAllowed();
|
|
|
|
if (error) {
|
|
Dialog.alert(error);
|
|
} else {
|
|
exec.if(!isAllowed, function() {
|
|
patch = Diff.createPatch(Value, newValue);
|
|
exec(callback, patch);
|
|
}, function(func) {
|
|
DOM.getDataFromStorage(FileName, function(error, data) {
|
|
if (data)
|
|
Value = data;
|
|
|
|
func();
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
function loadDiff(callback) {
|
|
var url = join([
|
|
'/modules/google-diff-match-patch/diff_match_patch.js',
|
|
'/modules/daffy/lib/daffy.js'
|
|
]);
|
|
|
|
DOM.load.js(url, function(error) {
|
|
if (!error && !Diff)
|
|
Diff = window.daffy;
|
|
|
|
callback(error);
|
|
});
|
|
}
|
|
|
|
function zip(value, callback) {
|
|
var dir = CloudCmd.LIBDIRCLIENT,
|
|
url = dir + 'zip.js';
|
|
|
|
exec.parallel([
|
|
function(callback) {
|
|
DOM.load.js(url, callback);
|
|
},
|
|
function(callback) {
|
|
DOM.loadRemote('pako', callback);
|
|
}
|
|
], function(error) {
|
|
if (error)
|
|
alert(error);
|
|
else
|
|
Zip.pack(value, callback);
|
|
});
|
|
}
|
|
|
|
function loadFiles(element, callback) {
|
|
var dir = CloudCmd.LIBDIRCLIENT,
|
|
name = 'edward',
|
|
url = dir + name + '.js';
|
|
|
|
Util.time(Name + ' load');
|
|
|
|
DOM.load.js(url, function() {
|
|
Loading = false;
|
|
|
|
edward(element, function() {
|
|
Util.timeEnd(Name + ' load');
|
|
exec(callback);
|
|
});
|
|
});
|
|
}
|
|
|
|
function onSave(error, text) {
|
|
var ret,
|
|
size = Format.size(Value.length),
|
|
msg = '\nShould I save file anyway?';
|
|
|
|
if (error) {
|
|
ret = Dialog.confirm(text + msg);
|
|
|
|
if (ret)
|
|
restafary.write(FileName, Value, onSave);
|
|
} else {
|
|
Edit.showMessage(text);
|
|
|
|
edward.sha(function(error, hash) {
|
|
if (error)
|
|
console.error(error);
|
|
|
|
DOM.saveDataToStorage(FileName, Value, hash);
|
|
});
|
|
|
|
DOM.setCurrentSize(size);
|
|
}
|
|
}
|
|
|
|
function setMenu() {
|
|
if (!Menu) {
|
|
DOM.loadRemote('menu', function(error) {
|
|
var position = CloudCmd.MousePosition,
|
|
options = {
|
|
beforeShow: function(params) {
|
|
params.x -= 18;
|
|
params.y -= 27;
|
|
},
|
|
afterClick: function() {
|
|
edward.focus();
|
|
}
|
|
},
|
|
menuData = {
|
|
'Save Ctrl+S' : function() {
|
|
CloudCmd.Edit.save();
|
|
},
|
|
'Go To Line Ctrl+G' : function() {
|
|
CloudCmd.Edit.goToLine();
|
|
},
|
|
'Select All Ctrl+A' : function() {
|
|
edward.selectAll();
|
|
},
|
|
'Delete Del' : function() {
|
|
edward.remove('right');
|
|
},
|
|
'Beautify Ctrl+B' : function() {
|
|
CloudCmd.Edit.beautify();
|
|
},
|
|
'Minify Ctrl+M' : function() {
|
|
CloudCmd.Edit.minify();
|
|
},
|
|
'Close Esc' : CloudCmd.Edit.hide
|
|
};
|
|
|
|
if (error) {
|
|
alert(error);
|
|
} else if (!Menu) {
|
|
Menu = new MenuIO(Element, options, menuData);
|
|
Menu.show(position.x, position.y);
|
|
|
|
Element.removeEventListener('contextmenu', setMenu);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
Edit.beautify = function() {
|
|
readWithFlag('beautify');
|
|
};
|
|
|
|
Edit.minify = function() {
|
|
readWithFlag('minify');
|
|
};
|
|
|
|
function readWithFlag(flag) {
|
|
var path = FileName;
|
|
|
|
restafary.read(path + '?' + flag, function(error, data) {
|
|
if (error)
|
|
alert(error);
|
|
else
|
|
edward
|
|
.setValue(data)
|
|
.clearSelection()
|
|
.moveCursorTo(0, 0);
|
|
});
|
|
}
|
|
|
|
this.showMessage = function(text) {
|
|
edward.showMessage(text);
|
|
};
|
|
|
|
init(callback);
|
|
}
|
|
|
|
})(CloudCmd, Util, DOM, CloudFunc);
|