diff options
Diffstat (limited to 'client/src/groups.js')
| -rw-r--r-- | client/src/groups.js | 74 |
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 }); +}; |
