singularity/main.js

287 lines
8.0 KiB
JavaScript
Raw Normal View History

2024-07-14 02:46:48 +02:00
var users = [];
var posts = {};
2024-07-17 01:08:03 +02:00
const blockContainer = document.getElementById("block-container");
2024-07-11 22:19:51 +02:00
const postCountElem = document.getElementById("post-count");
const postTotalElem = document.getElementById("post-total");
2024-07-11 21:13:17 +02:00
const loader = document.getElementById("loader");
2024-07-11 22:19:51 +02:00
// then we'll define a variable for how many posts we want to increase the
2024-07-11 21:13:17 +02:00
// page by
2024-07-11 22:19:51 +02:00
const postIncrease = 9;
2024-07-11 21:13:17 +02:00
// and define a value to determine which page we're on
let currentPage = 1;
2024-07-20 13:55:10 +02:00
// how many times can we increase the content until we reach the max limit?
function getPageCount() {
return Math.ceil(Object.keys(posts).length / postIncrease);
}
2024-07-11 21:13:17 +02:00
function getRandomColor() {
const h = Math.floor(Math.random() * 360);
return `hsl(${h}deg, 90%, 85%)`;
}
2024-07-11 22:19:51 +02:00
class Post {
2024-07-14 02:46:48 +02:00
constructor(data) {
this.id = data.id;
this.username = data.associatedUser;
this.content = data.body;
this.replyTo = data.replyTo;
this.replies = []
}
getIsReply() {
return this.replyTo != "";
}
addReply(reply) {
this.replies.push(reply);
2024-07-11 22:19:51 +02:00
}
getElement() {
const postElem = document.createElement("div");
2024-07-18 02:16:52 +02:00
postElem.className = "block post";
2024-07-11 22:19:51 +02:00
postElem.style.backgroundColor = getRandomColor();
// add a header to the post
const headerElem = document.createElement("h1");
headerElem.innerHTML = this.username;
2024-07-11 23:53:45 +02:00
const profileLinkElem = document.createElement("a");
profileLinkElem.setAttribute("href", "#");
profileLinkElem.addEventListener("click", () => updateUserProfile(this.username));
profileLinkElem.appendChild(headerElem);
postElem.appendChild(profileLinkElem);
2024-07-11 22:19:51 +02:00
const contentElem = document.createElement("p");
contentElem.innerHTML = this.content;
postElem.appendChild(contentElem);
2024-07-14 02:46:48 +02:00
for (let i = 0; i < this.replies.length; i++) {
const reply = this.replies[i];
2024-07-13 02:45:55 +02:00
const commentElem = document.createElement("div");
commentElem.style.backgroundColor = getRandomColor();
const commentUserElem = document.createElement("h2");
2024-07-14 02:46:48 +02:00
commentUserElem.innerHTML = reply.username;
2024-07-13 02:45:55 +02:00
commentElem.appendChild(commentUserElem);
const commentContentElem = document.createElement("p");
2024-07-14 02:46:48 +02:00
commentContentElem.innerHTML = reply.content;
2024-07-13 02:45:55 +02:00
commentElem.appendChild(commentContentElem);
postElem.appendChild(commentElem);
2024-07-14 02:46:48 +02:00
// TODO: indent 2nd-level replies
for (let j = 0; j < reply.replies.length; j++) {
const replyReply = reply.replies[j];
const replyReplyElem = document.createElement("div");
replyReplyElem.style.backgroundColor = getRandomColor();
const replyReplyUserElem = document.createElement("h3");
replyReplyUserElem.innerHTML = replyReply.username;
replyReplyElem.appendChild(replyReplyUserElem);
const replyReplyContentElem = document.createElement("p");
replyReplyContentElem.innerHTML = replyReply.content;
replyReplyElem.appendChild(replyReplyContentElem);
postElem.appendChild(replyReplyElem);
}
2024-07-13 02:45:55 +02:00
}
2024-07-11 22:19:51 +02:00
return postElem;
}
}
2024-07-14 02:46:48 +02:00
function getRootPosts() {
let result = [];
for (var id in posts) {
const post = posts[id];
if (post.getIsReply())
continue;
result.push(post);
}
return result;
2024-07-11 21:13:17 +02:00
}
2024-07-11 22:19:51 +02:00
function addPosts(pageIdx) {
2024-07-11 21:13:17 +02:00
currentPage = pageIdx;
2024-07-11 22:19:51 +02:00
const startRange = (pageIdx - 1) * postIncrease;
2024-07-20 13:55:10 +02:00
const endRange = currentPage == getPageCount()
? posts.length
2024-07-11 22:19:51 +02:00
: pageIdx * postIncrease;
2024-07-11 21:13:17 +02:00
2024-07-11 22:19:51 +02:00
postCountElem.innerHTML = endRange;
2024-07-11 21:13:17 +02:00
2024-07-14 02:46:48 +02:00
const rootPosts = getRootPosts();
2024-07-11 21:13:17 +02:00
for (let i = startRange + 1; i <= endRange; i++) {
2024-07-17 01:08:03 +02:00
blockContainer.appendChild(rootPosts[i].getElement());
2024-07-11 21:13:17 +02:00
}
}
function handleInfiniteScroll() {
throttle(() => {
const endOfPage = window.innerHeight + window.pageYOffset >= document.body.offsetHeight;
if (endOfPage) {
2024-07-11 22:19:51 +02:00
addPosts(currentPage + 1);
2024-07-11 21:13:17 +02:00
}
2024-07-20 13:55:10 +02:00
if (currentPage === getPageCount()) {
2024-07-11 21:13:17 +02:00
removeInfiniteScroll();
}
}, 1000);
}
2024-07-11 22:19:51 +02:00
// limit how often we try to load new posts to maintain browser performance
2024-07-11 21:13:17 +02:00
var throttleTimer;
function throttle(callback, time) {
if (throttleTimer) return;
throttleTimer = true;
setTimeout(() => {
callback();
throttleTimer = false;
}, time);
}
function removeInfiniteScroll() {
loader.remove();
window.removeEventListener("scroll", handleInfiniteScroll);
}
2024-07-18 02:16:52 +02:00
function writePost() {
// TODO: inject a new post element at the top of the feed
console.log("write something interesting");
setTimeout(() => {
}, 500);
const userName = "theChief";
fetch("https://api.wayfarer.games/singularity/generate-posts.php", {
method: "POST",
mode: "cors",
body: JSON.stringify({
"user": userName,
"interests": [
"gen-ai",
"blockchain",
"nfts"
],
"posting_style": "just the most truly inane takes"
}),
headers: {
"Content-type": "application/json; charset=UTF-8"
}
})
.then(response => response.json())
.then(json => {
// find the first post
const children = blockContainer.childNodes;
let firstPost = null;
for (let i = 0; i < children.length; i++) {
const child = children[i];
const classes = child.className.split(" ");
if (classes.some(c => c == "post")) {
firstPost = child;
break;
}
}
// generate a post to insert before the first post
const postData = {
id: json.id,
associatedUser: json.associatedUser,
body: json.body
};
const post = new Post(postData);
const postElem = post.getElement();
blockContainer.insertBefore(postElem, firstPost);
console.log(post);
});
}
2024-07-17 01:08:55 +02:00
function addWritePostBlock() {
const blockElem = document.createElement("div");
blockElem.className = "block";
blockElem.style.backgroundColor = "red";
const buttonElem = document.createElement("a");
buttonElem.setAttribute("href", "#");
buttonElem.innerHTML = "Write something interesting for me!";
2024-07-18 02:16:52 +02:00
buttonElem.addEventListener("click", writePost);
2024-07-17 01:08:55 +02:00
blockElem.append(buttonElem);
blockContainer.append(blockElem)
}
2024-07-14 02:46:48 +02:00
function init() {
if (posts == undefined)
{
console.log("resource loading failed");
return;
}
// need to load all the resources first
2024-07-17 01:08:55 +02:00
const postCount = Object.keys(posts).length;
if (users.length == 0 || postCount == 0)
2024-07-14 02:46:48 +02:00
return;
2024-07-17 01:08:55 +02:00
console.log(`loaded ${users.length} users and ${postCount} posts`);
// TODO: add write post block
addWritePostBlock();
// TODO: add bio
2024-07-14 02:46:48 +02:00
addPosts(currentPage);
window.addEventListener("scroll", handleInfiniteScroll);
}
function loadDataFromEndpoint(endpoint, callback) {
fetch(endpoint)
.then(response => response.json())
.then(json => {
callback(json);
init();
});
}
2024-07-11 21:13:17 +02:00
2024-07-16 20:56:34 +02:00
loadDataFromEndpoint("https://api.wayfarer.games/singularity/users.json", json => { users = json.users; });
loadDataFromEndpoint("https://api.wayfarer.games/singularity/posts.json", json => {
2024-07-14 02:46:48 +02:00
// first pass to instantiate all the posts
for (let i = 0; i < json.content.length; i++) {
const post = new Post(json.content[i]);
posts[post.id] = post;
}
// second pass to link each reply to the appropriate parent
for (const id in posts) {
const post = posts[id];
if (!post.getIsReply())
continue;
const parent = posts[post.replyTo];
parent.addReply(post);
}
2024-07-20 13:55:10 +02:00
postTotalElem.innerHTML = Object.keys(posts).length;
2024-07-14 02:46:48 +02:00
});