Add reply-all feature for non-forky replies
This commit is contained in:
@ -2,6 +2,7 @@
|
|||||||
"version": "0.1",
|
"version": "0.1",
|
||||||
"language": "en",
|
"language": "en",
|
||||||
"words": [
|
"words": [
|
||||||
|
"AGPL",
|
||||||
"backlinks",
|
"backlinks",
|
||||||
"hyperaxe",
|
"hyperaxe",
|
||||||
"msgs",
|
"msgs",
|
||||||
|
@ -52,4 +52,4 @@ yarn global add @fraction/oasis
|
|||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
ISC
|
AGPL-3.0
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "Christian Bundy <christianbundy@fraction.io>",
|
"author": "Christian Bundy <christianbundy@fraction.io>",
|
||||||
"license": "ISC",
|
"license": "AGPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fraction/flotilla": "^1.0.1",
|
"@fraction/flotilla": "^1.0.1",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
|
12
src/app.js
12
src/app.js
@ -21,7 +21,9 @@ const status = require('./pages/status')
|
|||||||
const highlight = require('./pages/highlight')
|
const highlight = require('./pages/highlight')
|
||||||
const mentions = require('./pages/mentions')
|
const mentions = require('./pages/mentions')
|
||||||
const reply = require('./pages/reply')
|
const reply = require('./pages/reply')
|
||||||
|
const replyAll = require('./pages/reply-all')
|
||||||
const publishReply = require('./pages/publish-reply')
|
const publishReply = require('./pages/publish-reply')
|
||||||
|
const publishReplyAll = require('./pages/publish-reply-all')
|
||||||
const image = require('./pages/image')
|
const image = require('./pages/image')
|
||||||
const blob = require('./pages/blob')
|
const blob = require('./pages/blob')
|
||||||
const publish = require('./pages/publish')
|
const publish = require('./pages/publish')
|
||||||
@ -117,12 +119,22 @@ module.exports = (config) => {
|
|||||||
const { message } = ctx.params
|
const { message } = ctx.params
|
||||||
ctx.body = await reply(message, false)
|
ctx.body = await reply(message, false)
|
||||||
})
|
})
|
||||||
|
.get('/reply-all/:message', async (ctx) => {
|
||||||
|
const { message } = ctx.params
|
||||||
|
ctx.body = await replyAll(message, false)
|
||||||
|
})
|
||||||
.post('/reply/:message', koaBody(), async (ctx) => {
|
.post('/reply/:message', koaBody(), async (ctx) => {
|
||||||
const { message } = ctx.params
|
const { message } = ctx.params
|
||||||
const text = String(ctx.request.body.text)
|
const text = String(ctx.request.body.text)
|
||||||
ctx.body = await publishReply({ message, text })
|
ctx.body = await publishReply({ message, text })
|
||||||
ctx.redirect('/')
|
ctx.redirect('/')
|
||||||
})
|
})
|
||||||
|
.post('/reply-all/:message', koaBody(), async (ctx) => {
|
||||||
|
const { message } = ctx.params
|
||||||
|
const text = String(ctx.request.body.text)
|
||||||
|
ctx.body = await publishReplyAll({ message, text })
|
||||||
|
ctx.redirect('/')
|
||||||
|
})
|
||||||
.post('/publish/', koaBody(), async (ctx) => {
|
.post('/publish/', koaBody(), async (ctx) => {
|
||||||
const text = String(ctx.request.body.text)
|
const text = String(ctx.request.body.text)
|
||||||
ctx.body = await publish({ text })
|
ctx.body = await publish({ text })
|
||||||
|
@ -19,7 +19,8 @@ const rawConnect = () => new Promise((resolve, reject) => {
|
|||||||
messagesByType: 'source',
|
messagesByType: 'source',
|
||||||
publish: 'async',
|
publish: 'async',
|
||||||
status: 'async',
|
status: 'async',
|
||||||
whoami: 'sync'
|
whoami: 'sync',
|
||||||
|
tangle: { branch: 'async' }
|
||||||
}
|
}
|
||||||
}, (err, api) => {
|
}, (err, api) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -148,7 +148,7 @@ const transform = (ssb, messages, myFeedId) =>
|
|||||||
return msg
|
return msg
|
||||||
}))
|
}))
|
||||||
|
|
||||||
module.exports = {
|
const post = {
|
||||||
fromFeed: async (feedId, customOptions = {}) => {
|
fromFeed: async (feedId, customOptions = {}) => {
|
||||||
const ssb = await cooler.connect()
|
const ssb = await cooler.connect()
|
||||||
|
|
||||||
@ -419,5 +419,23 @@ module.exports = {
|
|||||||
|
|
||||||
debug('Published: %O', body)
|
debug('Published: %O', body)
|
||||||
return cooler.get(ssb.publish, body)
|
return cooler.get(ssb.publish, body)
|
||||||
|
},
|
||||||
|
reply: async ({ parent, message }) => {
|
||||||
|
message.root = parent
|
||||||
|
message.branch = parent
|
||||||
|
|
||||||
|
return post.publish(message)
|
||||||
|
},
|
||||||
|
replyAll: async ({ parent, message }) => {
|
||||||
|
const ssb = await cooler.connect()
|
||||||
|
const parentMsg = await cooler.get(ssb.get, parent)
|
||||||
|
const branch = await cooler.get(ssb.tangle.branch, parent)
|
||||||
|
|
||||||
|
message.root = parentMsg.content.root
|
||||||
|
message.branch = branch
|
||||||
|
|
||||||
|
return post.publish(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = post
|
||||||
|
14
src/pages/publish-reply-all.js
Normal file
14
src/pages/publish-reply-all.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const ssbMentions = require('ssb-mentions')
|
||||||
|
const post = require('./models/post')
|
||||||
|
|
||||||
|
module.exports = async function publishReplyAllPage ({ message, text }) {
|
||||||
|
// TODO: rename `message` to `parent` or `ancestor` or similar
|
||||||
|
const mentions = ssbMentions(text) || undefined
|
||||||
|
|
||||||
|
return post.replyAll({
|
||||||
|
parent: message,
|
||||||
|
message: { text, mentions }
|
||||||
|
})
|
||||||
|
}
|
@ -4,11 +4,11 @@ const ssbMentions = require('ssb-mentions')
|
|||||||
const post = require('./models/post')
|
const post = require('./models/post')
|
||||||
|
|
||||||
module.exports = async function publishReplyPage ({ message, text }) {
|
module.exports = async function publishReplyPage ({ message, text }) {
|
||||||
|
// TODO: rename `message` to `parent` or `ancestor` or similar
|
||||||
const mentions = ssbMentions(text) || undefined
|
const mentions = ssbMentions(text) || undefined
|
||||||
return post.publish({
|
|
||||||
root: message,
|
return post.reply({
|
||||||
branch: message,
|
parent: message,
|
||||||
text,
|
message: { text, mentions }
|
||||||
mentions
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
12
src/pages/reply-all.js
Normal file
12
src/pages/reply-all.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const debug = require('debug')('oasis')
|
||||||
|
const post = require('./models/post')
|
||||||
|
const replyAllView = require('./views/reply-all')
|
||||||
|
|
||||||
|
module.exports = async function replyPage (parentId) {
|
||||||
|
const message = await post.get(parentId)
|
||||||
|
debug('%O', message)
|
||||||
|
|
||||||
|
return replyAllView({ message })
|
||||||
|
}
|
@ -34,9 +34,12 @@ module.exports = ({ msg }) => {
|
|||||||
parent: `/thread/${encoded.parent}#${encoded.parent}`,
|
parent: `/thread/${encoded.parent}#${encoded.parent}`,
|
||||||
avatar: msg.value.meta.author.avatar.url,
|
avatar: msg.value.meta.author.avatar.url,
|
||||||
raw: `/raw/${encoded.key}`,
|
raw: `/raw/${encoded.key}`,
|
||||||
reply: `/reply/${encoded.key}`
|
reply: `/reply/${encoded.key}`,
|
||||||
|
replyAll: `/reply-all/${encoded.key}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isRoot = msg.value.content.root == null
|
||||||
|
|
||||||
const isPrivate = Boolean(msg.value.meta.private)
|
const isPrivate = Boolean(msg.value.meta.private)
|
||||||
const isThreadTarget = Boolean(lodash.get(
|
const isThreadTarget = Boolean(lodash.get(
|
||||||
msg,
|
msg,
|
||||||
@ -131,6 +134,7 @@ module.exports = ({ msg }) => {
|
|||||||
},
|
},
|
||||||
`❤ ${likeCount}`)),
|
`❤ ${likeCount}`)),
|
||||||
isPrivate ? null : a({ href: url.reply }, 'reply'),
|
isPrivate ? null : a({ href: url.reply }, 'reply'),
|
||||||
|
isPrivate || isRoot ? null : a({ href: url.replyAll }, 'reply all'),
|
||||||
a({ href: url.context }, 'context'),
|
a({ href: url.context }, 'context'),
|
||||||
parentLink,
|
parentLink,
|
||||||
a({ href: url.raw }, 'raw')
|
a({ href: url.raw }, 'raw')
|
||||||
|
@ -13,7 +13,7 @@ module.exports = ({ messages }) => {
|
|||||||
|
|
||||||
return template(
|
return template(
|
||||||
form({ action: publishForm, method: 'post' },
|
form({ action: publishForm, method: 'post' },
|
||||||
textarea({ autofocus: true, required: true, name: 'text' }),
|
textarea({ required: true, name: 'text' }),
|
||||||
button({
|
button({
|
||||||
type: 'submit'
|
type: 'submit'
|
||||||
}, 'submit')),
|
}, 'submit')),
|
||||||
|
31
src/pages/views/reply-all.js
Normal file
31
src/pages/views/reply-all.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
'use strict'
|
||||||
|
|
||||||
|
const {
|
||||||
|
button,
|
||||||
|
form,
|
||||||
|
textarea
|
||||||
|
} = require('hyperaxe')
|
||||||
|
|
||||||
|
const template = require('./components/template')
|
||||||
|
const post = require('./components/post')
|
||||||
|
|
||||||
|
module.exports = ({ message }) => {
|
||||||
|
const likeForm = `/reply-all/${encodeURIComponent(message.key)}`
|
||||||
|
|
||||||
|
const authorName = message.value.meta.author.name
|
||||||
|
const authorFeedId = message.value.author
|
||||||
|
const markdownMention = `[@${authorName}](${authorFeedId})\n\n`
|
||||||
|
|
||||||
|
return template(
|
||||||
|
post({ msg: message }),
|
||||||
|
form({ action: likeForm, method: 'post' },
|
||||||
|
textarea({
|
||||||
|
autofocus: true,
|
||||||
|
required: true,
|
||||||
|
name: 'text'
|
||||||
|
}, markdownMention),
|
||||||
|
button({
|
||||||
|
type: 'submit'
|
||||||
|
}, 'reply all'))
|
||||||
|
)
|
||||||
|
}
|
Reference in New Issue
Block a user