oasis/src/views/post.js

163 lines
4.1 KiB
JavaScript
Raw Normal View History

2020-01-22 00:22:19 +00:00
"use strict";
2019-08-15 01:10:22 +00:00
const {
a,
2019-08-13 20:53:11 +00:00
article,
button,
details,
div,
2019-08-13 20:53:11 +00:00
footer,
form,
header,
img,
section,
span,
summary,
pre
2020-01-22 00:22:19 +00:00
} = require("hyperaxe");
2020-01-22 00:22:19 +00:00
const highlightJs = require("highlight.js");
const lodash = require("lodash");
2019-06-28 20:55:05 +00:00
module.exports = ({ msg }) => {
2019-06-28 20:55:05 +00:00
const encoded = {
key: encodeURIComponent(msg.key),
author: encodeURIComponent(msg.value.author),
parent: encodeURIComponent(msg.value.content.root)
2020-01-22 00:22:19 +00:00
};
2019-06-28 20:55:05 +00:00
const url = {
2019-06-28 20:55:05 +00:00
author: `/author/${encoded.author}`,
likeForm: `/like/${encoded.key}`,
link: `/thread/${encoded.key}#${encoded.key}`,
2019-06-28 20:55:05 +00:00
parent: `/thread/${encoded.parent}#${encoded.parent}`,
avatar: msg.value.meta.author.avatar.url,
json: `/json/${encoded.key}`,
reply: `/reply/${encoded.key}`,
comment: `/comment/${encoded.key}`
2020-01-22 00:22:19 +00:00
};
2020-01-22 00:22:19 +00:00
const isPrivate = Boolean(msg.value.meta.private);
const isRoot = msg.value.content.root == null;
const isThreadTarget = Boolean(
lodash.get(msg, "value.meta.thread.target", false)
);
// TODO: I think this is actually true for both replies and comments.
2020-01-22 00:22:19 +00:00
const isReply = Boolean(lodash.get(msg, "value.meta.thread.reply", false));
2020-01-22 00:22:19 +00:00
const { name } = msg.value.meta.author;
const timeAgo = msg.value.meta.timestamp.received.since.replace("~", "");
2019-06-28 20:55:05 +00:00
2020-01-22 00:22:19 +00:00
const depth = lodash.get(msg, "value.meta.thread.depth", 0);
2020-01-22 00:22:19 +00:00
const markdownContent = msg.value.meta.md.block();
2020-01-22 00:22:19 +00:00
const hasContentWarning =
typeof msg.value.content.contentWarning === "string";
2019-08-13 20:53:11 +00:00
2019-06-28 20:55:05 +00:00
const likeButton = msg.value.meta.voted
2020-01-22 00:22:19 +00:00
? { value: 0, class: "liked" }
: { value: 1, class: null };
2020-01-22 00:22:19 +00:00
const likeCount = msg.value.meta.votes.length;
2020-01-22 00:22:19 +00:00
const messageClasses = [];
if (isPrivate) {
2020-01-22 00:22:19 +00:00
messageClasses.push("private");
}
if (isThreadTarget) {
2020-01-22 00:22:19 +00:00
messageClasses.push("thread-target");
}
if (isReply) {
// True for comments too, I think
2020-01-22 00:22:19 +00:00
messageClasses.push("reply");
}
2020-01-22 00:22:19 +00:00
const isFork = msg.value.meta.postType === "reply";
2019-12-16 02:22:51 +00:00
const postOptions = {
post: null,
2020-01-22 00:22:19 +00:00
comment: ["commented on ", a({ href: url.parent }, " thread")],
reply: ["replied to ", a({ href: url.parent }, " message")],
mystery: "posted a mysterious message"
};
const emptyContent = "<p>undefined</p>\n";
const articleElement =
markdownContent === emptyContent
? article(
{ class: "content" },
pre({
innerHTML: highlightJs.highlight(
"json",
JSON.stringify(msg, null, 2)
).value
})
)
: article({ class: "content", innerHTML: markdownContent });
2019-08-13 20:53:11 +00:00
const articleContent = hasContentWarning
2020-01-22 00:22:19 +00:00
? details(summary(msg.value.content.contentWarning), articleElement)
: articleElement;
2019-08-13 20:53:11 +00:00
2020-01-22 00:22:19 +00:00
const fragment = section(
{
2019-06-28 20:55:05 +00:00
id: msg.key,
2020-01-22 00:22:19 +00:00
class: messageClasses.join(" "),
style: `margin-left: ${depth}rem;`
2019-06-28 20:55:05 +00:00
},
2019-12-16 02:22:51 +00:00
header(
2020-01-22 00:22:19 +00:00
span(
{ class: "author" },
a(
{ href: url.author },
img({ class: "avatar", src: url.avatar, alt: "" }),
2019-12-16 02:22:51 +00:00
name
),
postOptions[msg.value.meta.postType]
),
2020-01-22 00:22:19 +00:00
span(
{ class: "time" },
isPrivate ? "🔒" : null,
2019-12-16 02:22:51 +00:00
a({ href: url.link }, timeAgo)
)
),
2019-08-13 20:53:11 +00:00
articleContent,
// HACK: centered-footer
//
// Here we create an empty div with an anchor tag that can be linked to.
// In our CSS we ensure that this gets centered on the screen when we
// link to this anchor tag.
//
// This is used for redirecting users after they like a post, when we
// want the like button that they just clicked to remain close-ish to
// where it was before they clicked the button.
2020-01-22 00:22:19 +00:00
div({ id: `centered-footer-${encoded.key}`, class: "centered-footer" }),
footer(
2020-01-22 00:22:19 +00:00
form(
{ action: url.likeForm, method: "post" },
button(
{
name: "voteValue",
type: "submit",
value: likeButton.value,
class: likeButton.class
},
`${likeCount}`
)
),
a({ href: url.comment }, "comment"),
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, "reply"),
a({ href: url.json }, "json")
)
);
return fragment;
};