Refactored the client-side alert logic.
Exported WsHubImpl's PushMessage method. Fixed a bug in WSUser's WriteAll and WriteToPage methods where they wouldn't skip over the nil sockets.
This commit is contained in:
parent
e22a96f53e
commit
3822fe12d2
|
@ -322,7 +322,7 @@ func (hub *WsHubImpl) RemoveConn(wsUser *WSUser, conn *websocket.Conn) {
|
||||||
wsUser.Unlock()
|
wsUser.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hub *WsHubImpl) pushMessage(targetUser int, msg string) error {
|
func (hub *WsHubImpl) PushMessage(targetUser int, msg string) error {
|
||||||
wsUser, err := hub.getUser(targetUser)
|
wsUser, err := hub.getUser(targetUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -23,6 +23,9 @@ type WSUserSocket struct {
|
||||||
func (wsUser *WSUser) WriteAll(msg string) error {
|
func (wsUser *WSUser) WriteAll(msg string) error {
|
||||||
msgbytes := []byte(msg)
|
msgbytes := []byte(msg)
|
||||||
for _, socket := range wsUser.Sockets {
|
for _, socket := range wsUser.Sockets {
|
||||||
|
if socket == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
w, err := socket.conn.NextWriter(websocket.TextMessage)
|
w, err := socket.conn.NextWriter(websocket.TextMessage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -41,6 +44,9 @@ func (wsUser *WSUser) WriteToPage(msg string, page string) error {
|
||||||
func (wsUser *WSUser) WriteToPageBytes(msg []byte, page string) error {
|
func (wsUser *WSUser) WriteToPageBytes(msg []byte, page string) error {
|
||||||
var success bool
|
var success bool
|
||||||
for _, socket := range wsUser.Sockets {
|
for _, socket := range wsUser.Sockets {
|
||||||
|
if socket == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if socket.Page != page {
|
if socket.Page != page {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
185
public/global.js
185
public/global.js
|
@ -1,5 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
var formVars = {};
|
var formVars = {};
|
||||||
|
var alertMapping = {};
|
||||||
var alertList = [];
|
var alertList = [];
|
||||||
var alertCount = 0;
|
var alertCount = 0;
|
||||||
var moreTopicCount = 0;
|
var moreTopicCount = 0;
|
||||||
|
@ -26,7 +27,6 @@ function postLink(event)
|
||||||
{
|
{
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let formAction = $(event.target).closest('a').attr("href");
|
let formAction = $(event.target).closest('a').attr("href");
|
||||||
//console.log("Form Action: " + formAction);
|
|
||||||
$.ajax({ url: formAction, type: "POST", dataType: "json", error: ajaxError, data: {js: "1"} });
|
$.ajax({ url: formAction, type: "POST", dataType: "json", error: ajaxError, data: {js: "1"} });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,60 +37,88 @@ function bindToAlerts() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var alertsInitted = false;
|
function addAlert(msg, notice = false) {
|
||||||
// TODO: Add the ability for users to dismiss alerts
|
var mmsg = msg.msg;
|
||||||
function loadAlerts(menuAlerts)
|
if("sub" in msg) {
|
||||||
{
|
for(var i = 0; i < msg.sub.length; i++) {
|
||||||
if(!alertsInitted) return;
|
mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var alertListNode = menuAlerts.getElementsByClassName("alertList")[0];
|
let aItem = Template_alert({
|
||||||
var alertCounterNode = menuAlerts.getElementsByClassName("alert_counter")[0];
|
ASID: msg.asid,
|
||||||
|
Path: msg.path,
|
||||||
|
Avatar: msg.avatar || "",
|
||||||
|
Message: mmsg
|
||||||
|
})
|
||||||
|
|
||||||
|
alertMapping[msg.asid] = aItem;
|
||||||
|
alertList.push(msg.asid);
|
||||||
|
if(alertList.length > 8) alertList.shift();
|
||||||
|
|
||||||
|
if(notice) {
|
||||||
|
// TODO: Add some sort of notification queue to avoid flooding the end-user with notices?
|
||||||
|
// TODO: Use the site name instead of "Something Happened"
|
||||||
|
if(Notification.permission === "granted") {
|
||||||
|
var n = new Notification("Something Happened",{
|
||||||
|
body: mmsg,
|
||||||
|
icon: msg.avatar,
|
||||||
|
});
|
||||||
|
setTimeout(n.close.bind(n), 8000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runInitHook("after_add_alert");
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateAlertList(menuAlerts) {
|
||||||
|
let alertListNode = menuAlerts.getElementsByClassName("alertList")[0];
|
||||||
|
let alertCounterNode = menuAlerts.getElementsByClassName("alert_counter")[0];
|
||||||
alertCounterNode.textContent = "0";
|
alertCounterNode.textContent = "0";
|
||||||
|
|
||||||
|
let outList = "";
|
||||||
|
let j = 0;
|
||||||
|
for(var i = 0; i < alertList.length && j < 8; i++) {
|
||||||
|
outList += alertMapping[alertList[i]];
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(outList == "") outList = "<div class='alertItem'>You don't have any alerts</div>";
|
||||||
|
alertListNode.innerHTML = outList;
|
||||||
|
|
||||||
|
if(alertCount != 0) {
|
||||||
|
alertCounterNode.textContent = alertCount;
|
||||||
|
menuAlerts.classList.add("has_alerts");
|
||||||
|
} else {
|
||||||
|
menuAlerts.classList.remove("has_alerts");
|
||||||
|
}
|
||||||
|
|
||||||
|
bindToAlerts();
|
||||||
|
runInitHook("after_update_alert_list");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setAlertError(menuAlerts,msg) {
|
||||||
|
let alertListNode = menuAlerts.getElementsByClassName("alertList")[0];
|
||||||
|
alertListNode.innerHTML = "<div class='alertItem'>"+msg+"</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
var alertsInitted = false;
|
||||||
|
function loadAlerts(menuAlerts) {
|
||||||
|
if(!alertsInitted) return;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'get',
|
type: 'get',
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
url:'/api/?action=get&module=alerts',
|
url:'/api/?action=get&module=alerts',
|
||||||
success: (data) => {
|
success: (data) => {
|
||||||
if("errmsg" in data) {
|
if("errmsg" in data) {
|
||||||
alertListNode.innerHTML = "<div class='alertItem'>"+data.errmsg+"</div>";
|
setAlertError(menuAlerts,data.errmsg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var alist = "";
|
|
||||||
for(var i in data.msgs) {
|
for(var i in data.msgs) {
|
||||||
var msg = data.msgs[i];
|
addAlert(data.msgs[i]);
|
||||||
var mmsg = msg.msg;
|
|
||||||
if("sub" in msg) {
|
|
||||||
for(var i = 0; i < msg.sub.length; i++) {
|
|
||||||
mmsg = mmsg.replace("\{"+i+"\}", msg.sub[i]);
|
|
||||||
//console.log("Sub #" + i + ":",msg.sub[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let aItem = Template_alert({
|
|
||||||
ASID: msg.asid || 0,
|
|
||||||
Path: msg.path,
|
|
||||||
Avatar: msg.avatar || "",
|
|
||||||
Message: mmsg
|
|
||||||
})
|
|
||||||
alist += aItem;
|
|
||||||
alertList.push(aItem);
|
|
||||||
//console.log(msg);
|
|
||||||
//console.log(mmsg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(alist == "") alist = "<div class='alertItem'>You don't have any alerts</div>";
|
|
||||||
alertListNode.innerHTML = alist;
|
|
||||||
|
|
||||||
if(data.msgCount != 0 && data.msgCount != undefined) {
|
|
||||||
alertCounterNode.textContent = data.msgCount;
|
|
||||||
menuAlerts.classList.add("has_alerts");
|
|
||||||
} else {
|
|
||||||
menuAlerts.classList.remove("has_alerts");
|
|
||||||
}
|
}
|
||||||
alertCount = data.msgCount;
|
alertCount = data.msgCount;
|
||||||
|
updateAlertList(menuAlerts)
|
||||||
bindToAlerts();
|
|
||||||
},
|
},
|
||||||
error: (magic,theStatus,error) => {
|
error: (magic,theStatus,error) => {
|
||||||
let errtxt
|
let errtxt
|
||||||
|
@ -104,7 +132,7 @@ function loadAlerts(menuAlerts)
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
console.log("error", error);
|
console.log("error", error);
|
||||||
alertListNode.innerHTML = "<div class='alertItem'>"+errtxt+"</div>";
|
setAlertError(menuAlerts,errtxt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -129,46 +157,13 @@ function SplitN(data,ch,n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function wsAlertEvent(data) {
|
function wsAlertEvent(data) {
|
||||||
var msg = data.msg;
|
addAlert(data, true);
|
||||||
if("sub" in data) {
|
|
||||||
for(var i = 0; i < data.sub.length; i++) {
|
|
||||||
msg = msg.replace("\{"+i+"\}", data.sub[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let aItem = Template_alert({
|
|
||||||
ASID: data.asid || 0,
|
|
||||||
Path: data.path,
|
|
||||||
Avatar: data.avatar || "",
|
|
||||||
Message: msg
|
|
||||||
})
|
|
||||||
alertList.push(aItem);
|
|
||||||
if(alertList.length > 8) alertList.shift();
|
|
||||||
//console.log("post alertList",alertList);
|
|
||||||
alertCount++;
|
|
||||||
|
|
||||||
var alist = "";
|
var alist = "";
|
||||||
for (var i = 0; i < alertList.length; i++) alist += alertList[i];
|
for (var i = 0; i < alertList.length; i++) alist += alertMapping[alertList[i]];
|
||||||
|
|
||||||
//console.log(alist);
|
|
||||||
// TODO: Add support for other alert feeds like PM Alerts
|
// TODO: Add support for other alert feeds like PM Alerts
|
||||||
var generalAlerts = document.getElementById("general_alerts");
|
var generalAlerts = document.getElementById("general_alerts");
|
||||||
var alertListNode = generalAlerts.getElementsByClassName("alertList")[0];
|
updateAlertList(generalAlerts, alist);
|
||||||
var alertCounterNode = generalAlerts.getElementsByClassName("alert_counter")[0];
|
|
||||||
alertListNode.innerHTML = alist;
|
|
||||||
alertCounterNode.textContent = alertCount;
|
|
||||||
|
|
||||||
// TODO: Add some sort of notification queue to avoid flooding the end-user with notices?
|
|
||||||
// TODO: Use the site name instead of "Something Happened"
|
|
||||||
if(Notification.permission === "granted") {
|
|
||||||
var n = new Notification("Something Happened",{
|
|
||||||
body: msg,
|
|
||||||
icon: data.avatar,
|
|
||||||
});
|
|
||||||
setTimeout(n.close.bind(n), 8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
bindToAlerts();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function runWebSockets() {
|
function runWebSockets() {
|
||||||
|
@ -209,6 +204,20 @@ function runWebSockets() {
|
||||||
if ("msg" in data) {
|
if ("msg" in data) {
|
||||||
// TODO: Fix the data race where the alert template hasn't been loaded yet
|
// TODO: Fix the data race where the alert template hasn't been loaded yet
|
||||||
wsAlertEvent(data);
|
wsAlertEvent(data);
|
||||||
|
} else if("event" in data) {
|
||||||
|
if(data.event == "dismiss-alert"){
|
||||||
|
Object.keys(alertBuffer).forEach((key) => {
|
||||||
|
if(key==data.asid) {
|
||||||
|
alertCount--;
|
||||||
|
for(var i = 0; i < alertList.length;i++) {
|
||||||
|
if(alertList[i]==key) {
|
||||||
|
alertList.splice(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete alertMapping[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if("Topics" in data) {
|
} else if("Topics" in data) {
|
||||||
console.log("topic in data");
|
console.log("topic in data");
|
||||||
console.log("data:", data);
|
console.log("data:", data);
|
||||||
|
@ -300,17 +309,17 @@ function mainInit(){
|
||||||
|
|
||||||
$(".add_like").click(function(event) {
|
$(".add_like").click(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let likeButton = this;
|
|
||||||
let target = this.closest("a").getAttribute("href");
|
let target = this.closest("a").getAttribute("href");
|
||||||
console.log("target: ", target);
|
console.log("target: ", target);
|
||||||
likeButton.classList.remove("add_like");
|
this.classList.remove("add_like");
|
||||||
likeButton.classList.add("remove_like");
|
this.classList.add("remove_like");
|
||||||
let controls = likeButton.closest(".controls");
|
let controls = this.closest(".controls");
|
||||||
let hadLikes = controls.classList.contains("has_likes");
|
let hadLikes = controls.classList.contains("has_likes");
|
||||||
if(!hadLikes) controls.classList.add("has_likes");
|
if(!hadLikes) controls.classList.add("has_likes");
|
||||||
let likeCountNode = controls.getElementsByClassName("like_count")[0];
|
let likeCountNode = controls.getElementsByClassName("like_count")[0];
|
||||||
console.log("likeCountNode",likeCountNode);
|
console.log("likeCountNode",likeCountNode);
|
||||||
likeCountNode.innerHTML = parseInt(likeCountNode.innerHTML) + 1;
|
likeCountNode.innerHTML = parseInt(likeCountNode.innerHTML) + 1;
|
||||||
|
let likeButton = this;
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: target,
|
url: target,
|
||||||
|
@ -356,10 +365,6 @@ function mainInit(){
|
||||||
$(".show_on_edit").hide();
|
$(".show_on_edit").hide();
|
||||||
|
|
||||||
let formAction = this.form.getAttribute("action");
|
let formAction = this.form.getAttribute("action");
|
||||||
//console.log("New Topic Name: ", topicNameInput);
|
|
||||||
//console.log("New Topic Status: ", topicStatusInput);
|
|
||||||
//console.log("New Topic Content: ", topicContentInput);
|
|
||||||
//console.log("Form Action: ", formAction);
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: formAction,
|
url: formAction,
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
@ -393,7 +398,6 @@ function mainInit(){
|
||||||
block.html(newContent);
|
block.html(newContent);
|
||||||
|
|
||||||
var formAction = $(this).closest('a').attr("href");
|
var formAction = $(this).closest('a').attr("href");
|
||||||
//console.log("Form Action:",formAction);
|
|
||||||
$.ajax({ url: formAction, type: "POST", error: ajaxError, dataType: "json", data: { isJs: "1", edit_item: newContent }
|
$.ajax({ url: formAction, type: "POST", error: ajaxError, dataType: "json", data: { isJs: "1", edit_item: newContent }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -413,7 +417,6 @@ function mainInit(){
|
||||||
block.html(newContent);
|
block.html(newContent);
|
||||||
|
|
||||||
let formAction = $(this).closest('a').attr("href");
|
let formAction = $(this).closest('a').attr("href");
|
||||||
//console.log("Form Action:", formAction);
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: formAction + "?session=" + me.User.Session,
|
url: formAction + "?session=" + me.User.Session,
|
||||||
type: "POST",
|
type: "POST",
|
||||||
|
@ -430,7 +433,6 @@ function mainInit(){
|
||||||
if($(this).find("input").length !== 0) return;
|
if($(this).find("input").length !== 0) return;
|
||||||
//console.log("clicked .edit_fields");
|
//console.log("clicked .edit_fields");
|
||||||
var blockParent = $(this).closest('.editable_parent');
|
var blockParent = $(this).closest('.editable_parent');
|
||||||
//console.log(blockParent);
|
|
||||||
blockParent.find('.hide_on_edit').addClass("edit_opened");
|
blockParent.find('.hide_on_edit').addClass("edit_opened");
|
||||||
blockParent.find('.show_on_edit').addClass("edit_opened");
|
blockParent.find('.show_on_edit').addClass("edit_opened");
|
||||||
blockParent.find('.editable_block').show();
|
blockParent.find('.editable_block').show();
|
||||||
|
@ -443,9 +445,6 @@ function mainInit(){
|
||||||
else var it = ['No','Yes'];
|
else var it = ['No','Yes'];
|
||||||
var itLen = it.length;
|
var itLen = it.length;
|
||||||
var out = "";
|
var out = "";
|
||||||
//console.log("Field Name:",fieldName);
|
|
||||||
//console.log("Field Type:",fieldType);
|
|
||||||
//console.log("Field Value:",fieldValue);
|
|
||||||
for (var i = 0; i < itLen; i++) {
|
for (var i = 0; i < itLen; i++) {
|
||||||
var sel = "";
|
var sel = "";
|
||||||
if(fieldValue == i || fieldValue == it[i]) {
|
if(fieldValue == i || fieldValue == it[i]) {
|
||||||
|
|
Loading…
Reference in New Issue