diff --git a/conf/wide.go b/conf/wide.go index 91b4f18..9ec73aa 100644 --- a/conf/wide.go +++ b/conf/wide.go @@ -44,7 +44,6 @@ var rawWide conf func CheckEnv() { go func() { for { - if "" == os.Getenv("GOPATH") { glog.Fatal("Not found $GOPATH") os.Exit(-1) @@ -60,7 +59,7 @@ func CheckEnv() { cmd := exec.Command(gocode, "close") _, err := cmd.Output() if nil != err { - event.EventQueue <- event.EvtGocodeNotFount + event.EventQueue <- event.EvtCodeGocodeNotFound glog.Warningf("Not found gocode [%s]", gocode) } @@ -68,11 +67,12 @@ func CheckEnv() { cmd = exec.Command(ide_stub, "version") _, err = cmd.Output() if nil != err { - event.EventQueue <- event.EvtIDEStubNotFound + event.EventQueue <- event.EvtCodeIDEStubNotFound glog.Warningf("Not found ide_stub [%s]", ide_stub) } - time.Sleep(time.Second * 2) + // 7 分钟进行一次检查 + time.Sleep(time.Minute * 7) } }() } diff --git a/event/events.go b/event/events.go index 8e86c6c..d7dd0e1 100644 --- a/event/events.go +++ b/event/events.go @@ -4,23 +4,31 @@ package event import "github.com/golang/glog" const ( - EvtGOPATHNotFound = iota // 事件:找不到环境变量 $GOPATH - EvtGOROOTNotFound // 事件:找不到环境变量 $GOROOT - EvtGocodeNotFount // 事件:找不到 gocode - EvtIDEStubNotFound // 事件:找不到 IDE stub - + EvtCodeGOPATHNotFound = iota // 事件代码:找不到环境变量 $GOPATH + EvtCodeGOROOTNotFound // 事件代码:找不到环境变量 $GOROOT + EvtCodeGocodeNotFound // 事件代码:找不到 gocode + EvtCodeIDEStubNotFound // 事件代码:找不到 IDE stub ) +// 事件队列最大长度. const MaxQueueLength = 10 +// 事件结构. +type Event struct { + Code int `json:"code"` // 事件代码 + Sid string `json:"sid"` // 用户会话 id +} + // 全局事件队列. // 入队的事件将分发到每个用户的通知队列. var EventQueue = make(chan int, MaxQueueLength) // 用户事件队列. -// 入队的事件将翻译为通知,并通过通知通道推送到前端. var UserEventQueues = map[string]chan int{} +// 用户事件处理器集. +var UserEventHandlers = map[string]*Handlers{} + // 加载事件处理. func Load() { go func() { @@ -35,21 +43,51 @@ func Load() { }() } -// 添加一个用户事件队列. -func InitUserQueue(sid string) { +// 初始化一个用户事件队列. +func InitUserQueue(sid string, handlers ...Handler) { // FIXME: 会话过期后需要销毁对应的用户事件队列 q := UserEventQueues[sid] if nil != q { - close(q) + return } q = make(chan int, MaxQueueLength) UserEventQueues[sid] = q + if nil == UserEventHandlers[sid] { + UserEventHandlers[sid] = new(Handlers) + } + + for _, handler := range handlers { + UserEventHandlers[sid].add(handler) + } + go func() { - for event := range q { - glog.Infof("Session [%s] received a event [%d]", sid, event) + for evtCode := range q { + glog.V(5).Infof("Session [%s] received a event [%d]", sid, evtCode) + + // 将事件交给事件处理器进行处理 + for _, handler := range *UserEventHandlers[sid] { + e := Event{Code: evtCode, Sid: sid} + handler.Handle(&e) + } } }() } + +type Handler interface { + Handle(event *Event) +} + +type HandleFunc func(event *Event) + +func (fn HandleFunc) Handle(event *Event) { + fn(event) +} + +type Handlers []Handler + +func (handlers *Handlers) add(handler Handler) { + *handlers = append(*handlers, handler) +} diff --git a/file/files.go b/file/files.go index 5525446..5e12ce4 100644 --- a/file/files.go +++ b/file/files.go @@ -272,7 +272,7 @@ func listFiles(dirname string) []string { func getIconSkin(filenameExtension string) string { switch filenameExtension { - case ".gitignore", "", ".exe", ".s": + case ".gitignore", "", ".exe", ".s", ".tar", ".zip", ".rar", ".gz": // 不支持显示图标的文件 return "ico-ztree-other " case ".json", ".js": return "ico-ztree-js " diff --git a/i18n/zh_CN.json b/i18n/zh_CN.json index befba62..8112138 100644 --- a/i18n/zh_CN.json +++ b/i18n/zh_CN.json @@ -21,5 +21,7 @@ "goget": "go get", "goinstall": "go install", "build_n_run": "构建 & 运行", - "full_screen": "全屏" + "full_screen": "全屏", + "notification_2": "没有检查到 gocode,这将会导致 [自动完成] 失效", + "notification_3": "没有检查到 ide_stub,这将会导致 [跳转到声明]、[查找使用] 失效" } \ No newline at end of file diff --git a/notification/notifications.go b/notification/notifications.go index f4c19b6..5ab9696 100644 --- a/notification/notifications.go +++ b/notification/notifications.go @@ -8,52 +8,83 @@ import ( "runtime" "time" + "strconv" "github.com/b3log/wide/conf" "github.com/b3log/wide/event" + "github.com/b3log/wide/i18n" "github.com/b3log/wide/user" "github.com/golang/glog" "github.com/gorilla/websocket" ) +const ( + Error = "ERROR" // 通知.严重程度:ERROR + Warn = "WARN" // 通知.严重程度:WARN + Info = "INFO" // 通知.严重程度:INFO + + Setup = "Setup" // 通知.类型:安装 +) + // 通知结构. type Notification struct { - Event int - Type string - Severity string // ERROR/WARN/INFO - Message string + event *event.Event + Type string `json:"type"` + Severity string `json:"severity"` + Message string `json:"message"` } // 一个用户会话的 WebSocket 通道结构. type WSChannel struct { - Conn *websocket.Conn // WebSocket 连接 - Time time.Time // 该通道最近一次使用时间 + Conn *websocket.Conn // WebSocket 连接 + Request *http.Request // 关联的 HTTP 请求 + Time time.Time // 该通道最近一次使用时间 } // 通知通道. -// , }> -var notificationWSs = map[string]map[string]WSChannel{} +// +var notificationWSs = map[string]*WSChannel{} + +func event2Notification(e *event.Event) { + if nil == notificationWSs[e.Sid] { + return + } + + wsChannel := notificationWSs[e.Sid] + + var notification Notification + + switch e.Code { + case event.EvtCodeGocodeNotFound: + notification = Notification{event: e, Type: Setup, Severity: Error} + case event.EvtCodeIDEStubNotFound: + notification = Notification{event: e, Type: Setup, Severity: Error} + default: + glog.Warningf("Can't handle event[code=%d]", e.Code) + return + } + + msgs := i18n.GetLangs(wsChannel.Request) + notification.Message = msgs["notification_"+strconv.Itoa(e.Code)].(string) + + wsChannel.Conn.WriteJSON(¬ification) +} func WSHandler(w http.ResponseWriter, r *http.Request) { session, _ := user.Session.Get(r, "wide-session") - username := session.Values["username"].(string) sid := session.Values["id"].(string) conn, _ := websocket.Upgrade(w, r, nil, 1024, 1024) - wsChan := WSChannel{Conn: conn, Time: time.Now()} + wsChan := WSChannel{Conn: conn, Request: r, Time: time.Now()} - wsChans := notificationWSs[username] - if nil == wsChans { - wsChans = map[string]WSChannel{} - } - - wsChans[sid] = wsChan + notificationWSs[sid] = &wsChan ret := map[string]interface{}{"output": "Notification initialized", "cmd": "init-notification"} wsChan.Conn.WriteJSON(&ret) - glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(wsChans)) + glog.Infof("Open a new [Notification] with session [%s], %d", sid, len(notificationWSs)) - event.InitUserQueue(sid) + // 初始化用户事件队列 + event.InitUserQueue(sid, event.HandleFunc(event2Notification)) input := map[string]interface{}{}