From 0fc2bd3589d0689ebc4ab3864848ebab95583d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Daubensch=C3=BCtz?= Date: Wed, 13 Sep 2023 16:45:33 +0200 Subject: [PATCH] Top and New profile page --- src/http.mjs | 9 + src/views/components/secondheader.mjs | 6 +- src/views/feed.mjs | 17 +- src/views/upvotes.mjs | 270 +++++++++----------------- 4 files changed, 108 insertions(+), 194 deletions(-) diff --git a/src/http.mjs b/src/http.mjs index 364898b6..9058921a 100644 --- a/src/http.mjs +++ b/src/http.mjs @@ -143,10 +143,19 @@ export async function launch(trie, libp2p) { return reply.status(200).type("text/html").send(join(reply.locals.theme)); }); app.get("/upvotes", async (request, reply) => { + let mode = "top"; + if (request.query.mode === "new") mode = "new"; + + let page = parseInt(request.query.page); + if (isNaN(page) || page < 1) { + page = 0; + } const content = await upvotes( trie, reply.locals.theme, request.query.address, + page, + mode, ); return reply.status(200).type("text/html").send(content); }); diff --git a/src/views/components/secondheader.mjs b/src/views/components/secondheader.mjs index 1dad64ca..fa518a15 100644 --- a/src/views/components/secondheader.mjs +++ b/src/views/components/secondheader.mjs @@ -6,7 +6,7 @@ const html = htm.bind(vhtml); const style = "width: 1rem; position: relative; top: 0.15rem;"; -const broadcastSVG = html` +export const broadcastSVG = html` `; -const trophySVG = html` +export const trophySVG = html` `; -const fireSVG = html` +export const fireSVG = html` { return (votes - 1) / Math.pow(itemHourAge + 2, gravity); }; -async function topstories(leaves, start, end) { +export async function topstories(leaves, minimalUpvotes = 2) { return count(leaves) - .filter((story) => story.upvotes > 2) + .filter((story) => story.upvotes > minimalUpvotes) .map((story) => { const score = calculateScore(story.upvotes, itemAge(story.timestamp)); story.score = score; return story; }) - .sort((a, b) => b.score - a.score) - .slice(start, end); + .sort((a, b) => b.score - a.score); } async function editors(leaves) { @@ -153,13 +152,13 @@ async function editors(leaves) { } export default async function index(trie, theme, page) { - const aWeekAgo = sub(new Date(), { - weeks: 1, + const lookBack = sub(new Date(), { + weeks: 3, }); const from = null; const amount = null; const parser = JSON.parse; - const aWeekAgoUnixTime = Math.floor(aWeekAgo.getTime() / 1000); + const lookBackUnixTime = Math.floor(lookBack.getTime() / 1000); const allowlist = await registry.allowlist(); const delegations = await registry.delegations(); @@ -168,7 +167,7 @@ export default async function index(trie, theme, page) { from, amount, parser, - aWeekAgoUnixTime, + lookBackUnixTime, allowlist, delegations, ); @@ -183,7 +182,7 @@ export default async function index(trie, theme, page) { const totalStories = parseInt(env.TOTAL_STORIES, 10); const start = totalStories * page; const end = totalStories * (page + 1); - const storyPromises = await topstories(leaves, start, end); + const storyPromises = (await topstories(leaves)).slice(start, end); let stories = []; for await (let story of storyPromises) { diff --git a/src/views/upvotes.mjs b/src/views/upvotes.mjs index f87729a4..1471f28a 100644 --- a/src/views/upvotes.mjs +++ b/src/views/upvotes.mjs @@ -8,14 +8,16 @@ import { formatDistanceToNow } from "date-fns"; import { utils } from "ethers"; import Header from "./components/header.mjs"; +import { trophySVG, broadcastSVG } from "./components/secondheader.mjs"; import Footer from "./components/footer.mjs"; import Sidebar from "./components/sidebar.mjs"; import Head from "./components/head.mjs"; import * as store from "../store.mjs"; import { EIP712_MESSAGE } from "../constants.mjs"; -import { count } from "./feed.mjs"; +import { count, topstories } from "./feed.mjs"; import * as ens from "../ens.mjs"; import * as registry from "../chainstate/registry.mjs"; +import Row from "./components/row.mjs"; const html = htm.bind(vhtml); @@ -42,7 +44,7 @@ export const classify = (messages) => { .sort((a, b) => b.message.timestamp - a.message.timestamp); }; -export default async function (trie, theme, identity) { +export default async function (trie, theme, identity, page, mode) { if (!utils.isAddress(identity)) { return html`Not a valid address`; } @@ -60,65 +62,47 @@ export default async function (trie, theme, identity) { parser, startDatetime, allowlist, - delegations + delegations, ); const cacheEnabled = true; - leaves = await Promise.all( - leaves.map(async (leaf) => { + const totalStories = 10; + const start = totalStories * page; + const end = totalStories * (page + 1); + let storyPromises = await count(leaves); + + if (mode === "top") { + storyPromises = storyPromises.sort((a, b) => b.upvotes - a.upvotes); + } else if (mode === "new") { + storyPromises = storyPromises.sort((a, b) => b.timestamp - a.timestamp); + } + + let stories = storyPromises + .filter( + (story) => + utils.getAddress(story.identity) === utils.getAddress(identity), + ) + .slice(start, end); + stories = await Promise.all( + stories.map(async (leaf) => { const ensData = await ens.resolve(leaf.identity); + let avatars = []; + for await (let upvoter of leaf.upvoters) { + const upvoterEnsData = await ens.resolve(upvoter); + let avatarUrl = upvoterEnsData.avatar; + if (avatarUrl && !avatarUrl.startsWith("https")) { + avatarUrl = upvoterEnsData.avatar_url; + } + if (avatarUrl) { + avatars.push(avatarUrl); + } + } return { ...leaf, displayName: ensData.displayName, + avatars: avatars, }; - }) + }), ); - const actions = classify(leaves); - const taintedSubmissions = actions - .filter( - (action) => - // TODO: Should start using ethers.utils.getAddress - identity.toLowerCase() === action.message.identity.toLowerCase() && - action.verb === "submit" - ) - .map((action) => normalizeUrl(action.message.href)); - const taintedUpvotes = actions - .filter( - (action) => - // TODO: Should start using ethers.utils.getAddress - identity.toLowerCase() === action.message.identity.toLowerCase() && - action.verb === "upvote" - ) - .map((action) => normalizeUrl(action.message.href)); - const submissions = count(leaves) - .filter((story) => taintedSubmissions.includes(normalizeUrl(story.href))) - .sort((a, b) => { - const timestampA = new Date(a.timestamp); - const timestampB = new Date(b.timestamp); - - if (timestampA < timestampB) { - return 1; - } - if (timestampA > timestampB) { - return -1; - } - return 0; - }) - .slice(0, 10); - const upvotes = count(leaves) - .filter((story) => taintedUpvotes.includes(normalizeUrl(story.href))) - .sort((a, b) => { - const timestampA = new Date(a.timestamp); - const timestampB = new Date(b.timestamp); - - if (timestampA < timestampB) { - return 1; - } - if (timestampA > timestampB) { - return -1; - } - return 0; - }) - .slice(0, 10); return html` @@ -144,7 +128,6 @@ export default async function (trie, theme, identity) { href="https://etherscan.io/address/${ensData.address}" > ${ensData.displayName} - ${String.fromCharCode(0x2934, 0xfe0e)} ${ensData.description ? html` "${ensData.description}"
` @@ -152,8 +135,7 @@ export default async function (trie, theme, identity) { ${ensData.url ? html`Website: ${ensData.url} - ${String.fromCharCode(0x2934, 0xfe0e)} ${ensData.url}
` : ""} ${ensData.twitter @@ -162,8 +144,7 @@ export default async function (trie, theme, identity) { href="https://twitter.com/${ensData.twitter}" target="_blank" rel="noopener noreferrer" - >@${ensData.twitter} - ${String.fromCharCode(0x2934, 0xfe0e)} @${ensData.twitter}
` : ""} ${ensData.github @@ -172,8 +153,7 @@ export default async function (trie, theme, identity) { href="https://github.com/${ensData.github}" target="_blank" rel="noopener noreferrer" - >${ensData.github} - ${String.fromCharCode(0x2934, 0xfe0e)} ${ensData.github}
` : ""} ${ensData.telegram @@ -182,143 +162,69 @@ export default async function (trie, theme, identity) { href="https://t.me/${ensData.telegram}" target="_blank" rel="noopener noreferrer" - >${ensData.telegram} - ${String.fromCharCode(0x2934, 0xfe0e)} ${ensData.telegram}
` : ""} ${ensData.discord ? html`Discord: ${ensData.discord}
` : ""}
- ${submissions.length > 0 - ? html`LAST 10 SUBMISSIONS: ` + ${stories.length > 0 + ? html` + SUBMISSIONS + ${page !== 0 ? html`(page: ${page})` : ""} + ` : ""} - ${submissions.length === 0 && upvotes.length === 0 + + +
+ + + + + + +
+ + + ${stories.length === 0 ? html` No activity yet... ` : ""} - ${submissions.map( - (story, i) => html` - - - - - - - - - - - - -
- - ${story.title} - - (${extractDomain(story.href)}) - - -
- - - ${story.upvotes} - points - submitted - ${formatDistanceToNow( - new Date(story.timestamp * 1000) - )} - ago - - -
- - - ` - )} - ${upvotes.length > 0 - ? html` - -
-
- LAST 10 UPVOTES: -
- - ` + ${stories.map(Row())} + ${stories.length === totalStories + ? html` + + + + More + + + + ` : ""} - ${upvotes.map( - (story, i) => html` - - - - - - - - - - - - -
- - ${story.title} - - (${extractDomain(story.href)}) - - -
- - - ${story.upvotes} - points by - - ${story.displayName} - - submitted - ${formatDistanceToNow( - new Date(story.timestamp * 1000) - )} - ago - - -
- - - ` - )} - - -