readerAction
A button under an open article, next to Read the original. It is for doing something with that very article: report it, send it somewhere, rate it…
Where in Hodi
When someone opens an article in Hodi's reader, a row of buttons follows the article's text, with Read the original. The plugin's button joins this row.
Example
This button sends the article's id to a route of the plugin:
import { ReaderButton, definePlugin, usePluginApi } from 'hodi:sdk'
import { Flag } from 'lucide-react'
const Report = ({ article }) => {
const api = usePluginApi()
const send = () => api('/report', { method: 'POST', body: JSON.stringify({ id: article.id }) })
return (
<ReaderButton icon={<Flag size={12} />} onClick={send}>
Report
</ReaderButton>
)
}
definePlugin({ readerAction: Report })Props
Hodi gives the component a single prop, article: the open article. Here are the fields of article:
article.idstringThe article's id in Hodi.
article.titlestringThe article's title.
article.urlstringThe article's address on the original site.
article.sourceIdstringThe id of the article's source.
article.sourceNamestringThe source's name, such as The Guardian.
Server side
The plugin's route receives the article's id, never an address to open. With the articles permission, the route finds the article again in Hodi:
'POST /report': async (request, ctx) => {
const article = await ctx.articles.get(request.body.id)
const page = await ctx.articles.page(request.body.id)
…
}ctx.articles.get(id)returns the article, ornullif Hodi never listed it.ctx.articles.page(id)returns the article's page, as the site serves it.
So a plugin can't use the reader to open any address it likes.
Good to know
- How the button is drawn: a
ReaderButton, like Hodi's buttons in the same place. - Who sees the button: the profiles allowed by
audience.