Add thread and like views, rename "status" to "meta"

This should probably be separated into a few commits, but honestly I'm
feeling a bit lazy and I don't think this will hurt anything.

The `<nav>` was getting pretty hectic so I've removed "readme" and
"likes". The readme is now in the "meta" page, previously called
"status", and the likes are now available on each author's profile.

The big change here is that the default view is now the thread view, not
the comment view, so by default you're only going to see new threads
rather than random comments. This makes the feed a bit slower and more
cohesive, so you aren't seeing random comments on posts from 2 years
ago.

To be decided: should the comments view show root posts from threads? Or
should it just show comments? Right now it's basically a firehose view,
but I'm not sure that "firehose" is very accessible language for most
people.
This commit is contained in:
Christian Bundy 2019-11-15 08:38:06 -08:00
parent 449a352e69
commit 00890184df
No known key found for this signature in database
GPG Key ID: EB541AAEF4366237
12 changed files with 105 additions and 46 deletions

View File

@ -48,7 +48,8 @@
"scripts": {
"start": "node index.js",
"debug": "nodemon --inspect index.js --debug",
"test": "standard --fix && dependency-check ./package.json --unused --no-dev --ignore-module highlight.js --ignore-module @fraction/base16-css && cspell --no-summary '**/*.{js,md}' && stylelint --fix src/assets/*.css",
"fix": "standard --fix && stylelint --fix src/assets/*.css",
"test": "standard && dependency-check ./package.json --unused --no-dev --ignore-module highlight.js --ignore-module @fraction/base16-css && cspell --no-summary '**/*.{js,md}' && stylelint src/assets/*.css",
"preversion": "npm test"
}
}

View File

@ -19,7 +19,7 @@ const json = require('./pages/json')
const thread = require('./pages/thread')
const like = require('./pages/like')
const likesPage = require('./pages/likes')
const status = require('./pages/status')
const meta = require('./pages/meta')
const mentions = require('./pages/mentions')
const reply = require('./pages/reply')
const replyAll = require('./pages/reply-all')
@ -107,8 +107,14 @@ module.exports = (config) => {
return next()
})
.get('/', async (ctx) => {
ctx.redirect('/public/threads')
})
.get('/public/comments', async (ctx) => {
ctx.body = await publicPage()
})
.get('/public/threads', async (ctx) => {
ctx.body = await publicPage({ rootsOnly: true })
})
.get('/author/:feed', async (ctx) => {
const { feed } = ctx.params
ctx.body = await author(feed)
@ -154,14 +160,15 @@ module.exports = (config) => {
ctx.type = 'image/png'
ctx.body = await image({ blobId, imageSize: Number(imageSize) })
})
.get('/status/', async (ctx) => {
.get('/meta/', async (ctx) => {
const theme = ctx.cookies.get('theme') || defaultTheme
ctx.body = await status({ theme })
ctx.body = await meta({ theme })
})
.get('/likes/', async (ctx) => {
ctx.body = await likesPage()
.get('/likes/:feed', async (ctx) => {
const { feed } = ctx.params
ctx.body = await likesPage({ feed })
})
.get('/readme/', async (ctx) => {
.get('/meta/readme/', async (ctx) => {
ctx.body = await markdown(config.readme)
})
.get('/mentions/', async (ctx) => {

View File

@ -309,7 +309,7 @@ nav > ul > li {
.profile > img {
width: 4rem;
height: 4rem;
margin-right: 2rem;
margin-right: 1rem;
border-radius: var(--common-radius);
}

View File

@ -3,7 +3,7 @@
const post = require('./models/post')
const listView = require('./views/list')
module.exports = async function likesPage () {
const messages = await post.likes()
module.exports = async function likesPage ({ feed }) {
const messages = await post.likes({ feed })
return listView({ messages })
}

12
src/pages/meta.js Normal file
View File

@ -0,0 +1,12 @@
'use strict'
const meta = require('./models/meta')
const metaView = require('./views/meta')
module.exports = async function metaPage ({ theme }) {
const status = await meta.status()
const { themeNames } = require('@fraction/base16-css')
return metaView({ status, theme, themeNames })
}

View File

@ -18,5 +18,9 @@ module.exports = {
status: async () => {
const ssb = await cooler.connect()
return cooler.get(ssb.status)
},
peers: async () => {
const ssb = await cooler.connect()
return cooler.get(ssb.conn)
}
}

View File

@ -14,7 +14,7 @@ const configure = require('./lib/configure')
const cooler = require('./lib/cooler')
const markdown = require('./lib/markdown')
const maxMessages = 128
const maxMessages = 64
const getMessages = async ({ myFeedId, customOptions, ssb, query, filter }) => {
const options = configure({ query, index: 'DTA' }, customOptions)
@ -224,22 +224,19 @@ const post = {
return messages
},
likes: async (customOptions = {}) => {
likes: async ({ feed }, customOptions = {}) => {
const ssb = await cooler.connect()
const whoami = await cooler.get(ssb.whoami)
const myFeedId = whoami.id
const query = {
const query = [{
$filter: {
value: {
author: myFeedId, // for some reason this `author` isn't being respected
author: feed,
content: {
type: 'vote'
}
}
}
}
}]
const options = configure({
query,
@ -256,7 +253,7 @@ const post = {
source,
pull.filter((msg) => {
return typeof msg.value.content === 'object' &&
msg.value.author === myFeedId &&
msg.value.author === feed &&
typeof msg.value.content.vote === 'object' &&
typeof msg.value.content.vote.link === 'string'
}),
@ -284,8 +281,7 @@ const post = {
const myFeedId = whoami.id
const options = configure({
type: 'post',
limit: maxMessages
type: 'post'
}, customOptions)
const source = await cooler.read(
@ -299,6 +295,42 @@ const post = {
pull.filter((message) => // avoid private messages (!)
typeof message.value.content !== 'string'
),
pull.take(maxMessages),
pull.collect((err, collectedMessages) => {
if (err) {
reject(err)
} else {
resolve(transform(ssb, collectedMessages, myFeedId))
}
})
)
})
return messages
},
threads: async (customOptions = {}) => {
const ssb = await cooler.connect()
const whoami = await cooler.get(ssb.whoami)
const myFeedId = whoami.id
const options = configure({
type: 'post'
}, customOptions)
const source = await cooler.read(
ssb.messagesByType,
options
)
const messages = await new Promise((resolve, reject) => {
pull(
source,
pull.filter((message) => // avoid private messages (!)
typeof message.value.content !== 'string' &&
isRoot(message)
),
pull.take(maxMessages),
pull.collect((err, collectedMessages) => {
if (err) {
reject(err)

View File

@ -3,8 +3,10 @@
const listView = require('./views/public')
const post = require('./models/post')
module.exports = async function publicPage () {
const messages = await post.latest({ private: false })
module.exports = async function publicPage ({ rootsOnly } = {}) {
const messages = rootsOnly
? await post.threads({ private: false })
: await post.latest({ private: false })
return listView({ messages })
}

View File

@ -1,12 +0,0 @@
'use strict'
const meta = require('./models/meta')
const statusView = require('./views/status')
module.exports = async function statusPage ({ theme }) {
const status = await meta.status()
const { themeNames } = require('@fraction/base16-css')
return statusView({ status, theme, themeNames })
}

View File

@ -2,7 +2,9 @@
const highlightJs = require('highlight.js')
const {
a,
article,
footer,
h1,
header,
img,
@ -10,9 +12,9 @@ const {
section,
table,
tbody,
thead,
td,
th,
thead,
tr
} = require('hyperaxe')
const post = require('./components/post')
@ -59,7 +61,10 @@ module.exports = ({
description !== '<p>null</p>\n'
? article({ innerHTML: description })
: null,
metaTable
metaTable,
footer(
a({ href: `/likes/${encodeURIComponent(feedId)}` }, 'view likes')
)
)
return template(

View File

@ -40,13 +40,13 @@ module.exports = (...elements) => {
body(
nav(
ul(
li(a({ href: '/' }, 'public')),
li(a({ href: '/public/threads' }, 'threads')),
li(a({ href: '/public/comments' }, 'comments')),
li(a({ href: '/inbox' }, 'inbox')),
li(a({ href: '/mentions' }, 'mentions')),
li(a({ href: '/profile' }, 'profile')),
li(a({ href: '/likes' }, 'likes')),
li(a({ href: '/status' }, 'status')),
li(a({ href: '/readme' }, 'readme'))
li(a({ href: '/meta' }, 'meta'))
)
),
main({ id: 'content' }, ...elements)

View File

@ -2,12 +2,14 @@
const highlightJs = require('highlight.js')
const {
a,
button,
div,
form,
h1,
h2,
h3,
h4,
label,
li,
option,
@ -81,19 +83,25 @@ module.exports = ({ status, theme, themeNames }) => {
return template(
section({ class: 'message' },
h1('Theme'),
h1('Meta'),
p(
'Check out ',
a({ href: '/meta/readme' }, 'the readme'),
', configure your theme, or view debugging information below.'
),
h2('Theme'),
p('Choose from any theme you\'d like. The default theme is Unikitty Light. Other favorites are Ashes, Chalk, Default, Eighties, Google, Harmonic16, IR Black, Monokai, Rebecca, Solarized, Summerfruit, and Tomorrow.'),
form({ action: '/theme.css', method: 'post' },
select({ name: 'theme' }, ...themeElements),
button({ type: 'submit' }, 'set theme')),
base16Elements,
h1('Status'),
h2('Indexes'),
h2('Status'),
h3('Indexes'),
progressElements,
h2('Peers'),
h3('Local'),
h3('Peers'),
h4('Local'),
ul(localPeers),
h3('Remote'),
h4('Remote'),
ul(remotePeers),
h2('Raw'),
pre({ innerHTML: rawHighlighted }))