@@ -4,7 +4,6 @@ import { IContextNode, InsertionPointWithElement } from '@mweb/core'
44import { useEngine } from '../contexts/engine-context'
55import { useUserLinks } from '../contexts/mutable-web-context/use-user-links'
66import { Widget } from 'near-social-vm'
7- import { usePortalFilter } from '../contexts/engine-context/use-portal-filter'
87import { ShadowDomWrapper } from '../components/shadow-dom-wrapper'
98import { ContextTree } from '@mweb/react'
109import { useContextApps } from '../contexts/mutable-web-context/use-context-apps'
@@ -22,6 +21,7 @@ import { createPortal } from 'react-dom'
2221import { ModalProps } from '../contexts/modal-context/modal-context'
2322import { Portal } from '../contexts/engine-context/engine-context'
2423import { Target } from '../services/target/target.entity'
24+ import { filterAndDiscriminate } from '../common/filter-and-discriminate'
2525
2626const getRootContext = ( context : IContextNode ) : IContextNode => {
2727 return context . parentNode ? getRootContext ( context . parentNode ) : context
@@ -92,6 +92,27 @@ const ContextHandler: FC<{ context: IContextNode; insPoints: InsertionPointWithE
9292 const { links, createUserLink, deleteUserLink } = useUserLinks ( context )
9393 const { apps } = useContextApps ( context )
9494 const { engine, selectedMutation } = useMutableWeb ( )
95+ const { portals } = useEngine ( )
96+
97+ const portalComponents = useMemo ( ( ) => {
98+ return Array . from ( portals . values ( ) )
99+ . filter ( ( { target } ) => TargetService . isTargetMet ( target , context ) )
100+ . sort ( ( a , b ) => ( b . key > a . key ? 1 : - 1 ) )
101+ } , [ portals , context ] )
102+
103+ const [ materializedComponents , nonMaterializedComponents ] = useMemo ( ( ) => {
104+ return filterAndDiscriminate ( portalComponents , ( portal ) => portal . inMemory )
105+ } , [ portalComponents ] )
106+
107+ const componentsByInsPoint = useMemo ( ( ) => {
108+ return insPoints . map ( ( insPoint ) =>
109+ materializedComponents . filter ( ( { target } ) => target . injectTo === insPoint . name )
110+ )
111+ } , [ insPoints , materializedComponents ] )
112+
113+ const componentsForContextInsPoint = useMemo ( ( ) => {
114+ return materializedComponents . filter ( ( { target } ) => target . injectTo === undefined )
115+ } , [ materializedComponents ] )
95116
96117 const [ isEditMode , setIsEditMode ] = useState ( false )
97118
@@ -158,14 +179,16 @@ const ContextHandler: FC<{ context: IContextNode; insPoints: InsertionPointWithE
158179
159180 return (
160181 < >
161- { insPoints . map ( ( ip ) => (
182+ { insPoints . map ( ( ip , index ) => (
162183 < InsPointHandler
163184 key = { ip . name }
185+ element = { ip . element }
164186 insPointName = { ip . name }
165187 bosLayoutManager = { ip . bosLayoutManager }
166188 context = { context }
167189 transferableContext = { transferableContext }
168190 allUserLinks = { links }
191+ components = { componentsByInsPoint [ index ] }
169192 apps = { apps }
170193 isEditMode = { isEditMode }
171194 onContextQuery = { handleContextQuery }
@@ -178,11 +201,14 @@ const ContextHandler: FC<{ context: IContextNode; insPoints: InsertionPointWithE
178201 onSetLinkDataCurry = { handleSetLinkDataCurry }
179202 />
180203 ) ) }
204+
181205 { /* For OverlayTrigger */ }
182206 < InsPointHandler
207+ element = { context . element }
183208 context = { context }
184209 transferableContext = { transferableContext }
185210 allUserLinks = { links }
211+ components = { componentsForContextInsPoint }
186212 apps = { apps }
187213 isEditMode = { isEditMode }
188214 onContextQuery = { handleContextQuery }
@@ -205,16 +231,28 @@ const ContextHandler: FC<{ context: IContextNode; insPoints: InsertionPointWithE
205231 onSetLinkDataCurry = { handleSetLinkDataCurry }
206232 />
207233 ) ) }
234+
235+ { nonMaterializedComponents . map ( ( portal ) => (
236+ < PortalRenderer
237+ key = { portal . key }
238+ portal = { portal }
239+ context = { context }
240+ transferableContext = { transferableContext }
241+ onAttachContextRef = { attachContextRef }
242+ />
243+ ) ) }
208244 </ >
209245 )
210246}
211247
212248const InsPointHandler : FC < {
213249 insPointName ?: string
250+ element : HTMLElement | null
214251 bosLayoutManager ?: string
215252 context : IContextNode
216253 transferableContext : TransferableContext
217254 allUserLinks : BosUserLink [ ]
255+ components : Portal [ ]
218256 apps : AppMetadata [ ]
219257 isEditMode : boolean
220258 onContextQuery : ( target : Target ) => TransferableContext | null
@@ -239,10 +277,12 @@ const InsPointHandler: FC<{
239277 ) => Promise < void >
240278} > = ( {
241279 insPointName,
280+ element,
242281 bosLayoutManager,
243282 context,
244283 transferableContext,
245284 allUserLinks,
285+ components,
246286 apps,
247287 isEditMode,
248288 onContextQuery,
@@ -256,19 +296,11 @@ const InsPointHandler: FC<{
256296} ) => {
257297 const { redirectMap, isDevServerLoading } = useEngine ( )
258298 const { config, engine } = useMutableWeb ( )
259- const { components } = usePortalFilter ( context , insPointName ) // ToDo: extract to the separate AppManager component
260299 const { notify } = useModal ( )
261300
262301 const attachInsPointRef = useCallback (
263- ( callback : ( r : React . Component | Element | null | undefined ) => void ) => {
264- // ToDo: the similar logic is used in ContextPortal
265- const targetElement = insPointName
266- ? context . insPoints . find ( ( ip ) => ip . name === insPointName ) ?. element
267- : context . element
268-
269- callback ( targetElement )
270- } ,
271- [ context , insPointName ]
302+ ( callback : ( r : React . Component | Element | null | undefined ) => void ) => callback ( element ) ,
303+ [ element ]
272304 )
273305
274306 // prevents blinking
@@ -443,3 +475,30 @@ const InMemoryRenderer: FC<{ children: React.ReactNode }> = ({ children }) => {
443475
444476 return createPortal ( children , portalRef . current )
445477}
478+
479+ const PortalRenderer : FC < {
480+ portal : Portal
481+ context : IContextNode
482+ transferableContext : TransferableContext
483+ onAttachContextRef : ( callback : ( r : React . Component | Element | null | undefined ) => void ) => void
484+ } > = ( { portal, context, transferableContext, onAttachContextRef } ) => {
485+ const { component : PortalComponent , target } = portal
486+
487+ const attachInsPointRef = useCallback (
488+ ( callback : ( r : React . Component | Element | null | undefined ) => void ) => {
489+ const ip = context . insPoints . find ( ( ip ) => ip . name === target . injectTo )
490+ callback ( ip ? ip . element : null )
491+ } ,
492+ [ target , context ]
493+ )
494+
495+ return (
496+ < InMemoryRenderer >
497+ < PortalComponent
498+ context = { transferableContext }
499+ attachContextRef = { onAttachContextRef }
500+ attachInsPointRef = { attachInsPointRef }
501+ />
502+ </ InMemoryRenderer >
503+ )
504+ }
0 commit comments