aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/ui/Discussion.js
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/ui/Discussion.js')
-rw-r--r--client/src/ui/Discussion.js122
1 files changed, 122 insertions, 0 deletions
diff --git a/client/src/ui/Discussion.js b/client/src/ui/Discussion.js
new file mode 100644
index 0000000..5fef693
--- /dev/null
+++ b/client/src/ui/Discussion.js
@@ -0,0 +1,122 @@
+import { h } from 'preact';
+import { useState, useEffect } from 'preact/hooks';
+import Layout from '../layout';
+import css from './css';
+import { Links } from './Links';
+import { Note } from './Note';
+
+css`
+article {
+ position: absolute;
+ inset: 0;
+
+ overflow: auto;
+}
+
+article > h1 {
+ display: flex;
+ align-items: baseline;
+
+ position: sticky;
+ inset: 0;
+ bottom: auto;
+ z-index: 200;
+
+ margin: 0;
+ padding: 0.75rem 1.5rem;
+ background: var(--theme-title-bg);
+ color: var(--theme-title-fg);
+}
+
+article > h1 > span {
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+
+article > h1 .back {
+ font-size: 0.8em;
+ color: inherit;
+ opacity: 0.5;
+
+ margin-left: 1em;
+}
+
+article > div {
+ position: relative;
+ margin: 2rem 2rem 6rem;
+}
+`;
+
+const tmp = document.createElement('span');
+
+export const Discussion = ({
+ name, items, collapsed,
+ toggleCollapsed, toggleSelected,
+}) => {
+ const [{ width, height, positions, links }, setState] = useState({
+ width: 0,
+ height: 0,
+ positions: {},
+ links: [],
+ });
+
+ const layout = new Layout();
+ const setNodeSize = layout.addNode.bind(layout);
+
+ useEffect(() => {
+ layout.render().then(setState);
+ }, [ items, collapsed ]);
+
+ tmp.innerHTML = name;
+ name = tmp.innerText;
+
+ return (
+ <article>
+ <h1>
+ <span>{name}</span>
+ <a class="back" href="?">back</a>
+ </h1>
+ <div>
+ <Links width={width} height={height} links={links} />
+ <div>
+ {Object.values(items).map((item) => {
+ const isCollapsed = collapsed[item.id];
+ const hidden =
+ item.inReplyTo.every(p => collapsed[p.id])
+ && item.replies.every(c => collapsed[c.id])
+ && item.inReplyTo.length !== 0;
+ if (hidden)
+ return;
+
+ const onlyParent = item.inReplyTo.length === 1 && items[item.inReplyTo[0].id];
+
+ for (const reply of item.replies) {
+ if (isCollapsed && collapsed[reply.id])
+ continue;
+
+ layout.addLink(item.id, reply.id);
+ }
+
+ return (
+ <Note
+ {...item}
+ smallHeader={
+ onlyParent // only one parent post
+ && onlyParent.attributedTo === item.attributedTo // posted by same user
+ && onlyParent.published === item.published // in the same second
+ }
+ collapsed={isCollapsed}
+ position={positions[item.id]}
+ onCollapse={toggleCollapsed}
+ onSelect={toggleSelected}
+ onSize={setNodeSize}
+ />
+ );
+ })}
+ </div>
+ </div>
+ </article>
+ );
+};
+