Compare commits

...

13 Commits

3 changed files with 421 additions and 0 deletions

2
.gitignore vendored
View File

@@ -168,3 +168,5 @@ cython_debug/
**/IntegrationServer/XAStore/
**/IntegrationServer/packages/Wm*/
fontawesome
.DS_Store

204
index.html Normal file
View File

@@ -0,0 +1,204 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TootKomm</title>
</head>
<body>
<header>
</header>
<main id="comments">
<link rel="stylesheet" href="fontawesome/css/all.css">
<link rel="stylesheet" href="style.css?v=1.22">
<header>
<h1>Comments from the Fediverse</h1>
<button onclick="showHideAll()" class="hide" title="Show/Hide all statuses"></button></header>
</main>
<footer>
</footer>
<script>
function buildCommentTree(statusID){
const target = document.querySelector('#comments');
buildStatus(target, statusID);
buildDescendants(target, statusID);
}
async function getJSONObject(url){
const requestURL = url;
const request = new Request(requestURL);
const response = await fetch(request);
return await response.json();
}
async function buildArticle(target, mastopost) {
const article = document.createElement('article');
populateHeader(article, mastopost);
populateSection(article, mastopost);
populateAside(article, mastopost);
populateFooter(article, mastopost);
target.appendChild(article);
}
async function buildStatus(target, statusID) {
const url = buildStatusURL(statusID);
const mastopost = await getJSONObject(url);
buildArticle(target, mastopost);
}
async function buildDescendants(target, statusID){
const url = buildStatusURL(statusID);
const contextURL = url+'/context';
const context = await getJSONObject(contextURL);
const sorted_descendants = context.descendants.sort(
function (a, b) {
aDate = new Date(a.created_at).getTime();
bDate = new Date(b.created_at).getTime();
diff = aDate - bDate;
return diff;
});
for (const descendant of sorted_descendants) {
buildArticle(target, descendant);
}
}
function populateHeader(item, obj) {
const myHeader = document.createElement('header');
const myDateTime = document.createElement('time');
const link = document.createElement('a');
link.href = obj.url;
myDateTime.datetime = obj.created_at;
creation_date = new Date(obj.created_at);
myDateTime.textContent = creation_date.toLocaleString('de-DE',{ day: "2-digit", month: "short", year: "numeric", hour:"2-digit", minute:"2-digit"});
if(obj.spoiler_text.length > 0){
const myCW = document.createElement('summary');
const myButton = document.createElement('button');
myButton.addEventListener("click", showHide);
myButton.title = "Show/Hide Content";
// myButton.textContent = "\u{1F648}";
myCW.textContent = obj.spoiler_text;
myButton.classList.add("hide");
myHeader.appendChild(myCW);
myHeader.appendChild(myButton);
}
myHeader.appendChild(link).appendChild(myDateTime);
item.appendChild(myHeader);
}
function populateSection(item, obj){
const mySection = document.createElement('section');
mySection.innerHTML = `${obj['content']}`;
if(obj.spoiler_text.length > 0){
mySection.style.display="none";
}
item.appendChild(mySection);
}
function populateAside(item, obj){
const aside = document.createElement('aside');
const myImg = document.createElement('img');
myImg.src = obj['account']['avatar'];
myDate = new Date(obj.account['created_at']);
aside.appendChild(myImg);
const myH = document.createElement('hgroup');
const myP = document.createElement('div');
myH.innerHTML = `<h1>${obj.account['display_name']}</h1> <h2>(<a href="${obj.account.url}">${obj.account['username']}</a>)</h2>`;
myP.innerHTML = `<time datetime="${obj.account['created_at']}">since ${myDate.toLocaleDateString('de-DE',{ day: "2-digit", month: "short", year: "numeric"})}</time>`;
aside.appendChild(myH);
aside.appendChild(myP);
item.appendChild(aside);
}
function populateFooter(item, obj){
const footer = document.createElement('footer');
const stats = document.createElement('ul');
stats.innerHTML = `<li class="replies fa-solid fa-retweet" title="Replies">${obj.replies_count}</li><li class="favs fa-solid fa-star" title="Favorites">${obj.favourites_count}</li><li class="boosts fa-solid fa-share" title="Boosts">${obj.reblogs_count}</li>`;
footer.appendChild(stats);
item.appendChild(footer);
}
function buildStatusURL(statusID) {
const apiURL = 'https://social.tchncs.de/api/v1/statuses/';
return apiURL + statusID;
}
buildCommentTree("107735248507147283");
// buildCommentTree("107724981153178707");
function showHide(){
button = event.srcElement;
article = button.parentNode.parentNode;
section = article.querySelector('section');
if( section.style.display == "none" ){
section.style.display = "block";
button.classList.add("show");
button.classList.remove("hide");
}
else {
section.style.display = "none";
button.classList.add("hide");
button.classList.remove("show");
}
}
function showHideAll(){
button = event.srcElement;
commentArea = document.getElementById('comments');
articles = commentArea.querySelectorAll('article section');
if( button.classList.contains("hide") ) {
for( article of articles ) {
article.style.display = "block";
button.classList.add("show");
button.classList.remove("hide");
article.parentNode.querySelector("button").classList.add("show");
article.parentNode.querySelector("button").classList.remove("hide");
}
}
else {
for( article of articles ) {
article.style.display = "none";
button.classList.add("hide");
button.classList.remove("show");
article.parentNode.querySelector("button").classList.add("hide");
article.parentNode.querySelector("button").classList.remove("show");
}
}
}
</script>
</body>
</html>

215
style.css Normal file
View File

@@ -0,0 +1,215 @@
/* || general styles */
html {
font-family: monospace, sans-serif;
font-weight: thin;
}
#comments > a {
text-decoration: none;
}
#comments > header {
display:grid;
grid-template-areas:
"title button";
grid-template-columns: 4fr 1fr;
width:40em;
background: #282c37;
padding: 0.5em 0.25em 0.5em 0.25em;
}
#comments > header > h1 {
grid-area: title;
color: #b4b5ba;
text-shadow:2px 2px #424553;
font-size: 1em;
font-variant:oblique;
font-weight:thin;
padding-left:1em;
}
#comments > header > button {
grid-area:button;
}
time {
display:inline-block;
font-size: 0.7em;
color:#b4b5ba;
}
article {
font-family: monospace, sans-serif;
color: #fff;
background:#313543;
display: grid;
grid-template-areas:
"profile header "
"profile content"
"footer footer";
grid-template-columns: 1fr 3fr;
gap: 0.5em;
width: 40em;
padding: 1em 0.25em 0em 0.25em;
}
article a {
color: #4d9fdb;
}
article header {
width:100%;
grid-area: header;
display:grid;
grid-template-areas:
"cw button";
grid-template-columns: 3fr 1fr;
}
article header summary {
grid-area: cw;
font-weight: 300;
width:100%;
}
article header time {
width:100%;
padding-right:1em;
}
header button {
grid-area: button;
width: 2em;
height: 1.5em;
background: #313543;
border:solid thin #b4b5ba;
border-radius: 10px;
color:#b4b5ba;
}
header button.show {
font-size: 2em;
}
header button.show:before {
content: "\1F648";
}
header button.hide {
font-size: 2em;
}
header button.hide:before {
content: "\1F649";
}
article aside {
grid-area: profile;
text-align:center;
overflow-wrap: anywhere;
}
article aside h1 {
font-size: 1em;
font-weight: 300;
padding:0.25em; margin-bottom:0;
}
article aside h2 {
font-size: 0.8em;
font-weight: 200;
padding:0.25em; margin:0;
}
article aside h2 > a {
color: #fff;
font-style: oblique;
}
article aside h2 > a:before {
content: "@";
}
article aside img {
max-width: 100px;
}
article > aside > div {
}
article > aside > div > time {
}
article section {
grid-area: content;
}
article > footer {
grid-area: footer;
background: #282c37;
}
article > footer > ul {
width: 100%;
display: grid;
grid-template-areas:
"replies favs boosts";
grid-template-columns: 1fr 1fr 1fr;
gap:0em;
list-style-type: none;
}
article > footer > ul > li:before {
padding:0 1em;
}
article > footer > ul > li.replies {
grid-area: replies;
}
article > footer > ul > li.replies:before {
content: '\1F4AC';
}
article > footer > ul > li.favs {
grid-area: favs;
}
article > footer > ul > li.favs:before {
content:'\2B50';
}
article > footer > ul > li.boosts {
grid-area: boosts;
}
article > footer > ul > li.boosts:before {
content:'\1F680';
}
strong, b {
font-weight: 300;
}
.hashtag {
text-decoration:none;
}