2015-01-01 05:06:33 +03:00
|
|
|
/*
|
2015-12-30 11:13:43 +03:00
|
|
|
* Copyright (c) 2014-2016, b3log.org & hacpai.com
|
2015-01-01 05:06:33 +03:00
|
|
|
*
|
2014-11-12 18:13:14 +03:00
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
2015-01-01 05:06:33 +03:00
|
|
|
*
|
2014-11-12 18:13:14 +03:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2015-01-01 05:06:33 +03:00
|
|
|
*
|
2014-11-12 18:13:14 +03:00
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
2014-11-17 06:37:26 +03:00
|
|
|
*/
|
2014-11-12 18:13:14 +03:00
|
|
|
|
2015-12-08 16:08:37 +03:00
|
|
|
/*
|
2015-12-08 18:48:16 +03:00
|
|
|
* @file session.js
|
2015-12-08 16:08:37 +03:00
|
|
|
*
|
|
|
|
* @author <a href="http://vanessa.b3log.org">Liyuan Li</a>
|
2015-12-08 18:48:16 +03:00
|
|
|
* @version 1.1.0.1, Dec 8, 2015
|
2015-12-08 16:08:37 +03:00
|
|
|
*/
|
2014-09-23 17:03:44 +04:00
|
|
|
var session = {
|
|
|
|
init: function () {
|
|
|
|
this._initWS();
|
|
|
|
|
2015-12-08 16:08:37 +03:00
|
|
|
var getLayoutState = function (paneState) {
|
|
|
|
var state = 'normal';
|
|
|
|
if (paneState.isClosed) {
|
|
|
|
state = 'min';
|
|
|
|
} else if (paneState.size >= $('body').width()) {
|
|
|
|
state = 'max';
|
|
|
|
}
|
|
|
|
|
|
|
|
return state;
|
|
|
|
};
|
|
|
|
|
2015-12-08 04:58:06 +03:00
|
|
|
// save session content every 30 seconds
|
2014-09-23 17:03:44 +04:00
|
|
|
setInterval(function () {
|
|
|
|
var request = newWideRequest(),
|
|
|
|
filse = [],
|
|
|
|
fileTree = [],
|
2014-10-17 10:47:29 +04:00
|
|
|
currentId = editors.getCurrentId(),
|
|
|
|
currentFile = currentId ? editors.getCurrentPath() : "";
|
2014-09-23 17:03:44 +04:00
|
|
|
|
|
|
|
editors.tabs.obj._$tabs.find("div").each(function () {
|
|
|
|
var $it = $(this);
|
2014-10-21 18:48:33 +04:00
|
|
|
if ($it.find("span:eq(0)").attr("title") !== config.label.start_page) {
|
2014-10-17 10:47:29 +04:00
|
|
|
filse.push($it.find("span:eq(0)").attr("title"));
|
2014-09-23 17:03:44 +04:00
|
|
|
}
|
|
|
|
});
|
2014-09-23 18:29:53 +04:00
|
|
|
|
2014-09-23 17:03:44 +04:00
|
|
|
fileTree = tree.getOpenPaths();
|
|
|
|
|
2015-03-11 08:52:14 +03:00
|
|
|
request.currentFile = currentFile; // current editor file
|
|
|
|
request.fileTree = fileTree; // file tree expansion state
|
|
|
|
request.files = filse; // editor tabs
|
2014-09-23 17:03:44 +04:00
|
|
|
|
2015-12-08 16:08:37 +03:00
|
|
|
|
|
|
|
request.layout = {
|
|
|
|
"side": {
|
|
|
|
"size": windows.outerLayout.west.state.size,
|
|
|
|
"state": getLayoutState(windows.outerLayout.west.state)
|
|
|
|
},
|
|
|
|
"sideRight": {
|
|
|
|
"size": windows.innerLayout.east.state.size,
|
|
|
|
"state": getLayoutState(windows.innerLayout.east.state)
|
|
|
|
},
|
|
|
|
"bottom": {
|
|
|
|
"size": windows.innerLayout.south.state.size,
|
|
|
|
"state": getLayoutState(windows.innerLayout.south.state)
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-23 17:03:44 +04:00
|
|
|
$.ajax({
|
|
|
|
type: 'POST',
|
2014-12-11 10:32:24 +03:00
|
|
|
url: config.context + '/session/save',
|
2014-09-23 17:03:44 +04:00
|
|
|
data: JSON.stringify(request),
|
|
|
|
dataType: "json",
|
2015-11-24 12:39:35 +03:00
|
|
|
success: function (result) {
|
2014-09-23 17:03:44 +04:00
|
|
|
}
|
|
|
|
});
|
2014-09-24 10:36:34 +04:00
|
|
|
}, 30000);
|
2014-09-23 17:03:44 +04:00
|
|
|
},
|
2014-09-23 18:29:53 +04:00
|
|
|
restore: function () {
|
2015-01-02 12:56:13 +03:00
|
|
|
if (!config.latestSessionContent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-12-08 18:48:16 +03:00
|
|
|
var fileTree = config.latestSessionContent.fileTree,
|
|
|
|
files = config.latestSessionContent.files,
|
|
|
|
currentFile = config.latestSessionContent.currentFile,
|
2014-09-23 18:29:53 +04:00
|
|
|
id = "",
|
|
|
|
nodesToOpen = [];
|
|
|
|
|
|
|
|
var nodes = tree.fileTree.transformToArray(tree.fileTree.getNodes());
|
|
|
|
|
|
|
|
for (var i = 0, ii = nodes.length; i < ii; i++) {
|
|
|
|
// expand tree
|
|
|
|
for (var j = 0, jj = fileTree.length; j < jj; j++) {
|
|
|
|
if (nodes[i].path === fileTree[j]) {
|
2015-03-11 08:52:14 +03:00
|
|
|
// expand this node only if its parents are open
|
2014-11-17 06:37:26 +03:00
|
|
|
var parents = tree.getAllParents(tree.fileTree.getNodeByTId(nodes[i].tId)),
|
|
|
|
isOpen = true;
|
|
|
|
for (var l = 0, max = parents.length; l < max; l++) {
|
|
|
|
if (parents[l].open === false) {
|
|
|
|
isOpen = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isOpen) {
|
|
|
|
tree.fileTree.expandNode(nodes[i], true, false, true);
|
|
|
|
} else {
|
2015-03-11 08:52:14 +03:00
|
|
|
// flag it is open
|
2014-11-17 06:37:26 +03:00
|
|
|
nodes[i].open = true;
|
|
|
|
}
|
2014-09-23 18:29:53 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// open editors
|
|
|
|
for (var k = 0, kk = files.length; k < kk; k++) {
|
|
|
|
if (nodes[i].path === files[k]) {
|
|
|
|
nodesToOpen.push(nodes[i]);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nodes[i].path === currentFile) {
|
2015-04-26 16:58:23 +03:00
|
|
|
id = nodes[i].path;
|
2014-11-17 06:37:26 +03:00
|
|
|
|
2014-11-02 18:04:43 +03:00
|
|
|
// FIXME: 上面的展开是异步进行的,所以执行到这里的时候可能还没有展开完,导致定位不了可视区域
|
|
|
|
tree.fileTree.selectNode(nodes[i]);
|
|
|
|
wide.curNode = nodes[i];
|
2014-09-23 18:29:53 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-11 08:52:14 +03:00
|
|
|
// handle the open sequence of editors
|
2014-09-23 18:29:53 +04:00
|
|
|
for (var m = 0, mm = files.length; m < mm; m++) {
|
|
|
|
for (var n = 0, nn = nodesToOpen.length; n < nn; n++) {
|
|
|
|
if (nodesToOpen[n].path === files[m]) {
|
2014-10-09 11:48:27 +04:00
|
|
|
tree.openFile(nodesToOpen[n]);
|
2014-09-23 18:29:53 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-11 08:52:14 +03:00
|
|
|
// set the current editor
|
2014-09-23 18:29:53 +04:00
|
|
|
editors.tabs.setCurrent(id);
|
2014-12-23 05:03:03 +03:00
|
|
|
for (var c = 0, max = editors.data.length; c < max; c++) {
|
|
|
|
if (id === editors.data[c].id) {
|
|
|
|
wide.curEditor = editors.data[c].editor;
|
|
|
|
break;
|
|
|
|
}
|
2015-12-08 16:08:37 +03:00
|
|
|
}
|
2014-09-23 18:29:53 +04:00
|
|
|
},
|
2014-09-23 17:03:44 +04:00
|
|
|
_initWS: function () {
|
2015-02-13 04:59:51 +03:00
|
|
|
// Used for session retention, server will release all resources of the session if this channel closed
|
2014-12-11 10:32:24 +03:00
|
|
|
var sessionWS = new ReconnectingWebSocket(config.channel + '/session/ws?sid=' + config.wideSessionId);
|
2014-09-23 17:03:44 +04:00
|
|
|
|
|
|
|
sessionWS.onopen = function () {
|
|
|
|
console.log('[session onopen] connected');
|
2014-11-02 10:44:24 +03:00
|
|
|
|
|
|
|
var dateFormat = function (time, fmt) {
|
|
|
|
var date = new Date(time);
|
|
|
|
var dateObj = {
|
2015-03-11 08:52:14 +03:00
|
|
|
"M+": date.getMonth() + 1,
|
|
|
|
"d+": date.getDate(),
|
|
|
|
"h+": date.getHours(),
|
|
|
|
"m+": date.getMinutes(),
|
|
|
|
"s+": date.getSeconds(),
|
|
|
|
"q+": Math.floor((date.getMonth() + 3) / 3),
|
2015-03-13 16:04:31 +03:00
|
|
|
"S": date.getMilliseconds()
|
2014-11-02 10:44:24 +03:00
|
|
|
};
|
|
|
|
if (/(y+)/.test(fmt))
|
|
|
|
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
|
|
|
|
for (var k in dateObj)
|
|
|
|
if (new RegExp("(" + k + ")").test(fmt)) {
|
|
|
|
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1)
|
|
|
|
? (dateObj[k]) : (("00" + dateObj[k]).substr(("" + dateObj[k]).length)));
|
|
|
|
}
|
|
|
|
return fmt;
|
|
|
|
};
|
|
|
|
|
|
|
|
var data = {type: "Network", severity: "INFO",
|
|
|
|
message: "Connected to server [sid=" + config.wideSessionId + "], " + dateFormat(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')},
|
|
|
|
$notification = $('.bottom-window-group .notification > table'),
|
|
|
|
notificationHTML = '';
|
|
|
|
|
|
|
|
notificationHTML += '<tr><td class="severity">' + data.severity
|
|
|
|
+ '</td><td class="message">' + data.message
|
|
|
|
+ '</td><td class="type">' + data.type + '</td></tr>';
|
|
|
|
$notification.append(notificationHTML);
|
2014-09-23 17:03:44 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
sessionWS.onmessage = function (e) {
|
2015-03-13 16:04:31 +03:00
|
|
|
var data = JSON.parse(e.data);
|
|
|
|
switch (data.cmd) {
|
|
|
|
case 'create-file':
|
2015-10-02 16:39:36 +03:00
|
|
|
var node = tree.fileTree.getNodeByTId(tree.getTIdByPath(data.dir)),
|
2015-09-27 06:02:48 +03:00
|
|
|
name = data.path.replace(data.dir + '/', ''),
|
|
|
|
mode = CodeMirror.findModeByFileName(name),
|
|
|
|
iconSkin = wide.getClassBySuffix(name.split(".")[1]);
|
|
|
|
|
2015-09-27 09:29:26 +03:00
|
|
|
if (data.type && data.type === 'f') {
|
2015-10-02 16:39:36 +03:00
|
|
|
tree.fileTree.addNodes(node, [{
|
2015-10-02 12:01:24 +03:00
|
|
|
"id": data.path,
|
2015-09-27 06:02:48 +03:00
|
|
|
"name": name,
|
|
|
|
"iconSkin": iconSkin,
|
|
|
|
"path": data.path,
|
|
|
|
"mode": mode,
|
|
|
|
"removable": true,
|
|
|
|
"creatable": true
|
|
|
|
}]);
|
|
|
|
|
|
|
|
} else {
|
2015-10-02 16:39:36 +03:00
|
|
|
tree.fileTree.addNodes(node, [{
|
2015-10-02 12:01:24 +03:00
|
|
|
"id": data.path,
|
2015-09-27 06:02:48 +03:00
|
|
|
"name": name,
|
|
|
|
"iconSkin": "ico-ztree-dir ",
|
|
|
|
"path": data.path,
|
|
|
|
"removable": true,
|
|
|
|
"creatable": true,
|
|
|
|
"isParent": true
|
|
|
|
}]);
|
|
|
|
}
|
2015-03-13 16:04:31 +03:00
|
|
|
break;
|
|
|
|
case 'remove-file':
|
2015-09-27 09:29:26 +03:00
|
|
|
case 'rename-file':
|
2015-12-08 16:08:37 +03:00
|
|
|
var node = tree.fileTree.getNodeByTId(tree.getTIdByPath(data.path));
|
2015-10-02 16:39:36 +03:00
|
|
|
tree.fileTree.removeNode(node);
|
|
|
|
|
2015-10-03 10:00:19 +03:00
|
|
|
var nodes = tree.fileTree.transformToArray(node);
|
|
|
|
for (var i = 0, ii = nodes.length; i < ii; i++) {
|
|
|
|
editors.tabs.del(nodes[i].path);
|
|
|
|
}
|
|
|
|
|
2015-03-13 16:04:31 +03:00
|
|
|
break;
|
|
|
|
}
|
2014-09-23 17:03:44 +04:00
|
|
|
};
|
|
|
|
sessionWS.onclose = function (e) {
|
|
|
|
console.log('[session onclose] disconnected (' + e.code + ')');
|
2014-11-02 10:44:24 +03:00
|
|
|
|
|
|
|
var data = {type: "Network", severity: "ERROR",
|
|
|
|
message: "Disconnected from server, trying to reconnect it [sid=" + config.wideSessionId + "]"},
|
|
|
|
$notification = $('.bottom-window-group .notification > table'),
|
|
|
|
notificationHTML = '';
|
|
|
|
|
|
|
|
notificationHTML += '<tr><td class="severity">' + data.severity
|
|
|
|
+ '</td><td class="message">' + data.message
|
|
|
|
+ '</td><td class="type">' + data.type + '</td></tr>';
|
|
|
|
$notification.append(notificationHTML);
|
|
|
|
|
|
|
|
$(".notification-count").show();
|
2014-09-23 17:03:44 +04:00
|
|
|
};
|
|
|
|
sessionWS.onerror = function (e) {
|
2015-09-27 02:36:34 +03:00
|
|
|
console.log('[session onerror]');
|
2014-09-23 17:03:44 +04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|