import * as constant from "../entity/Constant.js";
-import { Fetcher } from "./Fetcher.js";
+ import { Fetcher } from "./Fetcher.js";
const NUM_POSTS = 50;
const API_V3 = "/api/v3/post/list?sort=Hot";
@@ -41,11 +40,17 @@ Source: fetchers/LemmyFetcher.js
const posts = [];
try {
const url = instanceUrl + API_V3 + "&limit=" + NUM_POSTS;
- const response = await fetch(url);
+
+ const timeoutDelay = 10000;
+ const response = await Promise.race([
+ fetch(url),
+ new Promise((_resolve, reject) => setTimeout(() => reject("Fetch calls timed out."), timeoutDelay)),
+ ]);
+
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
- let response_data = await response.json();
+ const response_data = await response.json();
const posts_json = response_data.posts;
posts_json.forEach((post) => {
posts.push(post);
@@ -74,7 +79,7 @@ Home
Classes
-
diff --git a/docs/fetchers_MastodonFetcher.js.html b/docs/fetchers_MastodonFetcher.js.html
index 7da1b43..682892a 100644
--- a/docs/fetchers_MastodonFetcher.js.html
+++ b/docs/fetchers_MastodonFetcher.js.html
@@ -26,11 +26,11 @@
Source: fetchers/MastodonFetcher.js
- import * as constant from "../entity/Constant.js";
-import { Fetcher } from "./Fetcher.js";
+ import { Fetcher } from "./Fetcher.js";
export const TAGS_SUFFIX = "/api/v1/trends/tags";
export const POST_SUFFIX = "/api/v1/timelines/tag/:";
+export const NUM_MASTODON_POSTS = 15;
export class MastodonFetcher extends Fetcher {
/**
@@ -40,12 +40,15 @@ Source: fetchers/MastodonFetcher.js
async fetchPosts(instURL) {
try {
const hashtags = await this.#fetchTrendingTags(instURL + TAGS_SUFFIX);
- const posts = [];
- for (const tag of hashtags) {
- console.log("Fetching posts for tag: " + tag.name);
- let response = await this.#fetchPostsByHashtag(instURL, tag.name);
- posts.push(...response);
- }
+ const fetchPromises = hashtags.map(tag => this.#fetchPostsByHashtag(instURL, tag.name));
+ const timeoutDelay = 10000;
+ const responses = await Promise.race(
+ [
+ Promise.all(fetchPromises),
+ new Promise((_resolve, reject) => setTimeout(() => reject("Fetch calls timed out."), timeoutDelay)),
+ ]);
+ const posts = responses.flat();
+ posts.push(...posts);
return posts;
}
catch (error) {
@@ -80,7 +83,7 @@ Source: fetchers/MastodonFetcher.js
* @returns {Promise<Array>} - A promise that resolves to an array of posts for the given hashtag
*/
async #fetchPostsByHashtag(instURL, hashtag) {
- const trendingPostURL = instURL + POST_SUFFIX + hashtag;
+ const trendingPostURL = instURL + POST_SUFFIX + hashtag + "?limit=" + NUM_MASTODON_POSTS;
try {
const response = await fetch(trendingPostURL);
if (!response.ok) {
@@ -110,7 +113,7 @@ Home
Classes
-
diff --git a/docs/global.html b/docs/global.html
index d645c81..0fcdd13 100644
--- a/docs/global.html
+++ b/docs/global.html
@@ -661,7 +661,7 @@
Parameters:
- Source:
@@ -844,7 +844,7 @@ Parameters:
- Source:
@@ -1296,7 +1296,7 @@ Parameters:
- Source:
@@ -1370,7 +1370,7 @@ Home
Classes
-
diff --git a/docs/index.html b/docs/index.html
index 2222c14..1df6885 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -56,7 +56,7 @@
Home
Classes
-
diff --git a/docs/instanceList.js.html b/docs/instanceList.js.html
index 1b3f129..07b68e6 100644
--- a/docs/instanceList.js.html
+++ b/docs/instanceList.js.html
@@ -27,8 +27,8 @@
Source: instanceList.js
export const DEFAULT_LISTS = {
- mastodon: ["https://mastodon.social", "https://fosstodon.org"],
- lemmy: ["https://lemmy.ml"],
+ mastodon: ["https://mastodon.social", "https://fosstodon.org", "https://mstdn.social", "https://mastodon.online", "https://mastodon.world"],
+ lemmy: ["https://lemmy.ml", "https://lemmy.world", "https://lemm.ee"],
};
const INST_LISTS = "instanceLists";
@@ -71,17 +71,9 @@ Source: instanceList.js
* @returns {Promise<boolean>} Promise which resolves to True if the instance addition was successful, False otherwise
*/
export async function addInstance(network, url, storage = localStorage) {
- // TODO: move validation out of this function? (may separate concerns better)
if (!(ALLOWED_NETWORKS.has(network)) || !validUrl(url)) return false;
- // Commented out because this creates CORS errors if not done exactly on API
- // try {
- // let response = await fetch(url);
- // if (response.status !== 200) return false;
- // } catch (_) {
- // return false;
- // }
-
- let instanceList = fetchInstanceLists(storage);
+
+ const instanceList = fetchInstanceLists(storage);
// network is already guaranteed to be in ALLOWED_NETWORKS and thus on the default list
instanceList[network].unshift(url);
storage.setItem(INST_LISTS, JSON.stringify(instanceList));
@@ -95,9 +87,9 @@ Source: instanceList.js
* @param {Storage} storage
*/
export function handleRemoveInstance(network, url, storage = localStorage) {
- let i = removeInstance(network, url, storage);
+ const i = removeInstance(network, url, storage);
if (i !== -1) {
- let list = document.getElementById(`${network}-instance-list`);
+ const list = document.getElementById(`${network}-instance-list`);
// first child will always be add instance input box
// index 0 of instance list will be child 1
list.removeChild(list.children[i + 1]);
@@ -111,9 +103,9 @@ Source: instanceList.js
* @returns {number} Index removed if successful, -1 otherwise
*/
export function removeInstance(network, url, storage = localStorage) {
- let instanceLists = fetchInstanceLists(storage);
+ const instanceLists = fetchInstanceLists(storage);
if (network in instanceLists && instanceLists[network].includes(url)) {
- let ind = instanceLists[network].indexOf(url);
+ const ind = instanceLists[network].indexOf(url);
instanceLists[network].splice(ind, 1);
saveLists(instanceLists, storage);
return ind;
@@ -150,7 +142,7 @@ Home
Classes
-
diff --git a/docs/js_doc_test.js.html b/docs/js_doc_test.js.html
index e7fd295..c2d5a1d 100644
--- a/docs/js_doc_test.js.html
+++ b/docs/js_doc_test.js.html
@@ -51,7 +51,7 @@
Home
Classes
-
diff --git a/docs/pageBuilder.js.html b/docs/pageBuilder.js.html
index 7a92249..8050840 100644
--- a/docs/pageBuilder.js.html
+++ b/docs/pageBuilder.js.html
@@ -47,26 +47,29 @@
Source: pageBuilder.js
nextPage.disabled = true;
prevPage.disabled = true;
- // TODO: sane pre-fetching solution that isn't just one instance
- let postsByNetwork = {};
+ const postsByNetwork = {};
let maxLengthArray = 0;
const instLists = fetchInstanceLists();
- for (let [network, instanceList] of Object.entries(instLists)) {
- let fetcher = new HANDLERS[network]["fetcher"]();
- let postBuilder = new HANDLERS[network]["postBuilder"]();
+ // Iterate over networks (currently just Mastodon and Lemmy)
+ for (const [network, instanceList] of Object.entries(instLists)) {
+ // Get object handlers for API and post formatting
+ const fetcher = new HANDLERS[network]["fetcher"]();
+ const postBuilder = new HANDLERS[network]["postBuilder"]();
postsByNetwork[network] = [];
- for (let url of instanceList) {
- let res = await fetcher.fetchPosts(url);
- for (let post of res) {
+ // Iterate over each network's instance list
+ for (const url of instanceList) {
+ const res = await fetcher.fetchPosts(url);
+ if (res === null) continue;
+ for (const post of res) {
postsByNetwork[network].push(postBuilder.buildPost(post));
}
}
maxLengthArray = Math.max(maxLengthArray, postsByNetwork[network].length);
}
- let posts = [];
+ const posts = [];
for (let i = 0; i < maxLengthArray; i++) {
- for (let [network, _] of Object.entries(instLists)) {
+ for (const [network] of Object.entries(instLists)) {
if (i < postsByNetwork[network].length) {
posts.push(postsByNetwork[network][i]);
}
@@ -101,7 +104,7 @@ Home
Classes
-
diff --git a/docs/paginator.js.html b/docs/paginator.js.html
index 8fb896c..a444154 100644
--- a/docs/paginator.js.html
+++ b/docs/paginator.js.html
@@ -26,9 +26,7 @@
Source: paginator.js
- import { Post } from "./entity/Post.js";
-
-const nextPage = document.getElementById("next-page");
+ const nextPage = document.getElementById("next-page");
const prevPage = document.getElementById("prev-page");
export class Paginator {
@@ -58,8 +56,9 @@ Source: paginator.js
* Display the page of items
*/
displayPage() {
- // Scroll to top of page once displayed
- window.scrollTo({ top: 0, behavior: "smooth" });
+ // Scroll to top of the page
+ document.body.scrollTop = 0; // Safari
+ document.documentElement.scrollTop = 0; // Chrome, Firefox, IE and Opera
// Clear the container
document.getElementById("featuredTagsPosts").innerHTML = "";
@@ -126,7 +125,7 @@ Home
Classes
-
diff --git a/docs/postBuilder_LemmyPostBuilder.js.html b/docs/postBuilder_LemmyPostBuilder.js.html
index cdd1d05..ca48131 100644
--- a/docs/postBuilder_LemmyPostBuilder.js.html
+++ b/docs/postBuilder_LemmyPostBuilder.js.html
@@ -46,7 +46,7 @@
Source: postBuilder/LemmyPostBuilder.js
* @returns {Object}- A Post element created from raw json data from the API
*/
buildPost(post) {
- let newPost = document.createElement("fedi-post");
+ const newPost = document.createElement("fedi-post");
newPost.setAttribute("id", post.post.id);
newPost.setAttribute("content", this.#extractPostContent(post.post)); // Either a url or body or both.
newPost.setAttribute("author-name", post.creator.name);
@@ -105,7 +105,7 @@ Home
Classes
-
diff --git a/docs/postBuilder_MastodonPostBuilder.js.html b/docs/postBuilder_MastodonPostBuilder.js.html
index 33dbb25..a47e6e7 100644
--- a/docs/postBuilder_MastodonPostBuilder.js.html
+++ b/docs/postBuilder_MastodonPostBuilder.js.html
@@ -29,22 +29,6 @@
Source: postBuilder/MastodonPostBuilder.js
import { PostBuilder } from "./PostBuilder.js";
export class MastodonPostBuilder extends PostBuilder {
- // TODO: review this function, remove if not needed
- #interleaveArrays(responses) {
- const maxLength = Math.max(...responses.map(response => response.length));
- const result = [];
-
- for (let i = 0; i < maxLength; i++) {
- for (let j = 0; j < responses.length; j++) {
- if (responses[j].length > i) {
- result.push(responses[j][i]);
- }
- }
- }
-
- return result;
- }
-
/**
*
* @param {Object} rawPost - The raw json data from the API
@@ -78,7 +62,7 @@ Home
Classes
-
diff --git a/docs/postBuilder_PostBuilder.js.html b/docs/postBuilder_PostBuilder.js.html
index 1567612..6f68610 100644
--- a/docs/postBuilder_PostBuilder.js.html
+++ b/docs/postBuilder_PostBuilder.js.html
@@ -37,7 +37,7 @@
Source: postBuilder/PostBuilder.js
/**
* @param {Object} rawPost - The raw json data from the API
*/
- buildPost(rawPost) {
+ buildPost() {
throw new Error("Not implemented - You must implement displayPost() in a subclass");
}
}
@@ -57,7 +57,7 @@ Home
Classes
-
diff --git a/docs/scripts_fetchers_Fetcher.js.html b/docs/scripts_fetchers_Fetcher.js.html
index d96e16f..4eb3eb6 100644
--- a/docs/scripts_fetchers_Fetcher.js.html
+++ b/docs/scripts_fetchers_Fetcher.js.html
@@ -54,7 +54,7 @@
Home
Classes
-
diff --git a/docs/scripts_fetchers_LemmyFetcher.js.html b/docs/scripts_fetchers_LemmyFetcher.js.html
index 2236c00..aad44bb 100644
--- a/docs/scripts_fetchers_LemmyFetcher.js.html
+++ b/docs/scripts_fetchers_LemmyFetcher.js.html
@@ -72,7 +72,7 @@
Home
Classes
-
diff --git a/docs/scripts_fetchers_MastodonFetcher.js.html b/docs/scripts_fetchers_MastodonFetcher.js.html
index 37fe47e..975b4b7 100644
--- a/docs/scripts_fetchers_MastodonFetcher.js.html
+++ b/docs/scripts_fetchers_MastodonFetcher.js.html
@@ -103,7 +103,7 @@
Home
Classes
-
diff --git a/docs/scripts_index.js.html b/docs/scripts_index.js.html
index 1127c78..b4133f5 100644
--- a/docs/scripts_index.js.html
+++ b/docs/scripts_index.js.html
@@ -111,7 +111,7 @@
Home
Classes
-
diff --git a/docs/scripts_paginator.js.html b/docs/scripts_paginator.js.html
index be09599..43b6a59 100644
--- a/docs/scripts_paginator.js.html
+++ b/docs/scripts_paginator.js.html
@@ -97,7 +97,7 @@
Home
Classes
-
diff --git a/docs/scripts_postBuilder_LemmyPostBuilder.js.html b/docs/scripts_postBuilder_LemmyPostBuilder.js.html
index e5df134..1286561 100644
--- a/docs/scripts_postBuilder_LemmyPostBuilder.js.html
+++ b/docs/scripts_postBuilder_LemmyPostBuilder.js.html
@@ -102,7 +102,7 @@
Home
Classes
-
diff --git a/docs/scripts_postBuilder_MastodonPostBuilder.js.html b/docs/scripts_postBuilder_MastodonPostBuilder.js.html
index d73d822..887bb23 100644
--- a/docs/scripts_postBuilder_MastodonPostBuilder.js.html
+++ b/docs/scripts_postBuilder_MastodonPostBuilder.js.html
@@ -78,7 +78,7 @@
Home
Classes
-
diff --git a/docs/scripts_postBuilder_PostBuilder.js.html b/docs/scripts_postBuilder_PostBuilder.js.html
index 280b5b4..b5ac58c 100644
--- a/docs/scripts_postBuilder_PostBuilder.js.html
+++ b/docs/scripts_postBuilder_PostBuilder.js.html
@@ -57,7 +57,7 @@
Home
Classes
-
diff --git a/index.html b/index.html
index b6d6f66..88e648f 100644
--- a/index.html
+++ b/index.html
@@ -3,6 +3,7 @@
+
@@ -12,19 +13,14 @@
- B L E N D
-
+ Blend
-
-
-
+
@@ -36,22 +32,15 @@ B L E N D
-
-
-
diff --git a/prototype/js/Post.js b/prototype/js/Post.js
index ac2e5c1..d5254e5 100644
--- a/prototype/js/Post.js
+++ b/prototype/js/Post.js
@@ -1,11 +1,10 @@
- export class Post {
-
+export class Post {
constructor(id, content, authorName, createdAt, authorImage) {
this.id = id;
this.content = content;
this.authorName = authorName; // Assuming 'author' is a simple string or object
this.createdAt = createdAt;
- this.authorImageURL = authorImage
+ this.authorImageURL = authorImage;
}
static fromJSON(json) {
@@ -13,25 +12,25 @@
}
getDisplayDiv() {
- const postDiv = document.createElement('div');
- postDiv.className = 'post';
+ const postDiv = document.createElement("div");
+ postDiv.className = "post";
// Author image
if (this.authorImageURL) {
console.log("Image found");
- const image = document.createElement('img');
+ const image = document.createElement("img");
image.src = this.authorImageURL;
image.alt = `Image of ${this.authorName}`;
- image.className = 'author-image';
+ image.className = "author-image";
postDiv.appendChild(image);
}
- else{
+ else {
console.log("No image found");
}
// Post content
- const contentParagraph = document.createElement('p');
- contentParagraph.innerHTML = this.content;
+ const contentParagraph = document.createElement("p");
+ contentParagraph.innerHTML = this.content;
postDiv.appendChild(contentParagraph);
return postDiv;
diff --git a/prototype/js/apiUtils.js b/prototype/js/apiUtils.js
index 6497024..f790d6e 100644
--- a/prototype/js/apiUtils.js
+++ b/prototype/js/apiUtils.js
@@ -3,16 +3,17 @@
* @returns {Promise} - A promise that resolves to an array of trending tags
*/
export async function fetchTrendingTags(endpoint) {
- try {
- const response = await fetch(endpoint);
- if (!response.ok) {
- throw new Error(`Error: ${response.statusText}`);
+ try {
+ const response = await fetch(endpoint);
+ if (!response.ok) {
+ throw new Error(`Error: ${response.statusText}`);
+ }
+ return response.json();
+ }
+ catch (error) {
+ console.error("Failed to fetch trending tags:", error);
+ return null;
}
- return response.json();
- } catch (error) {
- console.error("Failed to fetch trending tags:", error);
- return null;
- }
}
/**
@@ -21,15 +22,16 @@ export async function fetchTrendingTags(endpoint) {
* @returns
*/
export async function fetchPostsByHashtag(prefix, hashtag) {
- const endpoint = prefix + hashtag;
- try {
- const response = await fetch(endpoint);
- if (!response.ok) {
- throw new Error(`HTTP error: ${response.status}`);
+ const endpoint = prefix + hashtag;
+ try {
+ const response = await fetch(endpoint);
+ if (!response.ok) {
+ throw new Error(`HTTP error: ${response.status}`);
+ }
+ return response.json();
+ }
+ catch (error) {
+ console.error(`Failed to fetch posts for hashtag #${hashtag}:`, error);
+ return null;
}
- return response.json();
- } catch (error) {
- console.error(`Failed to fetch posts for hashtag #${hashtag}:`, error);
- return null;
- }
}
diff --git a/prototype/js/index.js b/prototype/js/index.js
index cef6afb..492e263 100644
--- a/prototype/js/index.js
+++ b/prototype/js/index.js
@@ -2,7 +2,7 @@ import { Post } from "../js/Post.js";
import * as apiUtils from "../js/apiUtils.js";
const tagsURL = "https://mastodon.social/api/v1/trends/tags";
-const postPrefix = "https://mastodon.social/api/v1/timelines/tag/:"
+const postPrefix = "https://mastodon.social/api/v1/timelines/tag/:";
document.addEventListener("DOMContentLoaded", function () {
displayPostsNew();
@@ -15,15 +15,15 @@ async function displayPostsNew() {
const container = document.getElementById("featuredTagsPosts");
const hashtags = await apiUtils.fetchTrendingTags(tagsURL);
hashtags.forEach(async (tag) => {
- const section = document.createElement("section");
- section.innerHTML = `#${tag.name}
`;
- const posts = await apiUtils.fetchPostsByHashtag(postPrefix, tag.name);
- posts.forEach((post) => {
- const p = Post.fromJSON(post);
- const postDiv = p.getDisplayDiv();
- section.appendChild(postDiv);
- section.appendChild(document.createElement("hr"));
- });
- container.appendChild(section);
+ const section = document.createElement("section");
+ section.innerHTML = `#${tag.name}
`;
+ const posts = await apiUtils.fetchPostsByHashtag(postPrefix, tag.name);
+ posts.forEach((post) => {
+ const p = Post.fromJSON(post);
+ const postDiv = p.getDisplayDiv();
+ section.appendChild(postDiv);
+ section.appendChild(document.createElement("hr"));
+ });
+ container.appendChild(section);
});
}
diff --git a/settings.html b/settings.html
index 8397c66..af3e9e8 100644
--- a/settings.html
+++ b/settings.html
@@ -3,22 +3,26 @@
+
-
+
+
+
+
Blend | What's happening across the Fediverse
- B L E N D
+ Blend
-
-
-
+
Instances
@@ -29,7 +33,7 @@ Mastodon
-
@@ -42,7 +46,7 @@ Lemmy
-
@@ -50,25 +54,8 @@ Lemmy
- Appearance
-
-
-
-
-
-
-
-
-
-
+