1
1
import { signal , computed , effect } from "@preact/signals" ;
2
2
import { Divider , SignalUpdate } from "../types" ;
3
+ import { settingsStore } from "./SettingsModel" ;
3
4
4
- export interface UpdateTreeNode {
5
+ export interface UpdateTreeNodeBase {
5
6
id : string ;
6
7
update : SignalUpdate ;
7
8
children : UpdateTreeNode [ ] ;
8
9
depth : number ;
9
10
hasChildren : boolean ;
10
11
}
11
12
13
+ export interface UpdateTreeNodeSingle extends UpdateTreeNodeBase {
14
+ type : "single" ;
15
+ }
16
+
17
+ export interface UpdateTreeNodeGroup extends UpdateTreeNodeBase {
18
+ type : "group" ;
19
+ count : number ;
20
+ firstUpdate : SignalUpdate ;
21
+ }
22
+
23
+ export type UpdateTreeNode = UpdateTreeNodeGroup | UpdateTreeNodeSingle ;
24
+
25
+ const nodesAreEqual = ( a : UpdateTreeNode , b : UpdateTreeNode ) : boolean => {
26
+ return (
27
+ a . update . signalId === b . update . signalId &&
28
+ a . children . length === b . children . length &&
29
+ a . children . every ( ( child , index ) => nodesAreEqual ( child , b . children [ index ] ) )
30
+ ) ;
31
+ } ;
32
+
33
+ const collapseTree = ( nodes : UpdateTreeNodeSingle [ ] ) : UpdateTreeNode [ ] => {
34
+ const tree : UpdateTreeNode [ ] = [ ] ;
35
+ let lastNode : UpdateTreeNode | undefined ;
36
+
37
+ for ( const node of nodes ) {
38
+ if ( lastNode && nodesAreEqual ( lastNode , node ) ) {
39
+ if ( lastNode . type !== "group" ) {
40
+ // TODO (jg): maybe its safe to mutate lastNode instead of cloning?
41
+ tree . pop ( ) ;
42
+ lastNode = {
43
+ ...lastNode ,
44
+ type : "group" ,
45
+ count : 2 ,
46
+ firstUpdate : node . update ,
47
+ } ;
48
+ tree . push ( lastNode ) ;
49
+ } else {
50
+ lastNode . count ++ ;
51
+ lastNode . firstUpdate = node . update ;
52
+ }
53
+ // If the current node is equal to the last one, skip it
54
+ continue ;
55
+ }
56
+ tree . push ( node ) ;
57
+ lastNode = node ;
58
+ }
59
+
60
+ return tree ;
61
+ } ;
62
+
12
63
const createUpdatesModel = ( ) => {
13
64
const updates = signal < ( SignalUpdate | Divider ) [ ] > ( [ ] ) ;
14
65
const lastUpdateId = signal < number > ( 0 ) ;
@@ -45,9 +96,9 @@ const createUpdatesModel = () => {
45
96
const updateTree = computed ( ( ) => {
46
97
const buildTree = (
47
98
updates : ( SignalUpdate | Divider ) [ ]
48
- ) : UpdateTreeNode [ ] => {
49
- const tree : UpdateTreeNode [ ] = [ ] ;
50
- const stack : UpdateTreeNode [ ] = [ ] ;
99
+ ) : UpdateTreeNodeSingle [ ] => {
100
+ const tree : UpdateTreeNodeSingle [ ] = [ ] ;
101
+ const stack : UpdateTreeNodeSingle [ ] = [ ] ;
51
102
52
103
// Process updates in reverse order to show newest first
53
104
const recentUpdates = updates . slice ( - 100 ) . reverse ( ) ;
@@ -67,6 +118,7 @@ const createUpdatesModel = () => {
67
118
const nodeId = `${ update . signalName } -${ update . receivedAt } -${ i } ` ;
68
119
69
120
const node : UpdateTreeNode = {
121
+ type : "single" ,
70
122
id : nodeId ,
71
123
update,
72
124
children : [ ] ,
@@ -134,9 +186,18 @@ const createUpdatesModel = () => {
134
186
return ( ) => window . removeEventListener ( "message" , handleMessage ) ;
135
187
} ) ;
136
188
189
+ const collapsedUpdateTree = computed ( ( ) => {
190
+ const updateTreeValue = updateTree . value ;
191
+ if ( settingsStore . settings . grouped ) {
192
+ return collapseTree ( updateTreeValue ) ;
193
+ }
194
+ return updateTreeValue ;
195
+ } ) ;
196
+
137
197
return {
138
198
updates,
139
199
updateTree,
200
+ collapsedUpdateTree,
140
201
totalUpdates : computed ( ( ) => Object . keys ( updateTree . value ) . length ) ,
141
202
signalCounts,
142
203
addUpdate,
0 commit comments