8
8
*/
9
9
import { Service } from '../service.js' ;
10
10
11
+ /**
12
+ * @typedef {{ activity: DomainActivity[], urls: string[] } } Incoming
13
+ */
14
+
11
15
export class BatchedActivityService {
12
16
INITIAL = 5 ;
13
17
CHUNK_SIZE = 10 ;
@@ -21,39 +25,49 @@ export class BatchedActivityService {
21
25
this . ntp = ntp ;
22
26
this . batched = batched ;
23
27
24
- /** @type {Service<import('../../types/new-tab.js').UrlInfo> } */
25
- this . urlService = new Service ( {
26
- initial : ( ) => {
27
- if ( this . batched ) {
28
- return this . ntp . messaging . request ( 'activity_getUrls' ) ;
29
- } else {
30
- /** @type {UrlInfo } */
31
- const next = {
32
- urls : [ ] ,
33
- totalTrackersBlocked : 0 ,
34
- } ;
35
- return Promise . resolve ( next ) ;
36
- }
37
- } ,
38
- subscribe : ( cb ) => ntp . messaging . subscribe ( 'activity_onDataPatch' , cb ) ,
39
- } ) ;
40
-
41
- /** @type {Service<ActivityData> } */
28
+ /** @type {Service<Incoming> } */
42
29
this . dataService = new Service ( {
43
- initial : ( params ) => {
30
+ initial : async ( params ) => {
44
31
if ( this . batched ) {
45
- return this . ntp . messaging . request ( 'activity_getDataForUrls' , { urls : params . urls } ) ;
32
+ if ( params && Array . isArray ( params . urls ) && this . dataService . data ?. urls ) {
33
+ const data = await this . ntp . messaging . request ( 'activity_getDataForUrls' , {
34
+ urls : params . urls ,
35
+ } ) ;
36
+ return { activity : data . activity , urls : this . dataService . data . urls } ;
37
+ } else {
38
+ const urlsResponse = await this . ntp . messaging . request ( 'activity_getUrls' ) ;
39
+ const data = await this . ntp . messaging . request ( 'activity_getDataForUrls' , {
40
+ urls : urlsResponse . urls . slice ( 0 , this . INITIAL ) ,
41
+ } ) ;
42
+ return { activity : data . activity , urls : urlsResponse . urls } ;
43
+ }
46
44
} else {
47
- return this . ntp . messaging . request ( 'activity_getData' ) ;
45
+ const data = await this . ntp . messaging . request ( 'activity_getData' ) ;
46
+ return { activity : data . activity , urls : data . activity . map ( ( x ) => x . url ) } ;
48
47
}
49
48
} ,
50
- subscribe : ( cb ) => ntp . messaging . subscribe ( 'activity_onDataUpdate' , cb ) ,
49
+ subscribe : ( cb ) => {
50
+ const sub1 = ntp . messaging . subscribe ( 'activity_onDataUpdate' , ( params ) => {
51
+ cb ( { activity : params . activity , urls : params . activity . map ( ( x ) => x . url ) } ) ;
52
+ } ) ;
53
+ const sub2 = ntp . messaging . subscribe ( 'activity_onDataPatch' , ( params ) => {
54
+ if ( 'patch' in params && params . patch !== null ) {
55
+ cb ( { activity : [ /** @type {DomainActivity } */ ( params . patch ) ] , urls : params . urls } ) ;
56
+ } else {
57
+ cb ( { activity : [ ] , urls : params . urls } ) ;
58
+ }
59
+ } ) ;
60
+ return ( ) => {
61
+ sub1 ( ) ;
62
+ sub2 ( ) ;
63
+ } ;
64
+ } ,
51
65
} ) . withUpdater ( ( old , next , source ) => {
52
66
if ( source === 'manual' ) {
53
67
return next ;
54
68
}
55
69
if ( this . batched ) {
56
- return { activity : old . activity . concat ( next . activity ) } ;
70
+ return { activity : old . activity . concat ( next . activity ) , urls : next . urls } ;
57
71
}
58
72
return next ;
59
73
} ) ;
@@ -70,7 +84,6 @@ export class BatchedActivityService {
70
84
this . burnUnsub = this . ntp . messaging . subscribe ( 'activity_onBurnComplete' , ( ) => {
71
85
this . burns ?. dispatchEvent ( new CustomEvent ( 'activity_onBurnComplete' ) ) ;
72
86
} ) ;
73
- this . patchesSub = this . onPatchData ( ) ;
74
87
}
75
88
76
89
name ( ) {
@@ -82,19 +95,10 @@ export class BatchedActivityService {
82
95
* @internal
83
96
*/
84
97
async getInitial ( ) {
85
- if ( this . batched ) {
86
- const configPromise = this . configService . fetchInitial ( ) ;
87
- const urlsPromise = this . urlService . fetchInitial ( ) ;
88
- const [ config , urlData ] = await Promise . all ( [ configPromise , urlsPromise ] ) ;
89
- const data = await this . dataService . fetchInitial ( { urls : urlData . urls . slice ( 0 , this . INITIAL ) } ) ;
90
- return { config, data } ;
91
- } else {
92
- const configPromise = this . configService . fetchInitial ( ) ;
93
- const dataPromise = this . dataService . fetchInitial ( ) ;
94
- const urlInfoPromise = this . urlService . fetchInitial ( ) ;
95
- const [ config , data ] = await Promise . all ( [ configPromise , dataPromise , urlInfoPromise ] ) ;
96
- return { config, data } ;
97
- }
98
+ const configPromise = this . configService . fetchInitial ( ) ;
99
+ const dataPromise = this . dataService . fetchInitial ( ) ;
100
+ const [ config , data ] = await Promise . all ( [ configPromise , dataPromise ] ) ;
101
+ return { config, data } ;
98
102
}
99
103
100
104
/**
@@ -104,43 +108,20 @@ export class BatchedActivityService {
104
108
this . configService . destroy ( ) ;
105
109
this . dataService . destroy ( ) ;
106
110
this . burnUnsub ( ) ;
107
- this . patchesSub ( ) ;
108
111
this . burns = null ;
109
112
}
110
113
111
114
/**
112
115
* @param {string[] } urls
113
116
*/
114
117
next ( urls ) {
115
- if ( ! this . urlService . data ) throw new Error ( 'unreachable' ) ;
116
118
if ( urls . length === 0 ) return ;
117
119
this . isFetchingNext = true ;
118
120
this . dataService . triggerFetch ( { urls } ) ;
119
121
}
120
122
121
123
/**
122
- * @param {(evt: {data: UrlInfo & PatchData, source: InvocationSource}) => void } cb
123
- * @internal
124
- */
125
- onUrlData ( cb ) {
126
- return this . urlService . onData ( ( params ) => {
127
- if ( 'patch' in params . data && params . data . patch !== null ) return console . log ( 'ignoring patch' ) ;
128
- cb ( params ) ;
129
- } ) ;
130
- }
131
-
132
- /**
133
- * @internal
134
- */
135
- onPatchData ( ) {
136
- return this . urlService . onData ( ( params ) => {
137
- if ( ! ( 'patch' in params . data && params . data . patch !== null ) ) return console . log ( 'ignoring none-patch' ) ;
138
- this . dataService . publish ( { activity : [ /** @type {DomainActivity } */ ( params . data . patch ) ] } ) ;
139
- } ) ;
140
- }
141
-
142
- /**
143
- * @param {(evt: {data: ActivityData, source: InvocationSource}) => void } cb
124
+ * @param {(evt: {data: Incoming, source: InvocationSource}) => void } cb
144
125
* @internal
145
126
*/
146
127
onData ( cb ) {
@@ -150,9 +131,12 @@ export class BatchedActivityService {
150
131
} ) ;
151
132
}
152
133
153
- triggerDataFetch ( ) {
154
- if ( this . batched ) {
155
- this . urlService . triggerFetch ( ) ;
134
+ /**
135
+ * @param {string[] } [urls] - optional subset to refresh
136
+ */
137
+ triggerDataFetch ( urls ) {
138
+ if ( urls ) {
139
+ this . dataService . triggerFetch ( { urls } ) ;
156
140
} else {
157
141
this . dataService . triggerFetch ( ) ;
158
142
}
@@ -220,19 +204,13 @@ export class BatchedActivityService {
220
204
* @param {string } url
221
205
*/
222
206
remove ( url ) {
223
- this . urlService . update ( ( old ) => {
224
- const next = old . urls . filter ( ( x ) => x !== url ) ;
225
- return {
226
- ...old ,
227
- urls : next ,
228
- } ;
229
- } ) ;
230
207
this . dataService . update ( ( old ) => {
231
208
return {
232
209
...old ,
233
210
activity : old . activity . filter ( ( item ) => {
234
211
return item . url !== url ;
235
212
} ) ,
213
+ urls : old . urls . filter ( ( x ) => x !== url ) ,
236
214
} ;
237
215
} ) ;
238
216
this . ntp . messaging . notify ( 'activity_removeItem' , { url } ) ;
0 commit comments