aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/groups.js
blob: 03f5369f1de67c43345c453e806b2737274398b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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 });
};