Live Topic List should work properly now with replies too, not just new topics.

Tweaked the visuals for the live topic list on Cosora. More to come with this.
Nox Theme is now present on the theme selector, although it's still under construction.

Improved SEO for social media.
Added the topic_list tmpl phrase prefix.
Added the topic_list.changed_topics phrase.
Added a few more PreparseMessage tests.
Session cookies should now be deleted after you logout, not just blanked.
This commit is contained in:
Azareal 2018-06-30 13:40:50 +10:00
parent 5d810c1e3b
commit bf40d61474
14 changed files with 174 additions and 59 deletions

View File

@ -182,13 +182,17 @@ func setCookie(w http.ResponseWriter, cookie *http.Cookie, sameSite string) {
}
}
func deleteCookie(w http.ResponseWriter, cookie *http.Cookie) {
cookie.MaxAge = -1
http.SetCookie(w, cookie)
}
// Logout logs you out of the computer you requested the logout for, but not the other computers you're logged in with
func (auth *DefaultAuth) Logout(w http.ResponseWriter, _ int) {
cookie := http.Cookie{Name: "uid", Value: "", Path: "/", MaxAge: int(Year)}
setCookie(w, &cookie, "lax")
http.SetCookie(w, &cookie)
cookie = http.Cookie{Name: "session", Value: "", Path: "/", MaxAge: int(Year)}
setCookie(w, &cookie, "lax")
cookie := http.Cookie{Name: "uid", Value: "", Path: "/"}
deleteCookie(w, &cookie)
cookie = http.Cookie{Name: "session", Value: "", Path: "/"}
deleteCookie(w, &cookie)
}
// TODO: Set the cookie domain

View File

@ -93,11 +93,13 @@ func (hub *WsHubImpl) Tick() error {
//fmt.Println("checking for changes")
// TODO: Optimise this by only sniffing the top non-sticky
// TODO: Optimise this by getting back an unsorted list so we don't have to hop around the stickies
// TODO: Add support for new stickies / replies to them
if len(tList) == len(hub.lastTopicList) {
var hasItem = false
for j, tItem := range tList {
if !tItem.Sticky {
if tItem.ID != hub.lastTopicList[j].ID {
if tItem.ID != hub.lastTopicList[j].ID || !tItem.LastReplyAt.Equal(hub.lastTopicList[j].LastReplyAt) {
hasItem = true
}
}

View File

@ -424,17 +424,18 @@
"quick_topic.add_file_button":"Add File",
"quick_topic.cancel_button":"Cancel",
"topic_list_create_topic_tooltip":"Create Topic",
"topic_list_create_topic_aria":"Create a topic",
"topic_list_moderate_tooltip":"Moderate",
"topic_list_moderate_aria":"Moderate Posts",
"topic_list_what_to_do":"What do you want to do with these 18 topics?",
"topic_list_moderate_delete":"Delete them",
"topic_list_moderate_lock":"Lock them",
"topic_list_moderate_move":"Move them",
"topic_list_moderate_run":"Run",
"topic_list_move_head":"Move these topics to?",
"topic_list_move_button":"Move Topics",
"topic_list.create_topic_tooltip":"Create Topic",
"topic_list.create_topic_aria":"Create a topic",
"topic_list.moderate_tooltip":"Moderate",
"topic_list.moderate_aria":"Moderate Posts",
"topic_list.what_to_do":"What do you want to do with these 18 topics?",
"topic_list.moderate_delete":"Delete them",
"topic_list.moderate_lock":"Lock them",
"topic_list.moderate_move":"Move them",
"topic_list.moderate_run":"Run",
"topic_list.move_head":"Move these topics to?",
"topic_list.move_button":"Move Topics",
"topic_list.changed_topics":"Click to see %d new or changed topics",
"status.closed_tooltip":"Status: Closed",
"status.pinned_tooltip":"Status: Pinned",

View File

@ -989,6 +989,11 @@ func TestPreparser(t *testing.T) {
msgList = addMETri(msgList, "</p>", "")
msgList = addMETri(msgList, "<p></p>", "")
msgList = addMETri(msgList, "<", "&lt;")
msgList = addMETri(msgList, ">", "&gt;")
msgList = addMETri(msgList, "<meow>", "&lt;meow&gt;")
msgList = addMETri(msgList, "&lt;", "&amp;lt;")
// Note: strings.TrimSpace strips newlines, if there's nothing before or after them
msgList = addMETri(msgList, "<br>", "")
msgList = addMETri(msgList, "<br />", "")

View File

@ -1,9 +1,11 @@
'use strict';
var formVars = {};
var tmplInits = {};
var tmplPhrases = [];
var tmplPhrases = []; // [key] array of phrases indexed by order of use
var phraseBox = {};
var alertList = [];
var alertCount = 0;
var moreTopicCount = 0;
var conn;
var selectedTopics = [];
var attachItemCallback = function(){}
@ -214,8 +216,8 @@ function runWebSockets() {
return;
}
// TODO: Fix the data races in this code
if ("msg" in data) {
// TODO: Fix the data race where the alert template hasn't been loaded yet
wsAlertEvent(data);
} else if("Topics" in data) {
console.log("topic in data");
@ -225,11 +227,27 @@ function runWebSockets() {
console.log("empty topic list");
return;
}
// TODO: Fix the data race where the function hasn't been loaded yet
let renTopic = Template_topics_topic(topic);
$(".topic_row[data-tid='"+topic.ID+"']").addClass("ajax_topic_dupe");
let node = $(renTopic);
node.addClass("new_item");
node.addClass("new_item hide_ajax_topic");
console.log("Prepending to topic list");
$(".topic_list").prepend(node);
moreTopicCount++;
let moreTopicBlocks = document.getElementsByClassName("more_topic_block_initial");
for(let i = 0; i < moreTopicBlocks.length; i++) {
let moreTopicBlock = moreTopicBlocks[i];
moreTopicBlock.classList.remove("more_topic_block_initial");
moreTopicBlock.classList.add("more_topic_block_active");
console.log("phraseBox:",phraseBox);
let msgBox = moreTopicBlock.getElementsByClassName("more_topics")[0];
msgBox.innerText = phraseBox["topic_list"]["topic_list.changed_topics"].replace("%d",moreTopicCount);
}
} else {
console.log("unknown message");
console.log(data);
@ -278,9 +296,11 @@ function DoNothingButPassBack(item) {
}
function fetchPhrases() {
fetch("//" +siteURL+"/api/phrases/?query=status")
fetch("//" +siteURL+"/api/phrases/?query=status,topic_list")
.then((resp) => resp.json())
.then((data) => {
console.log("loaded phrase endpoint data");
console.log("data:",data);
Object.keys(tmplInits).forEach((key) => {
let phrases = [];
let tmplInit = tmplInits[key];
@ -291,7 +311,20 @@ function fetchPhrases() {
console.log("key:",key);
console.log("phrases:",phrases);
tmplPhrases[key] = phrases;
})
});
let prefixes = {};
Object.keys(data).forEach((key) => {
let prefix = key.split(".")[0];
if(prefixes[prefix]===undefined) {
prefixes[prefix] = {};
}
prefixes[prefix][key] = data[key];
});
Object.keys(prefixes).forEach((prefix) => {
console.log("adding phrase prefix '"+prefix+"' to box");
phraseBox[prefix] = prefixes[prefix];
});
});
}
@ -319,6 +352,21 @@ $(document).ready(function(){
if(window["WebSocket"]) runWebSockets();
else conn = false;
$(".more_topics").click((event) => {
event.preventDefault();
let moreTopicBlocks = document.getElementsByClassName("more_topic_block_active");
for(let i = 0; i < moreTopicBlocks.length; i++) {
let moreTopicBlock = moreTopicBlocks[i];
moreTopicBlock.classList.remove("more_topic_block_active");
moreTopicBlock.classList.add("more_topic_block_initial");
}
$(".ajax_topic_dupe").fadeOut("slow", function(){
$(this).remove();
});
$(".hide_ajax_topic").removeClass("hide_ajax_topic"); // TODO: Do Fade
moreTopicCount = 0;
})
$(".add_like").click(function(event) {
event.preventDefault();
let likeButton = this;
@ -596,29 +644,31 @@ $(document).ready(function(){
let reader = new FileReader();
reader.onload = function(e) {
crypto.subtle.digest('SHA-256',e.target.result).then(function(hash) {
const hashArray = Array.from(new Uint8Array(hash))
return hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('')
}).then(function(hash) {
console.log("hash",hash);
let content = document.getElementById("input_content")
console.log("content.value", content.value);
crypto.subtle.digest('SHA-256',e.target.result)
.then(function(hash) {
const hashArray = Array.from(new Uint8Array(hash))
return hashArray.map(b => ('00' + b.toString(16)).slice(-2)).join('')
}).then(function(hash) {
console.log("hash",hash);
let content = document.getElementById("input_content")
console.log("content.value", content.value);
let attachItem;
if(content.value == "") attachItem = "//" + siteURL + "/attachs/" + hash + "." + ext;
else attachItem = "\r\n//" + siteURL + "/attachs/" + hash + "." + ext;
content.value = content.value + attachItem;
console.log("content.value", content.value);
let attachItem;
if(content.value == "") attachItem = "//" + siteURL + "/attachs/" + hash + "." + ext;
else attachItem = "\r\n//" + siteURL + "/attachs/" + hash + "." + ext;
content.value = content.value + attachItem;
console.log("content.value", content.value);
// For custom / third party text editors
attachItemCallback(attachItem);
});
// For custom / third party text editors
attachItemCallback(attachItem);
});
}
reader.readAsArrayBuffer(files[i]);
}
reader.readAsDataURL(files[i]);
}
if(totalSize>maxRequestSize) {
// TODO: Use a notice instead
alert("You can't upload this much data at once, max: " + maxRequestSize);
}
}

View File

@ -12,10 +12,10 @@
<div class="optbox">
{{if .CurrentUser.Perms.CreateTopic}}
<div class="pre_opt auto_hide"></div>
<div class="opt create_topic_opt" title="{{lang "topic_list_create_topic_tooltip"}}" aria-label="{{lang "topic_list_create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/{{.Forum.ID}}"></a></div>
<div class="opt create_topic_opt" title="{{lang "topic_list.create_topic_tooltip"}}" aria-label="{{lang "topic_list.create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/{{.Forum.ID}}"></a></div>
{{/** TODO: Add a permissions check for this **/}}
<div class="opt mod_opt" title="{{lang "topic_list_moderate_tooltip"}}">
<a class="moderate_link" href="#" aria-label="{{lang "topic_list_moderate_aria"}}"></a>
<div class="opt mod_opt" title="{{lang "topic_list.moderate_tooltip"}}">
<a class="moderate_link" href="#" aria-label="{{lang "topic_list.moderate_aria"}}"></a>
</div>
{{else}}<div class="opt locked_opt" title="{{lang "forum_locked_tooltip"}}" aria-label="{{lang "forum_locked_aria"}}"><a></a></div>{{end}}
</div>
@ -26,15 +26,15 @@
<div class="mod_floater auto_hide">
<form method="post">
<div class="mod_floater_head">
<span>{{lang "topic_list_what_to_do"}}</span>
<span>{{lang "topic_list.what_to_do"}}</span>
</div>
<div class="mod_floater_body">
<select class="mod_floater_options">
<option val="delete">{{lang "topic_list_moderate_delete"}}</option>
<option val="lock">{{lang "topic_list_moderate_lock"}}</option>
<option val="move">{{lang "topic_list_moderate_move"}}</option>
<option val="delete">{{lang "topic_list.moderate_delete"}}</option>
<option val="lock">{{lang "topic_list.moderate_lock"}}</option>
<option val="move">{{lang "topic_list.moderate_move"}}</option>
</select>
<button>{{lang "topic_list_moderate_run"}}</button>
<button>{{lang "topic_list.moderate_run"}}</button>
</div>
</form>
</div>

View File

@ -20,8 +20,11 @@
<script type="text/javascript" src="/static/global.js"></script>
<meta name="viewport" content="width=device-width,initial-scale = 1.0, maximum-scale=1.0,user-scalable=no" />
{{if .Header.MetaDesc}}<meta name="description" content="{{.Header.MetaDesc}}" />{{end}}
{{/** TODO: Have page / forum / topic level tags and descriptions below as-well **/}}
<meta property="og:type" content="website" />
<meta property="og:site_name" content="{{.Header.Site.Name}}">
<meta property="og:title" content="{{.Title}} | {{.Header.Site.Name}}">
<meta name="twitter:title" content="{{.Title}} | {{.Header.Site.Name}}" />
</head>
<body>
{{if not .CurrentUser.IsSuperMod}}<style>.supermod_only { display: none !important; }</style>{{end}}

View File

@ -7,10 +7,10 @@
<div class="optbox">
{{if .ForumList}}
<div class="pre_opt auto_hide"></div>
<div class="opt create_topic_opt" title="{{lang "topic_list_create_topic_tooltip"}}" aria-label="{{lang "topic_list_create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/"></a></div>
<div class="opt create_topic_opt" title="{{lang "topic_list.create_topic_tooltip"}}" aria-label="{{lang "topic_list.create_topic_aria"}}"><a class="create_topic_link" href="/topics/create/"></a></div>
{{/** TODO: Add a permissions check for this **/}}
<div class="opt mod_opt" title="{{lang "topic_list_moderate_tooltip"}}">
<a class="moderate_link" href="#" aria-label="{{lang "topic_list_moderate_aria"}}"></a>
<div class="opt mod_opt" title="{{lang "topic_list.moderate_tooltip"}}">
<a class="moderate_link" href="#" aria-label="{{lang "topic_list.moderate_aria"}}"></a>
</div>
{{else}}<div class="opt locked_opt" title="{{lang "topics_locked_tooltip"}}" aria-label="{{lang "topics_locked_aria"}}"><a></a></div>{{end}}
</div>
@ -23,15 +23,15 @@
<div class="mod_floater auto_hide">
<form method="post">
<div class="mod_floater_head">
<span>{{lang "topic_list_what_to_do"}}</span>
<span>{{lang "topic_list.what_to_do"}}</span>
</div>
<div class="mod_floater_body">
<select class="mod_floater_options">
<option val="delete">{{lang "topic_list_moderate_delete"}}</option>
<option val="lock">{{lang "topic_list_moderate_lock"}}</option>
<option val="move">{{lang "topic_list_moderate_move"}}</option>
<option val="delete">{{lang "topic_list.moderate_delete"}}</option>
<option val="lock">{{lang "topic_list.moderate_lock"}}</option>
<option val="move">{{lang "topic_list.moderate_move"}}</option>
</select>
<button class="mod_floater_submit">{{lang "topic_list_moderate_run"}}</button>
<button class="mod_floater_submit">{{lang "topic_list.moderate_run"}}</button>
</div>
</form>
</div>
@ -43,7 +43,7 @@
<form action="/topic/move/submit/?session={{.CurrentUser.Session}}" method="post">
<input id="mover_fid" name="fid" value="0" type="hidden" />
<div class="pane_header">
<h3>{{lang "topic_list_move_head"}}</h3>
<h3>{{lang "topic_list.move_head"}}</h3>
</div>
<div class="pane_body">
<div class="pane_table">
@ -51,7 +51,7 @@
</div>
</div>
<div class="pane_buttons">
<button id="mover_submit">{{lang "topic_list_move_button"}}</button>
<button id="mover_submit">{{lang "topic_list.move_button"}}</button>
</div>
</form>
</div>
@ -101,6 +101,9 @@
</div>
{{end}}
{{end}}
<div class="rowblock more_topic_block more_topic_block_initial">
<div class="rowitem rowmsg"><a href="" class="more_topics"></a></div>
</div>
<div id="topic_list" class="rowblock topic_list" aria-label="{{lang "topics_list_aria"}}">
{{range .TopicList}}{{template "topics_topic.html" . }}{{else}}<div class="rowitem passive rowmsg">{{lang "topics_no_topics"}}{{if .CurrentUser.Perms.CreateTopic}} <a href="/topics/create/">{{lang "topics_start_one"}}</a>{{end}}</div>{{end}}
</div>

View File

@ -698,9 +698,16 @@ textarea {
background-color: rgb(239, 255, 255);
border: 1px solid rgb(187, 217, 217);
border-bottom: 2px solid rgb(187, 217, 217);
border-left: none;
}
.topic_row.new_item .topic_left {
border-right: none;
}
.topic_row.new_item .topic_right {
border-left: none;
}
.hide_ajax_topic {
display: none !important;
}
.topic_middle {
display: none;
}
@ -896,6 +903,13 @@ textarea {
}
}
.more_topic_block_initial {
display: none;
}
.more_topic_block_active {
display: block;
}
.forum_list, .post_container {
border: none;
}

View File

@ -236,6 +236,14 @@ h1, h3 {
display: none;
}
/* TODO: Make a generic version of this so that we can have more blocks which are initially hidden but flip over to visible under certain conditions */
.more_topic_block_initial {
display: none;
}
.more_topic_block_active {
display: block;
}
input, select, button, .formbutton, textarea {
border-radius: 3px;
background: rgb(90,90,90);

View File

@ -1,12 +1,16 @@
{
"Name": "nox",
"FriendlyName": "Nox",
"FriendlyName": "Nox (Incomplete)",
"Version": "0.0.1",
"Creator": "Azareal",
"URL": "github.com/Azareal/Gosora",
"Tag": "WIP",
"HideFromThemes":true,
"Docks":["topMenu","rightSidebar","footer"],
"MapTmplToDock": {
"rightOfNav": {
"File": "./templates/userDock.html"
}
},
"Templates": [
{
"Name": "topic",

View File

@ -841,6 +841,13 @@ input[type=checkbox]:checked + label.poll_option_label .sel {
display: none;
}
.more_topic_block_initial {
display: none;
}
.more_topic_block_active {
display: block;
}
.topic_name_input {
width: 100%;
margin-right: 10px;

View File

@ -489,6 +489,13 @@ li a {
display: none;
}
.more_topic_block_initial {
display: none;
}
.more_topic_block_active {
display: block;
}
.postImage {
max-width: 100%;
max-height: 200px;

View File

@ -498,6 +498,13 @@ input, select {
display: none;
}
.more_topic_block_initial {
display: none;
}
.more_topic_block_active {
display: block;
}
.postImage {
max-width: 100%;
max-height: 200px;