1+ import memoize from "micro-memoize" ;
2+
13import type {
4+ Callback ,
25 CallbackRef ,
36 CallbackRequest ,
47 ContribRef ,
58 InputRef ,
69} from "@/types/model/callback" ;
7- import type { Input } from "@/types/model/channel" ;
810import { getInputValues } from "@/actions/helpers/getInputValues" ;
911import { formatObjPath } from "@/utils/objPath" ;
1012import { invokeCallbacks } from "@/actions/helpers/invokeCallbacks" ;
1113import type { ContributionState } from "@/types/state/contribution" ;
1214import type { HostStore } from "@/types/state/host" ;
1315import { store } from "@/store" ;
14- import { shallowEqualArrays } from "@/utils/compare" ;
16+ import { shallowEqualArrays } from "@/utils/shallowEqualArrays" ;
17+ import type { ContribPoint } from "@/types/model/extension" ;
1518
1619/**
1720 * A reference to a property of an input of a callback of a contribution.
@@ -21,23 +24,31 @@ export interface PropertyRef extends ContribRef, CallbackRef, InputRef {
2124 property : string ;
2225}
2326
24- export function handleHostStoreChange ( ) {
27+ /**
28+ * This action is called once a host store change has been detected.
29+ * Note this will only create callback requests for callbacks whose input
30+ * value are affected by the change.
31+ *
32+ * @returns The array of callback requests made or `undefined`,
33+ * if no callback requests have been made.
34+ */
35+ export function handleHostStoreChange ( ) : CallbackRequest [ ] | undefined {
2536 const { extensions, configuration, contributionsRecord } = store . getState ( ) ;
2637 const { hostStore } = configuration ;
2738 if ( ! hostStore ) {
2839 // Exit if no host store configured.
2940 // Actually, we should not come here.
30- return ;
41+ return undefined ;
3142 }
3243 synchronizeThemeMode ( hostStore ) ;
3344 if ( extensions . length === 0 ) {
3445 // Exit if there are no extensions (yet)
35- return ;
46+ return undefined ;
3647 }
37- const propertyRefs = getHostStorePropertyRefs ( ) ;
48+ const propertyRefs = getPropertyRefsForContribPoints ( contributionsRecord ) ;
3849 if ( ! propertyRefs || propertyRefs . length === 0 ) {
3950 // Exit if there are is nothing to be changed
40- return ;
51+ return undefined ;
4152 }
4253 const callbackRequests = getCallbackRequests (
4354 propertyRefs ,
@@ -49,9 +60,12 @@ export function handleHostStoreChange() {
4960 ( callbackRequest ) : callbackRequest is CallbackRequest =>
5061 callbackRequest !== undefined ,
5162 ) ;
52- if ( filteredCallbackRequests && filteredCallbackRequests . length > 0 ) {
53- invokeCallbacks ( filteredCallbackRequests ) ;
63+ if ( ! filteredCallbackRequests || ! filteredCallbackRequests . length ) {
64+ return undefined ;
5465 }
66+
67+ invokeCallbacks ( filteredCallbackRequests ) ;
68+ return filteredCallbackRequests ;
5569}
5670
5771// Exporting for testing only
@@ -103,36 +117,77 @@ const getCallbackRequest = (
103117 return { ...propertyRef , inputValues } ;
104118} ;
105119
106- // TODO: use a memoized selector to get hostStorePropertyRefs
107- // Note that this will only be effective and once we split the
108- // static contribution infos and dynamic contribution states.
109- // The hostStorePropertyRefs only depend on the static
110- // contribution infos.
111-
112120/**
113- * Get the static list of host state property references for all contributions.
121+ * Get the static list of host state property references
122+ * for given contribution points.
123+ * Note: the export exists only for testing.
114124 */
115- function getHostStorePropertyRefs ( ) : PropertyRef [ ] {
116- const { contributionsRecord } = store . getState ( ) ;
125+ export const getPropertyRefsForContribPoints = memoize (
126+ _getPropertyRefsForContribPoints ,
127+ ) ;
128+
129+ function _getPropertyRefsForContribPoints (
130+ contributionsRecord : Record < ContribPoint , ContributionState [ ] > ,
131+ ) : PropertyRef [ ] {
117132 const propertyRefs : PropertyRef [ ] = [ ] ;
118133 Object . getOwnPropertyNames ( contributionsRecord ) . forEach ( ( contribPoint ) => {
119134 const contributions = contributionsRecord [ contribPoint ] ;
120- contributions . forEach ( ( contribution , contribIndex ) => {
121- ( contribution . callbacks || [ ] ) . forEach (
122- ( callback , callbackIndex ) =>
123- ( callback . inputs || [ ] ) . forEach ( ( input , inputIndex ) => {
124- if ( ! input . noTrigger && input . id === "@app" && input . property ) {
125- propertyRefs . push ( {
126- contribPoint,
127- contribIndex,
128- callbackIndex,
129- inputIndex,
130- property : formatObjPath ( input . property ) ,
131- } ) ;
132- }
133- } ) ,
134- [ ] as Input [ ] ,
135- ) ;
135+ propertyRefs . push (
136+ ...getPropertyRefsForContributions ( contribPoint , contributions ) ,
137+ ) ;
138+ } ) ;
139+ return propertyRefs ;
140+ }
141+
142+ /**
143+ * Get the static list of host state property references
144+ * for given contributions.
145+ */
146+ const getPropertyRefsForContributions = memoize (
147+ _getPropertyRefsForContributions ,
148+ ) ;
149+
150+ function _getPropertyRefsForContributions (
151+ contribPoint : string ,
152+ contributions : ContributionState [ ] ,
153+ ) : PropertyRef [ ] {
154+ const propertyRefs : PropertyRef [ ] = [ ] ;
155+ contributions . forEach ( ( contribution , contribIndex ) => {
156+ propertyRefs . push (
157+ ...getPropertyRefsForCallbacks (
158+ contribPoint ,
159+ contribIndex ,
160+ contribution . callbacks ,
161+ ) ,
162+ ) ;
163+ } ) ;
164+ return propertyRefs ;
165+ }
166+
167+ /**
168+ * Get the static list of host state property references
169+ * for given callbacks.
170+ */
171+ const getPropertyRefsForCallbacks = memoize ( _getPropertyRefsForCallbacks ) ;
172+
173+ function _getPropertyRefsForCallbacks (
174+ contribPoint : string ,
175+ contribIndex : number ,
176+ callbacks : Callback [ ] | undefined ,
177+ ) {
178+ const propertyRefs : PropertyRef [ ] = [ ] ;
179+ ( callbacks || [ ] ) . forEach ( ( callback , callbackIndex ) => {
180+ const inputs = callback . inputs || [ ] ;
181+ inputs . forEach ( ( input , inputIndex ) => {
182+ if ( ! input . noTrigger && input . id === "@app" && input . property ) {
183+ propertyRefs . push ( {
184+ contribPoint,
185+ contribIndex,
186+ callbackIndex,
187+ inputIndex,
188+ property : formatObjPath ( input . property ) ,
189+ } ) ;
190+ }
136191 } ) ;
137192 } ) ;
138193 return propertyRefs ;
0 commit comments