aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/groups.js
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/groups.js')
-rw-r--r--client/src/groups.js74
1 files changed, 74 insertions, 0 deletions
diff --git a/client/src/groups.js b/client/src/groups.js
new file mode 100644
index 0000000..03f5369
--- /dev/null
+++ b/client/src/groups.js
@@ -0,0 +1,74 @@
+import { useMemo } from 'preact/hooks';
+
+export const GroupContainer = ({ items, first, render }) => {
+ const groups = useMemo(
+ () => {
+ const groupMap = Object.fromEntries(
+ Object.values(items).map(item => [
+ item.id,
+ {
+ id: item.id,
+ items: [item],
+ next: {},
+ depth: {},
+ },
+ ]),
+ );
+
+ for (const item of Object.values(items)) {
+ const parent = item.inReplyTo.length === 1 && item.inReplyTo[0].id;
+
+ if (parent && items[parent].replies.length === 1) {
+ const self = groupMap[item.id];
+ for (const s of self.items) {
+ groupMap[parent].items.push(s);
+ groupMap[s.id] = groupMap[parent];
+ }
+ }
+ }
+
+ const uniqueGroups = new Set(Object.values(groupMap));
+ const groups = {};
+ for (const group of uniqueGroups) {
+ group.next.up = group.items[0].inReplyTo.map(i => groupMap[i.id].id);
+ group.next.down = group.items[group.items.length-1].replies.map(i => groupMap[i.id].id);
+ groups[group.items[0].id] = group;
+ }
+
+ const updateDepth = (group, dir) => {
+ if (group.depth[dir] !== undefined) {
+ return group.depth[dir];
+ }
+
+ // @TODO: count nodes properly using Set,
+ // this counts nodes multiple times if subgraphs converge
+ let count = group.items.length;
+ for (const id of group.next[dir]) {
+ // go through groupMap here, since when moving 'up',
+ // were not hitting only group-headers
+ count += updateDepth(groupMap[id], dir);
+
+ if (count >= 9) {
+ count = Infinity;
+ break;
+ }
+ }
+
+ group.depth[dir] = count;
+ return count;
+ };
+
+ for (const group of Object.values(groups)) {
+ updateDepth(group, 'up');
+ updateDepth(group, 'down');
+ }
+
+ return groups;
+ },
+ [items]
+ );
+
+ first = groups[first].id;
+
+ return render({ groups, first });
+};