2019-09-01 00:13:59 +00:00
|
|
|
/*
|
|
|
|
Onionr - Private P2P Communication
|
|
|
|
|
|
|
|
This file handles the boards/circles interface
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
2019-12-01 09:51:38 +00:00
|
|
|
requested = []
|
2019-04-16 17:04:51 +00:00
|
|
|
newPostForm = document.getElementById('addMsg')
|
2019-07-17 05:10:39 +00:00
|
|
|
firstLoad = true
|
2019-07-29 03:00:38 +00:00
|
|
|
lastLoadedBoard = 'global'
|
2019-09-06 05:18:25 +00:00
|
|
|
loadingMessage = document.getElementById('loadingBoard')
|
2019-10-05 23:35:40 +00:00
|
|
|
loadedAny = false
|
|
|
|
loadingTimeout = 8000
|
2019-09-06 05:18:25 +00:00
|
|
|
|
|
|
|
let toggleLoadingMessage = function(){
|
|
|
|
switch (loadingMessage.style.display){
|
|
|
|
case "inline-block":
|
|
|
|
loadingMessage.style.display = "none"
|
2019-11-27 03:46:45 +00:00
|
|
|
break;
|
2019-09-06 05:18:25 +00:00
|
|
|
default:
|
|
|
|
loadingMessage.style.display = "initial"
|
2019-11-27 03:46:45 +00:00
|
|
|
break;
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
|
|
|
}
|
2019-07-29 03:00:38 +00:00
|
|
|
|
2020-03-28 05:16:42 +00:00
|
|
|
fetch('/circles/version', {
|
2019-09-06 05:18:25 +00:00
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
"token": webpass
|
2019-11-27 03:46:45 +00:00
|
|
|
}})
|
|
|
|
.then((ver) => ver.text())
|
|
|
|
.then(function(ver) {
|
|
|
|
document.getElementById('circlesVersion').innerText = ver
|
2019-09-06 05:18:25 +00:00
|
|
|
})
|
|
|
|
|
2019-11-27 03:46:45 +00:00
|
|
|
function appendMessages(msg, blockHash, beforeHash, channel) {
|
|
|
|
if (channel !== document.getElementById('feedIDInput').value) return // ignore if channel name isn't matching
|
|
|
|
if (msg.length == 0) return // ignore empty messages
|
|
|
|
|
2019-04-16 17:04:51 +00:00
|
|
|
var humanDate = new Date(0)
|
|
|
|
var msgDate = msg['meta']['time']
|
2019-09-06 05:18:25 +00:00
|
|
|
var feed = document.getElementById("feed")
|
|
|
|
var beforeEl = null
|
|
|
|
|
2019-04-16 17:04:51 +00:00
|
|
|
if (msgDate === undefined){
|
|
|
|
msgDate = 'unknown'
|
2019-11-27 03:46:45 +00:00
|
|
|
} else {
|
2019-04-16 17:04:51 +00:00
|
|
|
humanDate.setUTCSeconds(msgDate)
|
2019-12-06 20:25:02 +00:00
|
|
|
msgDate = humanDate.toLocaleString("en-US", {timeZone: "Etc/GMT"})
|
2019-02-02 03:49:11 +00:00
|
|
|
}
|
2019-11-27 03:46:45 +00:00
|
|
|
|
|
|
|
var el = document.createElement('div')
|
2019-04-16 17:04:51 +00:00
|
|
|
el.innerText = msg['content']
|
2019-11-27 03:46:45 +00:00
|
|
|
|
|
|
|
if (beforeHash !== null) {
|
|
|
|
for (i = 0; i < feed.children.length; i++) {
|
|
|
|
if (feed.children[i].getAttribute('data-bl') === beforeHash) {
|
|
|
|
beforeEl = feed.children[i]
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-06-28 21:24:34 +00:00
|
|
|
|
|
|
|
/* Template Test */
|
|
|
|
// Test to see if the browser supports the HTML template element by checking
|
|
|
|
// for the presence of the template element's content attribute.
|
|
|
|
if ('content' in document.createElement('template')) {
|
|
|
|
|
|
|
|
// Instantiate the table with the existing HTML tbody
|
|
|
|
// and the row with the template
|
2019-07-17 05:10:39 +00:00
|
|
|
var template = document.getElementById('cMsgTemplate')
|
2019-06-28 21:24:34 +00:00
|
|
|
|
|
|
|
// Clone the new row and insert it into the table
|
2019-09-06 05:18:25 +00:00
|
|
|
var clone = document.importNode(template.content, true)
|
2019-07-17 05:10:39 +00:00
|
|
|
var div = clone.querySelectorAll("div")
|
2019-09-21 05:06:49 +00:00
|
|
|
var identicon = clone.querySelectorAll("img")
|
2019-09-06 05:18:25 +00:00
|
|
|
|
2019-12-04 07:02:28 +00:00
|
|
|
div[0].classList.add('entry')
|
|
|
|
div[0].setAttribute('timestamp', msg['meta']['time'])
|
|
|
|
|
2019-09-06 05:18:25 +00:00
|
|
|
div[0].setAttribute('data-bl', blockHash)
|
2019-07-17 05:10:39 +00:00
|
|
|
div[2].textContent = msg['content']
|
2019-09-07 20:08:15 +00:00
|
|
|
if (typeof msg['meta']['signer'] != 'undefined' && msg['meta']['signer'].length > 0){
|
2019-08-31 10:56:44 +00:00
|
|
|
div[3].textContent = msg['meta']['signer'].substr(0, 5)
|
2019-09-07 20:08:15 +00:00
|
|
|
setHumanReadableIDOnPost(div[3], msg['meta']['signer'])
|
2020-09-19 03:08:42 +00:00
|
|
|
div[3].onclick = function(){
|
|
|
|
navigator.clipboard.writeText(div[3].title).then(function() {
|
|
|
|
PNotify.notice("Copied poster identity to clipboard")
|
|
|
|
})
|
|
|
|
}
|
2019-08-31 10:56:44 +00:00
|
|
|
div[3].title = msg['meta']['signer']
|
2019-09-27 23:04:49 +00:00
|
|
|
userIcon(msg['meta']['signer']).then(function(data){
|
|
|
|
identicon[0].src = "data:image/svg+xml;base64," + data
|
|
|
|
})
|
2019-09-21 05:06:49 +00:00
|
|
|
}
|
|
|
|
else{
|
|
|
|
identicon[0].remove()
|
2019-08-31 10:56:44 +00:00
|
|
|
}
|
|
|
|
div[4].textContent = msgDate
|
2019-06-28 21:24:34 +00:00
|
|
|
|
2019-09-06 05:18:25 +00:00
|
|
|
loadingMessage.style.display = "none"
|
2019-10-05 23:35:40 +00:00
|
|
|
loadedAny = true
|
2019-07-17 05:10:39 +00:00
|
|
|
if (firstLoad){
|
2019-09-06 05:18:25 +00:00
|
|
|
//feed.appendChild(clone)
|
|
|
|
feed.prepend(clone)
|
|
|
|
firstLoad = false
|
2019-07-17 05:10:39 +00:00
|
|
|
}
|
|
|
|
else{
|
2019-09-06 05:18:25 +00:00
|
|
|
if (beforeEl === null){
|
|
|
|
feed.prepend(clone)
|
|
|
|
}
|
|
|
|
else{
|
2019-09-21 01:41:06 +00:00
|
|
|
beforeEl.insertAdjacentElement("beforebegin", clone.children[0])
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
|
|
|
|
2019-07-17 05:10:39 +00:00
|
|
|
}
|
2019-06-28 21:24:34 +00:00
|
|
|
}
|
2019-02-02 03:49:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getBlocks(){
|
2019-07-29 03:00:38 +00:00
|
|
|
var feed = document.getElementById("feed")
|
|
|
|
var ch = document.getElementById('feedIDInput').value
|
|
|
|
if (lastLoadedBoard !== ch){
|
2019-11-27 03:46:45 +00:00
|
|
|
requested = []
|
2020-01-14 08:29:42 +00:00
|
|
|
|
2019-09-06 05:18:25 +00:00
|
|
|
toggleLoadingMessage()
|
2019-10-05 23:35:40 +00:00
|
|
|
loadedAny = false
|
2019-11-27 03:46:45 +00:00
|
|
|
|
|
|
|
while (feed.firstChild) feed.removeChild(feed.firstChild); // remove all messages from feed
|
|
|
|
|
2019-10-05 23:35:40 +00:00
|
|
|
setTimeout(function(){
|
|
|
|
if (! loadedAny && ch == document.getElementById('feedIDInput').value){
|
2019-10-11 09:28:43 +00:00
|
|
|
PNotify.notice("There are no posts for " + ch + ". You can be the first!")
|
2019-10-05 23:35:40 +00:00
|
|
|
}
|
|
|
|
}, loadingTimeout)
|
2019-07-29 03:00:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lastLoadedBoard = ch
|
2019-02-02 03:49:11 +00:00
|
|
|
if (document.getElementById('none') !== null){
|
|
|
|
document.getElementById('none').remove();
|
|
|
|
|
|
|
|
}
|
2019-09-06 05:18:25 +00:00
|
|
|
|
2020-03-28 05:16:42 +00:00
|
|
|
fetch('/circles/getpostsbyboard/' + ch, {
|
2020-03-24 05:21:46 +00:00
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
"token": webpass
|
|
|
|
}})
|
|
|
|
.then((resp) => resp.text())
|
|
|
|
.then(function(feedText) {
|
|
|
|
var blockList = feedText.split(',')
|
|
|
|
|
|
|
|
for (i = 0; i < blockList.length; i++){
|
|
|
|
blockList[i] = "0".repeat(64 - blockList[i].length) + blockList[i] // pad hash with zeroes
|
|
|
|
|
|
|
|
if (! requested.includes(blockList[i])){
|
|
|
|
if (blockList[i].length == 0) continue
|
|
|
|
else requested.push(blockList[i])
|
|
|
|
loadMessage(blockList[i], blockList, i, ch);
|
|
|
|
}
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
2020-03-24 05:21:46 +00:00
|
|
|
sortEntries()
|
|
|
|
})
|
2019-02-02 03:49:11 +00:00
|
|
|
}
|
|
|
|
|
2019-10-10 07:25:12 +00:00
|
|
|
function loadMessage(blockHash, blockList, count, channel){
|
2020-01-15 06:22:36 +00:00
|
|
|
if (blockHash == '0000000000000000000000000000000000000000000000000000000000000000'){
|
|
|
|
return
|
|
|
|
}
|
2019-09-06 05:18:25 +00:00
|
|
|
fetch('/getblockdata/' + blockHash, {
|
|
|
|
method: 'GET',
|
|
|
|
headers: {
|
|
|
|
"token": webpass
|
2020-01-15 06:24:42 +00:00
|
|
|
}}).then(function(response) {
|
|
|
|
if (!response.ok) {
|
|
|
|
let on404 = function() {
|
|
|
|
if (response.status == 404){
|
2020-03-28 05:16:42 +00:00
|
|
|
fetch('/circles/removefromcache/' + channel + '/' + blockHash, {
|
2020-01-15 06:24:42 +00:00
|
|
|
method: 'POST',
|
|
|
|
headers: {
|
|
|
|
"content-type": "application/json",
|
|
|
|
"token": webpass
|
|
|
|
}
|
|
|
|
})
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
2020-01-15 06:24:42 +00:00
|
|
|
else{
|
|
|
|
console.log(error)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
return
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
2020-01-15 06:24:42 +00:00
|
|
|
response.json().then(function(data){
|
|
|
|
let before = blockList[count - 1]
|
|
|
|
let delay = 2000
|
|
|
|
if (typeof before == "undefined"){
|
|
|
|
before = null
|
|
|
|
} else {
|
|
|
|
let existing = document.getElementsByClassName('cMsgBox')
|
|
|
|
for (x = 0; x < existing.length; x++){
|
|
|
|
if (existing[x].getAttribute('data-bl') === before){
|
|
|
|
delay = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setTimeout(function(){appendMessages(data, blockHash, before, channel)}, delay)
|
|
|
|
})
|
|
|
|
return response;
|
2019-11-27 03:46:45 +00:00
|
|
|
})
|
2019-09-06 05:18:25 +00:00
|
|
|
}
|
|
|
|
|
2019-11-27 03:46:45 +00:00
|
|
|
document.getElementById('refreshFeed').onclick = function() {
|
2019-02-02 03:49:11 +00:00
|
|
|
getBlocks()
|
2019-04-16 17:04:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
newPostForm.onsubmit = function(){
|
2019-04-20 22:55:54 +00:00
|
|
|
var message = document.getElementById('newMsgText').value
|
2019-07-29 03:00:38 +00:00
|
|
|
var channel = document.getElementById('feedIDInput').value
|
|
|
|
var meta = {'ch': channel}
|
2019-08-31 10:56:44 +00:00
|
|
|
let doSign = document.getElementById('postAnon').checked
|
|
|
|
var postData = {'message': message, 'sign': doSign, 'type': 'brd', 'encrypt': false, 'meta': JSON.stringify(meta)}
|
2019-04-20 22:55:54 +00:00
|
|
|
postData = JSON.stringify(postData)
|
|
|
|
newPostForm.style.display = 'none'
|
|
|
|
fetch('/insertblock', {
|
|
|
|
method: 'POST',
|
|
|
|
body: postData,
|
|
|
|
headers: {
|
|
|
|
"content-type": "application/json",
|
|
|
|
"token": webpass
|
2019-11-27 03:46:45 +00:00
|
|
|
}
|
|
|
|
})
|
2020-01-20 03:02:04 +00:00
|
|
|
.then((resp) => resp.text())
|
2019-04-20 22:55:54 +00:00
|
|
|
.then(function(data) {
|
|
|
|
newPostForm.style.display = 'block'
|
2019-08-13 22:28:53 +00:00
|
|
|
if (data == 'failure due to duplicate insert'){
|
2019-09-01 00:13:59 +00:00
|
|
|
PNotify.error({
|
|
|
|
text: "This message is already queued"
|
|
|
|
})
|
2019-08-13 22:28:53 +00:00
|
|
|
return
|
|
|
|
}
|
2019-09-01 00:13:59 +00:00
|
|
|
PNotify.success({
|
|
|
|
text: "Message queued for posting"
|
2019-11-27 03:46:45 +00:00
|
|
|
})
|
2019-09-06 05:18:25 +00:00
|
|
|
setTimeout(function(){getBlocks()}, 500)
|
2019-11-27 03:46:45 +00:00
|
|
|
})
|
2019-04-16 17:04:51 +00:00
|
|
|
return false
|
2019-09-28 01:38:47 +00:00
|
|
|
}
|
2020-01-15 06:24:42 +00:00
|
|
|
|
2020-03-29 23:51:12 +00:00
|
|
|
resetCirclePickers = function(){
|
|
|
|
document.getElementById('recommendedBoards').value = ""
|
|
|
|
document.getElementById('popularBoards').value = ""
|
|
|
|
}
|
|
|
|
|
|
|
|
document.getElementById('feedIDInput').onchange = resetCirclePickers
|
2020-01-15 06:24:42 +00:00
|
|
|
|