@@ -29,6 +29,7 @@ export default class extends Controller {
2929 }
3030
3131 async connect ( ) {
32+ window . wbController = this ;
3233 try {
3334 const res = await fetch ( this . urlValue , {
3435 headers : { Accept : "application/json" } ,
@@ -44,7 +45,6 @@ export default class extends Controller {
4445 checkbox : true ,
4546 lazy : true ,
4647 selectMode : "hier" ,
47- grid : { debounce : 0 } ,
4848 columnsResizable : true ,
4949 fixedCol : true ,
5050 filter : {
@@ -178,27 +178,24 @@ export default class extends Controller {
178178 ? this . contentdmCollectionOptions
179179 : this . userOptions ;
180180
181- if ( ! options ) {
182- util . setValueToElem ( elem , value ?? "" ) ;
183- break ;
181+ if ( ! elem . dataset . bound ) {
182+ const select = document . createElement ( "select" )
183+ select . name = colId
184+ ; ( options || [ ] ) . forEach ( opt => {
185+ const o = document . createElement ( "option" )
186+ o . value = String ( opt . value )
187+ o . textContent = opt . label
188+ select . appendChild ( o )
189+ } )
190+ elem . textContent = ""
191+ elem . appendChild ( select )
192+ elem . dataset . bound = "1"
193+ select . addEventListener ( "change" , ev => {
194+ node . data [ colId ] = ev . target . value
195+ } )
184196 }
185-
186- if ( ! elem . dataset . rendered ) {
187- const select = document . createElement ( "select" ) ;
188- select . name = colId ;
189- options . forEach ( ( opt ) => {
190- const option = document . createElement ( "option" ) ;
191- option . value = String ( opt . value ) ;
192- option . textContent = opt . label ;
193- select . appendChild ( option ) ;
194- } ) ;
195- elem . replaceChildren ( select ) ;
196- elem . dataset . rendered = "true" ;
197- }
198-
199- const select = elem . querySelector ( "select" ) ;
200- if ( select ) select . value = value ?? "" ;
201- break ;
197+ elem . querySelector ( "select" ) . value = value ?? ""
198+ break
202199 }
203200
204201 case "notes" :
@@ -280,11 +277,62 @@ export default class extends Controller {
280277
281278 source
282279 } ) ;
280+ const t = this . tree ;
281+ let lastTop = - 1
282+
283+ if ( t && typeof t . updateViewport === "function" ) {
284+ const orig = t . updateViewport
285+ t . updateViewport = function ( force ) {
286+ const el = this . listContainerElement
287+ if ( ! el ) return
288+ const top = el . scrollTop
289+ if ( ! force && Math . abs ( top - lastTop ) < 8 ) return
290+ lastTop = top
291+ return orig . call ( this , force )
292+ }
293+ }
294+
295+ requestAnimationFrame ( ( ) => {
296+ const list = this . tree ?. listContainerElement
297+ if ( list ) {
298+ list . style . lineHeight = "24px"
299+ list . style . rowHeight = "24px"
300+ }
301+ this . tree . rowHeight = 24
302+ } )
303+
304+ if ( t && typeof t . updateViewport === "function" ) {
305+ const origUpdate = t . updateViewport ;
306+ let ticking = false ;
307+
308+ t . updateViewport = ( force ) => {
309+ if ( ticking ) return ;
310+ ticking = true ;
311+ requestAnimationFrame ( ( ) => {
312+ try {
313+ origUpdate . call ( t , force ) ;
314+ } catch ( err ) {
315+ console . error ( "updateViewport failed:" , err ) ;
316+ } finally {
317+ ticking = false ;
318+ }
319+ } ) ;
320+ } ;
321+ }
322+
323+ this . $scrollContainer = [ this . tree . listContainerElement ] ;
324+ // this._setupScrollHandler();
283325
284326 if ( ! this . _renderCount ) this . _renderCount = 0
285327 this . _renderCount ++
286328 if ( this . _renderCount % 50 === 0 ) console . log ( "renders:" , this . _renderCount )
287329
330+ if ( ! this . _renderCount ) this . _renderCount = 0 ;
331+ this . _renderCount ++ ;
332+ if ( this . _renderCount % 10 === 0 ) {
333+ console . log ( "render" , this . _renderCount , this . tree . listContainerElement ?. scrollTop ) ;
334+ }
335+
288336 requestAnimationFrame ( ( ) => {
289337 const t = this . tree
290338 const listEl = t . listContainerElement
@@ -295,13 +343,24 @@ export default class extends Controller {
295343 const parentId = root ?. key || "root"
296344 let nextPage = 2
297345
298- listEl . addEventListener ( "scroll" , async ( ) => {
299- if ( listEl . scrollTop + listEl . clientHeight >= listEl . scrollHeight - 100 ) {
300- if ( nextPage ) nextPage = await this . _loadNextAssetPage ( parentId , nextPage )
346+ let scrollTicking = false ;
347+
348+ listEl . addEventListener ( "scroll" , async ( ) => {
349+ if ( scrollTicking ) return ;
350+ scrollTicking = true ;
351+
352+ requestAnimationFrame ( async ( ) => {
353+ const atBottom = listEl . scrollTop + listEl . clientHeight >= listEl . scrollHeight - 100 ;
354+
355+ if ( atBottom && ! this . _pageLoading ) {
356+ this . _pageLoading = true ;
357+ if ( nextPage ) nextPage = await this . _loadNextAssetPage ( parentId , nextPage ) ;
358+ this . _pageLoading = false ;
301359 }
302- if ( t . updateViewport ) t . updateViewport ?. ( true )
303- else if ( t . _updateViewportThrottled ) t . _updateViewportThrottled ?. ( true )
304- } )
360+ console . log ( "scroll fired" , listEl . scrollTop , listEl . scrollHeight , performance . now ( ) ) ;
361+ scrollTicking = false ;
362+ } ) ;
363+ } ) ;
305364 }
306365 } )
307366
@@ -315,7 +374,7 @@ export default class extends Controller {
315374 this . _setupFilterModeToggle ( ) ;
316375 requestAnimationFrame ( ( ) => {
317376 this . _tagHeaderCells ( )
318- this . _deferSelectHydration ( )
377+ // this._deferSelectHydration()
319378 // this._setupVirtualWindow()
320379 } )
321380
@@ -728,20 +787,25 @@ _handleInputChange(e) {
728787
729788 if ( remaining . length ) {
730789 let i = 0
731- const schedule = ( ) => {
732- if ( i >= remaining . length ) {
790+ const total = remaining . length
791+ const processNextChunk = ( ) => {
792+ if ( i >= total ) {
733793 this . assetsLoadedFor . add ( k )
734794 this . loadedAssets . add ( k )
735- this . tree ?. updateViewport ?. ( true )
736795 return
737796 }
738- const slice = remaining . slice ( i , i + CHUNK_SIZE )
739- i += CHUNK_SIZE
740- node . addChildren ( slice )
741- this . tree ?. updateViewport ?. ( true )
742- requestIdleCallback ( schedule , { timeout : 200 } )
797+ const slice = remaining . slice ( i , i + 50 )
798+ i += 50
799+ node . addChildren ( slice , { batch : true } )
800+ if ( ! this . _assetViewportTimer ) {
801+ this . _assetViewportTimer = setTimeout ( ( ) => {
802+ this . _assetViewportTimer = null
803+ this . tree ?. updateViewport ?. ( true )
804+ } , 200 )
805+ }
806+ requestIdleCallback ( processNextChunk , { timeout : 250 } )
743807 }
744- requestIdleCallback ( schedule , { timeout : 200 } )
808+ requestIdleCallback ( processNextChunk , { timeout : 250 } )
745809 } else {
746810 this . assetsLoadedFor . add ( k )
747811 this . loadedAssets . add ( k )
@@ -941,11 +1005,6 @@ _handleInputChange(e) {
9411005 if ( batch . length ) node . addChildren ( batch )
9421006 if ( queue . length ) {
9431007 requestIdleCallback ( processNext , { timeout : 200 } )
944- } else {
945- requestAnimationFrame ( ( ) => {
946- const t = node . tree
947- if ( t . updateViewport ) t . updateViewport ?. ( true )
948- } )
9491008 }
9501009 }
9511010
@@ -1199,7 +1258,7 @@ async _processBgAdds() {
11991258 }
12001259 this . _bgAddRunning = false
12011260 requestAnimationFrame ( ( ) => {
1202- this . tree ?. updateViewport ?. ( true )
1261+ //requestAnimationFrame(() => this.tree?.update ?.("lazy") )
12031262 } )
12041263}
12051264
@@ -1507,12 +1566,6 @@ async _loadNextAssetPage(parentId, nextPage) {
15071566 node . lazy = false ;
15081567 node . data . lazy = false ;
15091568
1510- requestAnimationFrame ( ( ) => {
1511- const t = node . tree ;
1512- if ( t ?. updateViewport ) t . updateViewport ?. ( true ) ;
1513- else if ( t ?. _updateViewportThrottled ) t . _updateViewportThrottled ?. ( true ) ;
1514- } ) ;
1515-
15161569 return children ;
15171570 } catch ( err ) {
15181571 console . error ( "Folder lazy load failed:" , err ) ;
@@ -1522,58 +1575,55 @@ async _loadNextAssetPage(parentId, nextPage) {
15221575 }
15231576 }
15241577
1525- // _setupVirtualWindow() {
1526- // const list = this.tree.listContainerElement
1527- // if (!list) return
1528-
1529- // const rowH = list.querySelector(".wb-row")?.offsetHeight || 24
1530- // const buffer = 40
1531- // let scheduled = false
1532- // let virtualActive = true
1533-
1534- // const renderWindow = () => {
1535- // scheduled = false
1536- // if (!virtualActive) return
1537-
1538- // const top = list.scrollTop
1539- // const bottom = top + list.clientHeight
1540- // const startIdx = Math.max(0, Math.floor(top / rowH) - buffer)
1541- // const endIdx = Math.ceil(bottom / rowH) + buffer
1542- // let idx = 0
1543-
1544- // const iterator = this.tree.visit((node) => {
1545- // if (!node.parent?.expanded || node.data.folder) return true
1546- // const el = node.tr || node.li
1547- // if (!el) return
1548- // const visible = idx >= startIdx && idx <= endIdx
1549- // el.hidden = !visible
1550- // idx++
1551- // })
1552-
1553- // // yield control after big trees
1554- // if (idx > 500) requestIdleCallback(() => iterator, { timeout: 200 })
1555- // }
1556-
1557- // const schedule = () => {
1558- // if (!scheduled) {
1559- // scheduled = true
1560- // requestAnimationFrame(renderWindow)
1561- // }
1562- // }
1563-
1564- // list.addEventListener("scroll", schedule, { passive: true })
1565-
1566- // document.addEventListener("focusin", e => {
1567- // if (e.target?.tagName === "SELECT") virtualActive = false
1568- // })
1569- // document.addEventListener("focusout", e => {
1570- // if (e.target?.tagName === "SELECT") {
1571- // virtualActive = true
1572- // schedule()
1573- // }
1574- // })
1575-
1576- // renderWindow()
1577- // }
1578+ _setupScrollHandler ( ) {
1579+ console . log ( "_setupScrollHandler called, container:" , this . $scrollContainer ) ;
1580+ if ( ! this . $scrollContainer || ! this . $scrollContainer [ 0 ] ) {
1581+ console . log ( "container missing, will retry" ) ;
1582+ setTimeout ( ( ) => this . _setupScrollHandler ( ) , 50 ) ;
1583+ return ;
1584+ }
1585+
1586+ const container = this . $scrollContainer [ 0 ] ;
1587+ console . log ( "container found:" , container ) ;
1588+
1589+ let isUpdating = false ;
1590+
1591+ container . addEventListener ( "scroll" , ( ) => {
1592+ console . log ( "scroll event fired" ) ;
1593+ if ( isUpdating ) return ;
1594+ isUpdating = true ;
1595+
1596+ requestAnimationFrame ( ( ) => {
1597+ console . log ( "_setupVirtualWindow triggered" ) ;
1598+ // this._setupVirtualWindow();
1599+ isUpdating = false ;
1600+ } ) ;
1601+ } ) ;
1602+ }
1603+
1604+ _setupVirtualWindow ( ) {
1605+ if ( this . _inVirtualUpdate ) return ;
1606+ this . _inVirtualUpdate = true ;
1607+
1608+ if ( ! this . $scrollContainer || ! this . $scrollContainer [ 0 ] ) return ;
1609+
1610+ const container = this . $scrollContainer [ 0 ] ;
1611+ const scrollTop = container . scrollTop ;
1612+ const viewportHeight = container . clientHeight ;
1613+ const rowHeight = this . rowHeight || 24 ;
1614+
1615+ const first = Math . floor ( scrollTop / rowHeight ) ;
1616+ const last = Math . ceil ( ( scrollTop + viewportHeight ) / rowHeight ) ;
1617+
1618+ if ( first === this . _prevFirst && last === this . _prevLast ) return ;
1619+ this . _prevFirst = first ;
1620+ this . _prevLast = last ;
1621+
1622+ const active = document . activeElement ;
1623+ if ( active && this . element . contains ( active ) ) return ;
1624+
1625+ this . tree ?. update ?. ( "scroll" ) ;
1626+ this . _inVirtualUpdate = false ;
1627+ }
15781628
15791629}
0 commit comments