@@ -417,27 +417,39 @@ export async function showDataView(source: string, type: string, title: string,
417417 if ( ! server ) {
418418 throw new Error ( 'R server not available' ) ;
419419 }
420- const response : unknown = await sessionRequest ( server , {
420+
421+ // Set a timeout for the entire operation
422+ const timeoutPromise = new Promise ( ( _ , reject ) => {
423+ setTimeout ( ( ) => reject ( new Error ( 'Operation timed out' ) ) , 60000 ) ; // 60 second timeout
424+ } ) ;
425+
426+ const requestPromise : unknown = await sessionRequest ( server , {
421427 type : 'dataview_fetch_rows' ,
422428 varname : title ,
423429 start,
424430 end,
425431 sortModel
426432 } ) ;
433+
434+ const response : unknown = await Promise . race ( [ requestPromise , timeoutPromise ] ) ;
435+
427436 if ( typeof response !== 'object' || response === null || ! ( 'rows' in response ) || ! ( 'totalRows' in response ) ) {
428437 throw new Error ( 'Invalid response from R server' ) ;
429438 }
439+
430440 const rows : unknown = ( response as { rows : object [ ] } ) . rows ;
431441 const totalRows : unknown = ( response as { totalRows : number } ) . totalRows ;
442+
432443 if ( ! Array . isArray ( rows ) || typeof totalRows !== 'number' ) {
433444 throw new Error ( 'Fetched rows or totalRows invalid' ) ;
434445 }
446+
435447 await panel ?. webview . postMessage ( {
436448 command : 'fetchedRows' ,
437449 start,
438450 end,
439451 rows : rows as object [ ] ,
440- lastRow : ( totalRows <= ( end ?? totalRows ) ? totalRows : - 1 ) ,
452+ totalRows,
441453 requestId
442454 } ) ;
443455 } catch ( error ) {
@@ -603,70 +615,101 @@ export async function getTableHtml(webview: Webview, file: string): Promise<stri
603615 const displayDataSource = {
604616 rowCount: undefined,
605617 getRows(params) {
618+ console.log("Getting rows:", params.startRow, "to", params.endRow,
619+ "Sort:", JSON.stringify(params.sortModel));
620+
621+
606622 const msg = {
607623 command: 'fetchRows',
608624 start: params.startRow,
609625 end: params.endRow,
610626 sortModel: params.sortModel,
611- requestId: Math.random().toString(36).substr(2, 9) // Generate unique requestId
627+ requestId: Math.random().toString(36).substr(2, 9)
612628 };
613629
614630 const handler = event => {
615631 const m = event.data;
616632 if (m.command === 'fetchedRows' && m.requestId === msg.requestId) {
617- console.log('Fetched rows:', m.rows);
618- params.successCallback(m.rows, m.lastRow);
633+ console.log('Received rows:', m.rows.length, 'First few row IDs:', m.rows.slice(0, 3).map(r => r.x1));
634+
635+ const totalRows = m.totalRows;
636+ let lastRow = -1;
637+ if (totalRows <= params.endRow) {
638+ lastRow = totalRows;
639+ }
640+ console.log('Success callback with lastRow:', lastRow, 'totalRows:', totalRows);
641+ params.successCallback(m.rows, lastRow);
619642 window.removeEventListener('message', handler);
620- }
643+ }
621644 };
622645 window.addEventListener('message', handler);
623646 vscode.postMessage(msg);
624647 }
625648 };
626- const colDefs = data.columns.map(col => {
627- if (col.field === 'x1') {
628- return {
629- ...col,
630- sortable: false,
631- filter: false,
632- suppressMenu: true,
633- };
634- }
635- return col;
636- });
649+
637650 const gridOptions = {
638651 defaultColDef: {
639652 sortable: true,
640653 resizable: true,
641654 filter: true,
642655 width: 100,
643- minWidth: 50 ,
656+ minWidth: 80 ,
644657 filterParams: {
645658 buttons: ['reset', 'apply'],
646659 closeOnApply: true
647660 }
648661 },
649- datasource: displayDataSource,
650- getRowId: params => params.data.x1,
651- columnDefs: colDefs,
652- rowSelection: { mode: "multiRow", headerCheckbox: false },
653- pagination: ${ pageSize > 0 ? 'true' : 'false' } ,
654- paginationPageSize: ${ pageSize } ,
655- enableCellTextSelection: true,
662+
663+ columnDefs: data.columns,
664+
665+ suppressColumnVirtualisation: true,
666+ alwaysShowVerticalScroll: true,
667+ debounceVerticalScrollbar: true,
668+
669+ suppressRowTransform: false,
656670 ensureDomOrder: true,
657- tooltipShowDelay: 100,
658- onFirstDataRendered: onFirstDataRendered,
671+
672+ rowHeight: 25,
673+
659674 rowModelType: 'infinite',
660675 cacheBlockSize: 100,
661- maxBlocksInCache: 10,
662- cacheOverflowSize: 2,
663- maxConcurrentDatasourceRequests: 2,
664- infiniteInitialRowCount: 1
676+ maxBlocksInCache: 5,
677+ infiniteInitialRowCount: 100,
678+
679+ getRowId: function(params) {
680+ return params.data.x1;
681+ },
682+
683+ rowSelection: 'multiple',
684+ enableCellTextSelection: true,
685+
686+ onFirstDataRendered: onFirstDataRendered,
687+
688+ onViewportChanged: function(params) {
689+ // Store viewport state but don't trigger immediate redraw
690+ if (!gridOptions._viewportUpdateScheduled && params.api) {
691+ gridOptions._viewportUpdateScheduled = true;
692+ setTimeout(() => {
693+ // Only refresh if grid still exists
694+ if (params.api) {
695+ // Use a simpler refresh approach
696+ params.api.redrawRows();
697+ gridOptions._viewportUpdateScheduled = false;
698+ }
699+ }, 100);
700+ }
701+ },
702+
703+ // Clear cache when sorting changes
704+ onSortChanged: function(params) {
705+ params.api.purgeInfiniteCache();
706+ }
665707 };
666708
667709 function onFirstDataRendered(params) {
668710 params.api.autoSizeAllColumns(false);
669711 }
712+
670713 function updateTheme() {
671714 const gridDiv = document.querySelector('#myGrid');
672715 if (document.body.classList.contains('vscode-light')) {
@@ -675,15 +718,22 @@ export async function getTableHtml(webview: Webview, file: string): Promise<stri
675718 gridDiv.className = 'ag-theme-balham-dark';
676719 }
677720 }
721+
678722 document.addEventListener('DOMContentLoaded', () => {
679723 gridOptions.columnDefs.forEach(function(column) {
680724 if (column.type === 'dateColumn') {
681725 column.filterParams = dateFilterParams;
682726 }
683727 });
728+
684729 const gridDiv = document.querySelector('#myGrid');
685- new agGrid.createGrid(gridDiv, gridOptions);
730+
731+ const gridApi = agGrid.createGrid(gridDiv, gridOptions);
732+
733+ gridApi.setGridOption('datasource', displayDataSource);
734+
686735 });
736+
687737 function onload() {
688738 updateTheme();
689739 const observer = new MutationObserver(function (event) {
@@ -1030,7 +1080,7 @@ export async function sessionRequest(server: SessionServer, data: any): Promise<
10301080 } ,
10311081 body : JSON . stringify ( data ) ,
10321082 follow : 0 ,
1033- timeout : 500 ,
1083+ timeout : 30000 ,
10341084 } ) ;
10351085
10361086 if ( ! response . ok ) {
0 commit comments