Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
475d5a414f
|
@ -27,6 +27,8 @@
|
|||
<ul>
|
||||
<li>Ctrl+1:焦点切换到文件树</li>
|
||||
<li>Ctrl+4:焦点切换到输出窗口</li>
|
||||
<li>Ctrl+5:焦点切换到搜索窗口</li>
|
||||
<li>Ctrl+6:焦点切换到通知窗口</li>
|
||||
</ul>
|
||||
|
||||
<h2>运行</h2>
|
||||
|
|
8
main.go
8
main.go
|
@ -40,7 +40,7 @@ func init() {
|
|||
// Wide 首页.
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// 创建一个 Wide 会话
|
||||
wideSession := user.NewSession()
|
||||
wideSession := user.WideSessions.New()
|
||||
|
||||
i18n.Load()
|
||||
|
||||
|
@ -54,7 +54,8 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
name := conf.Wide.Users[0].Name
|
||||
|
||||
httpSession.Values["username"] = name
|
||||
httpSession.Values["id"] = strconv.Itoa(rand.Int())
|
||||
httpSessionId := strconv.Itoa(rand.Int())
|
||||
httpSession.Values["id"] = httpSessionId
|
||||
// 一天过期
|
||||
httpSession.Options.MaxAge = 60 * 60 * 24
|
||||
|
||||
|
@ -63,6 +64,9 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
httpSession.Save(r, w)
|
||||
|
||||
// Wide 会话关联 HTTP 会话
|
||||
wideSession.HTTPSessionId = httpSession.Values["id"].(string)
|
||||
|
||||
t, err := template.ParseFiles("view/index.html")
|
||||
|
||||
if nil != err {
|
||||
|
|
|
@ -79,12 +79,11 @@ var editors = {
|
|||
--start;
|
||||
}
|
||||
|
||||
var request = {
|
||||
path: $(".edit-header .current > span:eq(0)").attr("title"),
|
||||
code: editor.getValue(),
|
||||
cursorLine: cur.line,
|
||||
cursorCh: cur.ch
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = $(".edit-header .current > span:eq(0)").attr("title");
|
||||
request.code = editor.getValue();
|
||||
request.cursorLine = cur.line;
|
||||
request.cursorCh = cur.ch;
|
||||
|
||||
var autocompleteHints = [];
|
||||
|
||||
|
@ -134,12 +133,11 @@ var editors = {
|
|||
CodeMirror.commands.jumpToDecl = function (cm) {
|
||||
var cur = wide.curEditor.getCursor();
|
||||
|
||||
var request = {
|
||||
path: $(".edit-header .current > span:eq(0)").attr("title"),
|
||||
code: wide.curEditor.getValue(),
|
||||
cursorLine: cur.line,
|
||||
cursorCh: cur.ch
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = $(".edit-header .current > span:eq(0)").attr("title");
|
||||
request.code = wide.curEditor.getValue();
|
||||
request.cursorLine = cur.line;
|
||||
request.cursorCh = cur.ch;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
@ -154,9 +152,8 @@ var editors = {
|
|||
var cursorLine = data.cursorLine;
|
||||
var cursorCh = data.cursorCh;
|
||||
|
||||
var request = {
|
||||
path: data.path
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = data.path;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
@ -186,12 +183,11 @@ var editors = {
|
|||
CodeMirror.commands.findUsages = function (cm) {
|
||||
var cur = wide.curEditor.getCursor();
|
||||
|
||||
var request = {
|
||||
file: wide.curNode.path,
|
||||
code: wide.curEditor.getValue(),
|
||||
cursorLine: cur.line,
|
||||
cursorCh: cur.ch
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = wide.curNode.path;
|
||||
request.code = wide.curEditor.getValue();
|
||||
request.cursorLine = cur.line;
|
||||
request.cursorCh = cur.ch;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
|
|
@ -69,10 +69,10 @@ var tree = {
|
|||
return false;
|
||||
}
|
||||
|
||||
var request = {
|
||||
path: wide.curNode.path + '\\' + name,
|
||||
fileType: "f"
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = wide.curNode.path + '\\' + name;
|
||||
request.fileType = "f";
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/file/new',
|
||||
|
@ -133,10 +133,10 @@ var tree = {
|
|||
return false;
|
||||
}
|
||||
|
||||
var request = {
|
||||
path: wide.curNode.path + '\\' + name,
|
||||
fileType: "d"
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = wide.curNode.path + '\\' + name;
|
||||
request.fileType = "d";
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/file/new',
|
||||
|
@ -161,9 +161,10 @@ var tree = {
|
|||
if (!confirm("Remove it?")) {
|
||||
return;
|
||||
}
|
||||
var request = {
|
||||
path: wide.curNode.path
|
||||
};
|
||||
|
||||
var request = newWideRequest();
|
||||
request.path = wide.curNode.path;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/file/remove',
|
||||
|
@ -197,9 +198,12 @@ var tree = {
|
|||
});
|
||||
},
|
||||
init: function () {
|
||||
var request = newWideRequest();
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
type: 'POST',
|
||||
url: '/files',
|
||||
data: JSON.stringify(request),
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data.succ) {
|
||||
|
@ -256,9 +260,9 @@ var tree = {
|
|||
wide.curNode = treeNode;
|
||||
|
||||
if ("ico-ztree-dir " !== treeNode.iconSkin) { // 如果单击了文件
|
||||
var request = {
|
||||
path: treeNode.path
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.path = treeNode.path;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/file',
|
||||
|
|
|
@ -12,9 +12,8 @@ outputWS.onmessage = function(e) {
|
|||
}
|
||||
|
||||
if ('run' === data.nextCmd) {
|
||||
var request = {
|
||||
executable: data.executable
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.executable = data.executable;
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
@ -101,10 +100,10 @@ var wide = {
|
|||
|
||||
},
|
||||
saveFile: function() {
|
||||
var request = {
|
||||
file: $(".edit-header .current span:eq(0)").attr("title"),
|
||||
code: wide.curEditor.getValue()
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = $(".edit-header .current span:eq(0)").attr("title");
|
||||
request.code = wide.curEditor.getValue();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: '/file/save',
|
||||
|
@ -128,10 +127,9 @@ var wide = {
|
|||
},
|
||||
// 构建 & 运行.
|
||||
run: function() {
|
||||
var request = {
|
||||
file: $(".edit-header .current span:eq(0)").attr("title"),
|
||||
code: wide.curEditor.getValue()
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = $(".edit-header .current span:eq(0)").attr("title");
|
||||
request.code = wide.curEditor.getValue();
|
||||
|
||||
// TODO: 修改 [构建&运行] 图标状态为不可用状态
|
||||
|
||||
|
@ -148,9 +146,8 @@ var wide = {
|
|||
});
|
||||
},
|
||||
goget: function() {
|
||||
var request = {
|
||||
file: $(".edit-header .current span:eq(0)").attr("title")
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = $(".edit-header .current span:eq(0)").attr("title");
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
@ -165,10 +162,9 @@ var wide = {
|
|||
});
|
||||
},
|
||||
goinstall: function() {
|
||||
var request = {
|
||||
file: $(".edit-header .current span:eq(0)").attr("title"),
|
||||
code: wide.curEditor.getValue()
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = $(".edit-header .current span:eq(0)").attr("title");
|
||||
request.code = wide.curEditor.getValue();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
|
@ -186,12 +182,11 @@ var wide = {
|
|||
var path = $(".edit-header .current span:eq(0)").attr("title");
|
||||
var mode = wide.curNode.mode;
|
||||
|
||||
var request = {
|
||||
file: path,
|
||||
code: wide.curEditor.getValue(),
|
||||
cursorLine: wide.curEditor.getCursor().line,
|
||||
cursorCh: wide.curEditor.getCursor().ch
|
||||
};
|
||||
var request = newWideRequest();
|
||||
request.file = path;
|
||||
request.code = wide.curEditor.getValue();
|
||||
request.cursorLine = wide.curEditor.getCursor().line;
|
||||
request.cursorCh = wide.curEditor.getCursor().ch;
|
||||
|
||||
switch (mode) {
|
||||
case "text/x-go":
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/gorilla/sessions"
|
||||
)
|
||||
|
||||
|
@ -18,22 +19,54 @@ var Session = sessions.NewCookieStore([]byte("BEYOND"))
|
|||
// Wide 会话,对应一个浏览器 tab.
|
||||
type WideSession struct {
|
||||
Id string // 唯一标识
|
||||
HTTPSessionId string // HTTP 会话 id
|
||||
State int // 状态
|
||||
Created time.Time // 创建时间
|
||||
Updated time.Time // 最近一次使用时间
|
||||
}
|
||||
|
||||
type Sessions []*WideSession
|
||||
|
||||
// 所有 Wide 会话集.
|
||||
var WideSessions Sessions
|
||||
|
||||
// 创建一个 Wide 会话.
|
||||
func NewSession() *WideSession {
|
||||
func (sessions *Sessions) New() *WideSession {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
|
||||
id := strconv.Itoa(rand.Int())
|
||||
now := time.Now()
|
||||
|
||||
return &WideSession{
|
||||
ret := &WideSession{
|
||||
Id: id,
|
||||
State: SessionStateActive,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
}
|
||||
|
||||
*sessions = append(*sessions, ret)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// 移除 Wide 会话.
|
||||
func (sessions *Sessions) Remove(sid string) {
|
||||
for i, s := range *sessions {
|
||||
if s.Id == sid {
|
||||
*sessions = append((*sessions)[:i], (*sessions)[i+1:]...)
|
||||
|
||||
glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除 HTTP 会话关联的所有 Wide 会话.
|
||||
func (sessions *Sessions) RemoveByHTTPSid(httpSessionId string) {
|
||||
for i, s := range *sessions {
|
||||
if s.HTTPSessionId == httpSessionId {
|
||||
*sessions = append((*sessions)[:i], (*sessions)[i+1:]...)
|
||||
|
||||
glog.V(3).Infof("Has [%d] wide sessions currently", len(*sessions))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{{.i18n.wide}} - {{.session.Id}}</title>
|
||||
<title>{{.i18n.wide}}</title>
|
||||
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/codemirror.css">
|
||||
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/hint/show-hint.css">
|
||||
<link rel="stylesheet" href="{{.conf.StaticServer}}/static/js/lib/codemirror-4.5/addon/lint/lint.css">
|
||||
|
@ -168,11 +168,22 @@
|
|||
<script type="text/javascript">
|
||||
var config = {
|
||||
channel: {
|
||||
editor: '{{.conf.EditorChannel}}',
|
||||
shell: '{{.conf.ShellChannel}}',
|
||||
output: '{{.conf.OutputChannel}}'
|
||||
editor: {{.conf.EditorChannel}},
|
||||
shell: {{.conf.ShellChannel}},
|
||||
output: {{.conf.OutputChannel}}
|
||||
},
|
||||
wideSessionId: {{.session.Id}}
|
||||
};
|
||||
// 发往 Wide 的所有 AJAX 请求需要使用该函数创建请求参数.
|
||||
function newWideRequest() {
|
||||
var ret = {
|
||||
sid: config.wideSessionId
|
||||
}
|
||||
};</script>
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/jquery-2.1.1.min.js"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/reconnecting-websocket.js"></script>
|
||||
<script type="text/javascript" src="{{.conf.StaticServer}}/static/js/lib/ztree/jquery.ztree.all-3.5.min.js"></script>
|
||||
|
|
Loading…
Reference in New Issue