Moved plugin web files to be in the plugin folder to reduce staticfiles blueprint coupling
This commit is contained in:
		
							parent
							
								
									14f2d03ebf
								
							
						
					
					
						commit
						37e5dbab4b
					
				
					 23 changed files with 37 additions and 40 deletions
				
			
		|  | @ -8,6 +8,7 @@ import os | |||
| import ujson as json | ||||
| 
 | ||||
| from flask import Response, Blueprint | ||||
| from flask import send_from_directory | ||||
| from deadsimplekv import DeadSimpleKV | ||||
| 
 | ||||
| from utils import identifyhome | ||||
|  | @ -28,6 +29,9 @@ from utils import identifyhome | |||
| 
 | ||||
| flask_blueprint = Blueprint('circles', __name__) | ||||
| 
 | ||||
| root = os.path.dirname(os.path.realpath(__file__)) | ||||
| 
 | ||||
| 
 | ||||
| with open( | ||||
|     os.path.dirname( | ||||
|         os.path.realpath(__file__)) + '/info.json', 'r') as info_file: | ||||
|  | @ -41,6 +45,15 @@ read_only_cache = DeadSimpleKV( | |||
|     flush_on_exit=False, | ||||
|     refresh_seconds=30) | ||||
| 
 | ||||
| @flask_blueprint.route('/board/<path:path>', endpoint='circlesstatic') | ||||
| def load_mail(path): | ||||
|     return send_from_directory(root + '/web/', path) | ||||
| 
 | ||||
| 
 | ||||
| @flask_blueprint.route('/board/', endpoint='circlesindex') | ||||
| def load_mail_index(): | ||||
|     return send_from_directory(root + '/web/', 'index.html') | ||||
| 
 | ||||
| 
 | ||||
| @flask_blueprint.route('/circles/getpostsbyboard/<board>') | ||||
| def get_post_by_board(board): | ||||
|  |  | |||
|  | @ -36,7 +36,7 @@ import flowapi  # noqa | |||
| """ | ||||
| 
 | ||||
| flask_blueprint = flowapi.flask_blueprint | ||||
| security_whitelist = ['staticfiles.boardContent', 'staticfiles.board'] | ||||
| security_whitelist = ['circles.circlesstatic', 'circles.circlesindex'] | ||||
| 
 | ||||
| plugin_name = 'circles' | ||||
| PLUGIN_VERSION = '0.1.0' | ||||
|  |  | |||
							
								
								
									
										44
									
								
								static-data/default-plugins/circles/web/autorefresh.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								static-data/default-plugins/circles/web/autorefresh.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Auto refresh board posts | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| var checkbox = document.getElementById('refreshCheckbox') | ||||
| function autoRefresh(){ | ||||
|     if (! checkbox.checked || document.hidden){return} | ||||
|     getBlocks() | ||||
| } | ||||
| 
 | ||||
| function setupInterval(){ | ||||
|     if (checkbox.checked){ | ||||
|         refreshInterval = setInterval(autoRefresh, 3000) | ||||
|         autoRefresh() | ||||
|         return | ||||
|     } | ||||
|     clearInterval(refreshInterval) | ||||
| } | ||||
| 
 | ||||
| var refreshInterval = setInterval(autoRefresh, 3000) | ||||
| setupInterval() | ||||
| 
 | ||||
| checkbox.onchange = function(){setupInterval} | ||||
| 
 | ||||
| 
 | ||||
| document.addEventListener("visibilitychange", function() { | ||||
|     if (document.visibilityState === 'visible') { | ||||
|       autoRefresh() | ||||
|     } | ||||
|   }) | ||||
							
								
								
									
										260
									
								
								static-data/default-plugins/circles/web/board.js
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										260
									
								
								static-data/default-plugins/circles/web/board.js
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,260 @@ | |||
| /* | ||||
|     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/>.
 | ||||
| */ | ||||
| requested = [] | ||||
| newPostForm = document.getElementById('addMsg') | ||||
| firstLoad = true | ||||
| lastLoadedBoard = 'global' | ||||
| loadingMessage = document.getElementById('loadingBoard') | ||||
| loadedAny = false | ||||
| loadingTimeout = 8000 | ||||
| 
 | ||||
| let toggleLoadingMessage = function(){ | ||||
|     switch (loadingMessage.style.display){ | ||||
|         case "inline-block": | ||||
|             loadingMessage.style.display = "none" | ||||
|             break; | ||||
|         default: | ||||
|             loadingMessage.style.display = "initial" | ||||
|             break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| fetch('/circles/version', { | ||||
|     method: 'GET', | ||||
|     headers: { | ||||
|       "token": webpass | ||||
| }}) | ||||
| .then((ver) => ver.text()) | ||||
| .then(function(ver) { | ||||
|     document.getElementById('circlesVersion').innerText = ver | ||||
| }) | ||||
| 
 | ||||
| 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
 | ||||
| 
 | ||||
|     var humanDate = new Date(0) | ||||
|     var msgDate = msg['meta']['time'] | ||||
|     var feed = document.getElementById("feed") | ||||
|     var beforeEl = null | ||||
| 
 | ||||
|     if (msgDate === undefined){ | ||||
|         msgDate = 'unknown' | ||||
|     } else { | ||||
|         humanDate.setUTCSeconds(msgDate) | ||||
|         msgDate = humanDate.toLocaleString("en-US", {timeZone: "Etc/GMT"}) | ||||
|     } | ||||
| 
 | ||||
|     var el = document.createElement('div') | ||||
|     el.innerText = msg['content'] | ||||
| 
 | ||||
|     if (beforeHash !== null) { | ||||
|         for (i = 0; i < feed.children.length; i++) { | ||||
|             if (feed.children[i].getAttribute('data-bl') === beforeHash) { | ||||
|                 beforeEl = feed.children[i] | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* 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
 | ||||
|         var template = document.getElementById('cMsgTemplate') | ||||
| 
 | ||||
|         // Clone the new row and insert it into the table
 | ||||
|         var clone = document.importNode(template.content, true) | ||||
|         var div = clone.querySelectorAll("div") | ||||
|         var identicon = clone.querySelectorAll("img") | ||||
| 
 | ||||
|         div[0].classList.add('entry') | ||||
|         div[0].setAttribute('timestamp', msg['meta']['time']) | ||||
| 
 | ||||
|         div[0].setAttribute('data-bl', blockHash) | ||||
|         div[2].textContent = msg['content'] | ||||
|         if (typeof msg['meta']['signer'] != 'undefined' && msg['meta']['signer'].length > 0){ | ||||
|             div[3].textContent = msg['meta']['signer'].substr(0, 5) | ||||
|             setHumanReadableIDOnPost(div[3], msg['meta']['signer']) | ||||
|             div[3].title = msg['meta']['signer'] | ||||
|             userIcon(msg['meta']['signer']).then(function(data){ | ||||
|                 identicon[0].src = "data:image/svg+xml;base64," + data | ||||
|             }) | ||||
|         } | ||||
|         else{ | ||||
|             identicon[0].remove() | ||||
|         } | ||||
|         div[4].textContent = msgDate | ||||
| 
 | ||||
|         loadingMessage.style.display = "none" | ||||
|         loadedAny = true | ||||
|         if (firstLoad){ | ||||
|             //feed.appendChild(clone)
 | ||||
|             feed.prepend(clone) | ||||
|             firstLoad = false | ||||
|         } | ||||
|         else{ | ||||
|             if (beforeEl === null){ | ||||
|                 feed.prepend(clone) | ||||
|             } | ||||
|             else{ | ||||
|                 beforeEl.insertAdjacentElement("beforebegin", clone.children[0]) | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function getBlocks(){ | ||||
|     var feed = document.getElementById("feed") | ||||
|     var ch = document.getElementById('feedIDInput').value | ||||
|     if (lastLoadedBoard !== ch){ | ||||
|         requested = [] | ||||
| 
 | ||||
|         toggleLoadingMessage() | ||||
|         loadedAny = false | ||||
| 
 | ||||
|         while (feed.firstChild) feed.removeChild(feed.firstChild); // remove all messages from feed
 | ||||
| 
 | ||||
|         setTimeout(function(){ | ||||
|             if (! loadedAny && ch == document.getElementById('feedIDInput').value){ | ||||
|                 PNotify.notice("There are no posts for " + ch + ". You can be the first!") | ||||
|             } | ||||
|         }, loadingTimeout) | ||||
|     } | ||||
| 
 | ||||
|     lastLoadedBoard = ch | ||||
|     if (document.getElementById('none') !== null){ | ||||
|         document.getElementById('none').remove(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     fetch('/circles/getpostsbyboard/' + ch, { | ||||
|         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); | ||||
|             } | ||||
|         } | ||||
|         sortEntries() | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| function loadMessage(blockHash, blockList, count, channel){ | ||||
|     if (blockHash == '0000000000000000000000000000000000000000000000000000000000000000'){ | ||||
|         return | ||||
|     } | ||||
|     fetch('/getblockdata/' + blockHash, { | ||||
|         method: 'GET', | ||||
|         headers: { | ||||
|           "token": webpass | ||||
|     }}).then(function(response) { | ||||
|         if (!response.ok) { | ||||
|             let on404 = function() { | ||||
|             if (response.status == 404){ | ||||
|                 fetch('/circles/removefromcache/' + channel + '/' + blockHash, { | ||||
|                     method: 'POST', | ||||
|                     headers: { | ||||
|                         "content-type": "application/json", | ||||
|                         "token": webpass | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|             else{ | ||||
|                 console.log(error) | ||||
|             } | ||||
|             }() | ||||
|             return | ||||
|         } | ||||
|         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; | ||||
|     }) | ||||
| } | ||||
| 
 | ||||
| document.getElementById('refreshFeed').onclick = function() { | ||||
|     getBlocks() | ||||
| } | ||||
| 
 | ||||
| newPostForm.onsubmit = function(){ | ||||
|     var message = document.getElementById('newMsgText').value | ||||
|     var channel = document.getElementById('feedIDInput').value | ||||
|     var meta = {'ch': channel} | ||||
|     let doSign = document.getElementById('postAnon').checked | ||||
|     var postData = {'message': message, 'sign': doSign, 'type': 'brd', 'encrypt': false, 'meta': JSON.stringify(meta)} | ||||
|     postData = JSON.stringify(postData) | ||||
|     newPostForm.style.display = 'none' | ||||
|     fetch('/insertblock', { | ||||
|         method: 'POST', | ||||
|         body: postData, | ||||
|         headers: { | ||||
|           "content-type": "application/json", | ||||
|           "token": webpass | ||||
|         } | ||||
|     }) | ||||
|     .then((resp) => resp.text()) | ||||
|     .then(function(data) { | ||||
|         newPostForm.style.display = 'block' | ||||
|         if (data == 'failure due to duplicate insert'){ | ||||
|             PNotify.error({ | ||||
|                 text: "This message is already queued" | ||||
|             }) | ||||
|             return | ||||
|         } | ||||
|         PNotify.success({ | ||||
|             text: "Message queued for posting" | ||||
|         }) | ||||
|         setTimeout(function(){getBlocks()}, 500) | ||||
|     }) | ||||
|     return false | ||||
| } | ||||
| 
 | ||||
| resetCirclePickers = function(){ | ||||
|     document.getElementById('recommendedBoards').value = "" | ||||
|     document.getElementById('popularBoards').value = "" | ||||
| } | ||||
| 
 | ||||
| document.getElementById('feedIDInput').onchange = resetCirclePickers | ||||
| 
 | ||||
|  | @ -0,0 +1,26 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Handle default board picker | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| 
 | ||||
| recommendedIDs = document.getElementById('recommendedBoards') | ||||
| 
 | ||||
| recommendedIDs.onchange = function(){ | ||||
|     document.getElementById('feedIDInput').value = recommendedIDs.value | ||||
|     getBlocks() | ||||
|     resetCirclePickers() | ||||
| } | ||||
|  | @ -0,0 +1,35 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     detect for Circles if plaintext insert/storage is enabled | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| plaintext_enabled = null | ||||
| 
 | ||||
| fetch('/config/get/general.store_plaintext_blocks', { | ||||
|     method: 'GET', | ||||
|     headers: { | ||||
|       "token": webpass | ||||
|     }}) | ||||
| .then((resp) => resp.text()) | ||||
| .then(function(data) { | ||||
|     plaintext_enabled = true | ||||
|     if (data == "false"){ | ||||
|         plaintext_enabled = false | ||||
|         PNotify.error({ | ||||
|             text: "Plaintext storage is disabled. You will not be able to see new posts or make posts yourself" | ||||
|         }) | ||||
|     } | ||||
| }) | ||||
							
								
								
									
										196
									
								
								static-data/default-plugins/circles/web/index.html
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										196
									
								
								static-data/default-plugins/circles/web/index.html
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,196 @@ | |||
| <!DOCTYPE HTML> | ||||
| <html> | ||||
| 
 | ||||
| <head> | ||||
|     <meta charset='utf-8'> | ||||
|     <!--Mobile responsive--> | ||||
|     <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||
|     <title> | ||||
|         Circles | ||||
|     </title> | ||||
|     <link rel="shortcut icon" type="image/ico" href="/shared/images/favicon.ico"> | ||||
|     <link rel="stylesheet" href="/shared/main/PNotifyBrightTheme.css"> | ||||
|     <link rel="stylesheet" href="/shared/fontawesome-free-5.10.2/css/all.min.css"> | ||||
|     <link rel="stylesheet" href="/gettheme"> | ||||
|     <link rel="stylesheet" href="theme.css"> | ||||
|     <script defer src="/shared/base32.js"></script> | ||||
|     <script defer src="/shared/identicon.js"></script> | ||||
|     <script defer src="/shared/node_modules/pnotify/dist/iife/PNotify.js"></script> | ||||
|     <script defer src="/shared/node_modules/pnotify/dist/iife/PNotifyButtons.js"></script> | ||||
|     <script defer src="/shared/useridenticons.js"></script> | ||||
|     <script defer src="/shared/misc.js"></script> | ||||
|     <script defer src="/shared/navbar.js"></script> | ||||
|     <script defer src="/shared/main/apicheck.js"></script> | ||||
|     <script defer src="detect-plaintext-storage.js"></script> | ||||
|     <script defer src="sethumanreadable.js"></script> | ||||
|     <script defer src="default-circle-picker.js"></script> | ||||
|     <script defer src="sort-posts.js"></script> | ||||
|     <script defer src="board.js"></script> | ||||
|     <script defer src="autorefresh.js"></script> | ||||
|     <script defer src="popular.js"></script> | ||||
| </head> | ||||
| 
 | ||||
| <body> | ||||
|     <nav class="navbar is-dark" role="navigation" aria-label="main navigation"> | ||||
|         <div class="navbar-brand"> | ||||
|             <a class="navbar-item idLink" href="/"> | ||||
|                 <img src="/shared/images/favicon.ico" class="navbarLogo"> | ||||
|             </a> | ||||
| 
 | ||||
|             <a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" | ||||
|                 data-target="navbarBasic"> | ||||
|                 <span aria-hidden="true"></span> | ||||
|                 <span aria-hidden="true"></span> | ||||
|                 <span aria-hidden="true"></span> | ||||
|             </a> | ||||
|         </div> | ||||
| 
 | ||||
|         <div id="navbarBasic" class="navbar-menu"> | ||||
|             <div class="navbar-start"> | ||||
|                 <a class="navbar-item idLink" href="/mail/">Mail</a> | ||||
|                 <a class="navbar-item idLink" href="/friends/">Friends</a> | ||||
|                 <a class="navbar-item idLink" href="/board/">Circles</a> | ||||
|             </div> | ||||
|         </div> | ||||
|     </nav> | ||||
| 
 | ||||
|     <!--Hero (Dark Section)--> | ||||
|     <section class="hero is-small is-dark"> | ||||
|         <div class="hero-body"> | ||||
|             <div class="container"> | ||||
|                 <div class="columns"> | ||||
|                     <div class="column"> | ||||
|                         <h1 class="title"> | ||||
|                             Circles <span class="is-pulled-right">v<span id='circlesVersion'></span></span> | ||||
|                         </h1> | ||||
|                         <h2 class="subtitle"> | ||||
|                             Anonymous message boards | ||||
|                         </h2> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|     </section> | ||||
| 
 | ||||
|     <br> | ||||
| 
 | ||||
|     <!--Start Content--> | ||||
|     <div class="container"> | ||||
|         <div class="columns"> | ||||
|             <!--Add Friend--> | ||||
|             <div class="column is-one-third"> | ||||
|                 <div class="card"> | ||||
|                     <form method='POST' action='/' id='addMsg'> | ||||
|                         <header class="card-header"> | ||||
|                             <p class="card-header-title"> | ||||
|                                 Post message | ||||
|                             </p> | ||||
|                         </header> | ||||
|                         <div class="card-content"> | ||||
|                             <div class="content"> | ||||
|                                     <textarea id='newMsgText' class="textarea" name='newMsgText' rows=10 cols=50 required | ||||
|                                         minlength="2"></textarea> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <footer class="card-footer"> | ||||
|                             <a class="card-footer-item"> | ||||
|                                 <input class='button is-primary' type='submit' value='Post'> | ||||
|                             </a> | ||||
|                         </footer> | ||||
|                     </form> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <!--Feed--> | ||||
|             <div class="column"> | ||||
|                 <div class="card"> | ||||
|                     <header class="card-header"> | ||||
|                         <p class="card-header-title"> | ||||
|                             Feed | ||||
|                         </p> | ||||
|                     </header> | ||||
|                     <div class="card-content"> | ||||
|                         <div class="content"> | ||||
|                             <div class="field"> | ||||
|                                 <div class="field has-addons"> | ||||
|                                     <p class="control"> | ||||
|                                         <a class="button is-static">Circle Name</a> | ||||
|                                     </p> | ||||
|                                     <p class="control is-expanded"> | ||||
|                                         <input id="feedIDInput" class="input" placeholder="Board name" value="global"> | ||||
|                                     </p> | ||||
|                                     <p class="control"> | ||||
|                                         <a class="button is-success" id="refreshFeed">Refresh Feed</a> | ||||
|                                     </p> | ||||
|                                 </div> | ||||
|                                 <div class="field"> | ||||
|                                     <div class="columns"> | ||||
|                                         <div class="column is-2"> | ||||
|                                             <div class="control"> | ||||
|                                                 <label for="recommendedBoards" class="label">Default Circles:</label> | ||||
|                                                 <div class="select"> | ||||
|                                                     <select id="recommendedBoards"> | ||||
|                                                         <option value=""></option> | ||||
|                                                         <option value="global">Global</option> | ||||
|                                                         <option value="onionr">Onionr</option> | ||||
|                                                         <option value="games">Games</option> | ||||
|                                                         <option value="politics">Politics</option> | ||||
|                                                         <option value="tech">Tech</option> | ||||
|                                                         <option value="random">Random</option> | ||||
|                                                         <option value="privacy">Privacy</option> | ||||
|                                                     </select> | ||||
|                                                 </div> | ||||
|                                             </div> | ||||
|                                         </div> | ||||
|                                         <div class="column is-2"> | ||||
|                                             <div class="control"> | ||||
|                                                 <label for="popularBoards" class="label">Popular Circles:</label> | ||||
|                                                 <div class="select"> | ||||
|                                                     <select id="popularBoards"> | ||||
|                                                         <option value="">       </option> | ||||
|                                                     </select> | ||||
|                                                 </div> | ||||
|                                             </div> | ||||
|                                         </div> | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                                 <p class="control"> | ||||
|                                     <br> | ||||
|                                         Note: All posts in Circles are publicly accessible. | ||||
|                                 </p> | ||||
|                                 <input type="checkbox" class="checkbox" id="refreshCheckbox" checked> | ||||
|                                 <label for="refreshCheckbox">Auto refresh feed</label> | ||||
|                                 <br> | ||||
|                                 <input type="checkbox" class="checkbox" id="postAnon" checked> | ||||
|                                 <label for="postAnon">Sign posts</label> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <div class="content"> | ||||
|                             <span id='loadingBoard'><i class="fas fa-yin-yang fa-spin"></i></span> | ||||
|                             <div id='feed'> | ||||
|                                 <span id='none'>None yet, try refreshing 😃</span> | ||||
|                                 <!--Message Items are appended here based on template--> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| 
 | ||||
|     <!--Template markup for Circle message--> | ||||
|     <template id="cMsgTemplate"> | ||||
|         <div class="box cMsgBox"> | ||||
|             <div class="columns"> | ||||
|                 <div class="column cMsg"> | ||||
|                     Message | ||||
|                 </div> | ||||
|                 <div class="column cAuthor is-narrow"></div> | ||||
|                 <img class="identicon image is-48x48" alt="user icon" src="/shared/images/anon.svg"> | ||||
|                 <div class="column is-narrow cMsgDate"> | ||||
|                     Date | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </template> | ||||
| </body> | ||||
| 
 | ||||
| </html> | ||||
							
								
								
									
										45
									
								
								static-data/default-plugins/circles/web/popular.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								static-data/default-plugins/circles/web/popular.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Load popular boards and show them in the UI. Handle selections of popular boards. | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| fetch('/circles/getpopular/8', { | ||||
|     method: 'GET', | ||||
|     headers: { | ||||
|       "token": webpass | ||||
| }}) | ||||
| .then((popular) => popular.text()) | ||||
| .then(function(popular) { | ||||
|     var popularSelect = document.getElementById('popularBoards') | ||||
|     let boards = popular.split(',') | ||||
|     for (board of boards){ | ||||
|         let newOption = document.createElement('option') | ||||
|         if (board == ""){continue} | ||||
|         newOption.value = board | ||||
|         newOption.innerText = board.charAt(0).toUpperCase() + board.slice(1) | ||||
|         console.debug(board) | ||||
|         popularSelect.appendChild(newOption) | ||||
|     } | ||||
| }) | ||||
| 
 | ||||
| document.getElementById('popularBoards').onchange = function(){ | ||||
|     document.getElementById('feedIDInput').value = document.getElementById('popularBoards').value | ||||
|     getBlocks() | ||||
|     resetCirclePickers() | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										39
									
								
								static-data/default-plugins/circles/web/sethumanreadable.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								static-data/default-plugins/circles/web/sethumanreadable.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Set human readable public keys onto post author elements | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| humanReadableKeys = {} | ||||
| 
 | ||||
| function setHumanReadableIDOnPost(el, key){ | ||||
|     if (typeof humanReadableKeys[key] == "undefined"){ | ||||
|         fetch('/getHumanReadable/' + key, { | ||||
|             method: 'GET', | ||||
|             headers: { | ||||
|               "token": webpass | ||||
|             }}) | ||||
|         .then((resp) => resp.text()) // Transform the data into json
 | ||||
|         .then(function(data) { | ||||
|             if (data.includes('HTML')){ | ||||
|                 return | ||||
|             } | ||||
|             humanReadableKeys[key] = data | ||||
|             setHumanReadableIDOnPost(el, key) | ||||
|         }) | ||||
|         return | ||||
|     } | ||||
|     el.innerText = humanReadableKeys[key].split('-').slice(0, 3).join(' ') | ||||
| } | ||||
							
								
								
									
										30
									
								
								static-data/default-plugins/circles/web/sort-posts.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								static-data/default-plugins/circles/web/sort-posts.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /* | ||||
|     Onionr - Private P2P Communication | ||||
| 
 | ||||
|     Sort post entries | ||||
| 
 | ||||
|     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/>.
 | ||||
| */ | ||||
| 
 | ||||
| function sortEntries() { | ||||
|     var entries = document.getElementsByClassName('entry') | ||||
| 
 | ||||
|     if (entries.length > 1) { | ||||
|         const sortBy = 'timestamp' | ||||
|         const parent = entries[0].parentNode | ||||
| 
 | ||||
|         const sorted = Array.from(entries).sort((a, b) => b.getAttribute(sortBy) - a.getAttribute(sortBy)) | ||||
|         sorted.forEach(element => parent.appendChild(element)) | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								static-data/default-plugins/circles/web/theme.css
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										11
									
								
								static-data/default-plugins/circles/web/theme.css
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,11 @@ | |||
| 
 | ||||
| .cMsg{ | ||||
|     word-wrap:break-word; | ||||
|     word-break:break-word; | ||||
|     white-space: pre-wrap; | ||||
| } | ||||
| 
 | ||||
| body{ | ||||
|     background-color: #212224; | ||||
|     color: white; | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue