Added the Online Users Context widget.
Commented out a couple lines of debug code. Fixed a data race where the Online Users widget would sometimes show more users than it should. Added a new phrase.
This commit is contained in:
parent
dc8079f581
commit
89a5eafa48
|
@ -34,6 +34,7 @@ var errWsNouser = errors.New("This user isn't connected via WebSockets")
|
|||
func init() {
|
||||
adminStatsWatchers = make(map[*websocket.Conn]*WSUser)
|
||||
topicListWatchers = make(map[*WSUser]bool)
|
||||
topicWatchers = make(map[int]map[*WSUser]bool)
|
||||
}
|
||||
|
||||
type WsTopicList struct {
|
||||
|
@ -122,6 +123,7 @@ func wsPageResponses(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
topicListMutex.Lock()
|
||||
topicListWatchers[wsUser] = true
|
||||
topicListMutex.Unlock()
|
||||
// TODO: Evict from page when permissions change? Or check user perms every-time before sending data?
|
||||
case strings.HasPrefix(page, "/topic/"):
|
||||
//fmt.Println("entering topic prefix websockets zone")
|
||||
_, tid, err := ParseSEOURL(page)
|
||||
|
@ -132,13 +134,12 @@ func wsPageResponses(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
if err != nil {
|
||||
return
|
||||
}
|
||||
var usercpy *User = BlankUser()
|
||||
*usercpy = *wsUser.User
|
||||
usercpy.Init()
|
||||
|
||||
if !Forums.Exists(topic.ParentID) {
|
||||
return
|
||||
}
|
||||
var usercpy *User = BlankUser()
|
||||
*usercpy = *wsUser.User
|
||||
usercpy.Init()
|
||||
|
||||
/*skip, rerr := header.Hooks.VhookSkippable("ws_topic_check_pre_perms", w, r, usercpy, &fid, &header)
|
||||
if skip || rerr != nil {
|
||||
|
@ -155,6 +156,14 @@ func wsPageResponses(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
if !usercpy.Perms.ViewTopic {
|
||||
return
|
||||
}
|
||||
|
||||
topicMutex.Lock()
|
||||
_, ok := topicWatchers[topic.ID]
|
||||
if !ok {
|
||||
topicWatchers[topic.ID] = make(map[*WSUser]bool)
|
||||
}
|
||||
topicWatchers[topic.ID][wsUser] = true
|
||||
topicMutex.Unlock()
|
||||
case page == "/panel/":
|
||||
if !wsUser.User.IsSuperMod {
|
||||
return
|
||||
|
@ -180,9 +189,7 @@ func wsPageResponses(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
func wsLeavePage(wsUser *WSUser, conn *websocket.Conn, page string) {
|
||||
if page == "/" {
|
||||
page = Config.DefaultPath
|
||||
}
|
||||
|
||||
if page != "" {
|
||||
} else if page != "" {
|
||||
DebugLog("Leaving page " + page)
|
||||
}
|
||||
switch {
|
||||
|
@ -194,6 +201,26 @@ func wsLeavePage(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
})
|
||||
case strings.HasPrefix(page, "/topic/"):
|
||||
//fmt.Println("leaving topic prefix websockets zone")
|
||||
wsUser.FinalizePage(page, func() {
|
||||
_, tid, err := ParseSEOURL(page)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
topicMutex.Lock()
|
||||
defer topicMutex.Unlock()
|
||||
topic, ok := topicWatchers[tid]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
_, ok = topic[wsUser]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
delete(topic, wsUser)
|
||||
if len(topic) == 0 {
|
||||
delete(topicWatchers, tid)
|
||||
}
|
||||
})
|
||||
case page == "/panel/":
|
||||
adminStatsMutex.Lock()
|
||||
delete(adminStatsWatchers, conn)
|
||||
|
@ -209,6 +236,8 @@ func wsLeavePage(wsUser *WSUser, conn *websocket.Conn, page string) {
|
|||
// TODO: Use odd-even sharding
|
||||
var topicListWatchers map[*WSUser]bool
|
||||
var topicListMutex sync.RWMutex
|
||||
var topicWatchers map[int]map[*WSUser]bool // map[tid]watchers
|
||||
var topicMutex sync.RWMutex
|
||||
var adminStatsWatchers map[*websocket.Conn]*WSUser
|
||||
var adminStatsMutex sync.RWMutex
|
||||
|
||||
|
|
|
@ -25,6 +25,9 @@ func wolBuild(widget *Widget, hvars interface{}) (string, error) {
|
|||
var users []*User
|
||||
if ucount < 30 {
|
||||
users = WsHub.AllUsers()
|
||||
if len(users) >= 30 {
|
||||
users = nil
|
||||
}
|
||||
}
|
||||
wol := &wolUsers{hvars.(*Header), phrases.GetTmplPhrase("widget.online_name"), users, ucount}
|
||||
err := wol.Header.Theme.RunTmpl("widget_online", wol, wol.Header.Writer)
|
||||
|
|
|
@ -3,13 +3,24 @@ package common
|
|||
import "github.com/Azareal/Gosora/common/phrases"
|
||||
|
||||
func wolContextRender(widget *Widget, hvars interface{}) (string, error) {
|
||||
ucount := WsHub.UserCount()
|
||||
// We don't want a ridiculously long list, so we'll show the number if it's too high and only show staff individually
|
||||
var users []*User
|
||||
if ucount < 30 {
|
||||
users = WsHub.AllUsers()
|
||||
header := hvars.(*Header)
|
||||
if header.Zone != "view_topic" {
|
||||
return "", nil
|
||||
}
|
||||
wol := &wolUsers{hvars.(*Header), phrases.GetTmplPhrase("widget.online_name"), users, ucount}
|
||||
err := wol.Header.Theme.RunTmpl("widget_online", wol, wol.Header.Writer)
|
||||
var ucount int
|
||||
var users []*User
|
||||
topicMutex.RLock()
|
||||
topic, ok := topicWatchers[header.ZoneID]
|
||||
if ok {
|
||||
ucount = len(topic)
|
||||
if ucount < 30 {
|
||||
for wsUser, _ := range topic {
|
||||
users = append(users, wsUser.User)
|
||||
}
|
||||
}
|
||||
}
|
||||
topicMutex.RUnlock()
|
||||
wol := &wolUsers{header, phrases.GetTmplPhrase("widget.online_view_topic_name"), users, ucount}
|
||||
err := header.Theme.RunTmpl("widget_online", wol, header.Writer)
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -669,6 +669,7 @@
|
|||
"widget.online_name":"Online Users",
|
||||
"widget.online_none_online":"No one is online.",
|
||||
"widget.online_some_online":"There are %d users online.",
|
||||
"widget.online_view_topic_name":"In Topic",
|
||||
|
||||
"option_yes":"Yes",
|
||||
"option_no":"No",
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -386,7 +385,7 @@ func widgetsParseInputs(r *http.Request, widget *common.Widget) (*common.WidgetE
|
|||
return nil, errors.New("You need to fill in the body for this widget.")
|
||||
}
|
||||
widget.Type = wtype // ? - Are we sure we should be directly assigning user provided data even if it's validated?
|
||||
case "wol", "search_and_filter":
|
||||
case "wol", "wol_context", "search_and_filter":
|
||||
widget.Type = wtype // ? - Are we sure we should be directly assigning user provided data even if it's validated?
|
||||
default:
|
||||
return nil, errors.New("Unknown widget type")
|
||||
|
@ -397,7 +396,7 @@ func widgetsParseInputs(r *http.Request, widget *common.Widget) (*common.WidgetE
|
|||
|
||||
// ThemesWidgetsEditSubmit is an action which is triggered when someone sends an update request for a widget
|
||||
func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user common.User, swid string) common.RouteError {
|
||||
fmt.Println("in ThemesWidgetsEditSubmit")
|
||||
//fmt.Println("in ThemesWidgetsEditSubmit")
|
||||
_, ferr := common.SimplePanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
return ferr
|
||||
|
@ -434,7 +433,7 @@ func ThemesWidgetsEditSubmit(w http.ResponseWriter, r *http.Request, user common
|
|||
|
||||
// ThemesWidgetsCreateSubmit is an action which is triggered when someone sends a create request for a widget
|
||||
func ThemesWidgetsCreateSubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||
fmt.Println("in ThemesWidgetsCreateSubmit")
|
||||
//fmt.Println("in ThemesWidgetsCreateSubmit")
|
||||
isJs := (r.PostFormValue("js") == "1")
|
||||
_, ferr := common.SimplePanelUserCheck(w, r, &user)
|
||||
if ferr != nil {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<option value="about"{{if eq .Type "about"}} selected{{end}}>{{lang "panel_themes_widgets_type_about"}}</option>
|
||||
<option value="simple"{{if eq .Type "simple"}} selected{{end}}>{{lang "panel_themes_widgets_type_simple"}}</option>
|
||||
<option value="wol"{{if eq .Type "wol"}} selected{{end}}>{{lang "panel_themes_widgets_type_wol"}}</option>
|
||||
<!--<option value="wol_context"{{if eq .Type "wol_context"}} selected{{end}}>{{lang "panel_themes_widgets_type_wol_context"}}</option>-->
|
||||
<option value="wol_context"{{if eq .Type "wol_context"}} selected{{end}}>{{lang "panel_themes_widgets_type_wol_context"}}</option>
|
||||
<!--<option value="search_and_filter"{{if eq .Type "search_and_filter"}} selected{{end}}>{{lang "panel_themes_widgets_type_search_and_filter"}}</option>-->
|
||||
</select>
|
||||
</div>
|
||||
|
|
Loading…
Reference in New Issue