Change:
Open Select the top cell and page down a few times Focus hits a cell that is longer than the viewport, which is maybe important, then the next page down moves to a higher cell
When a list item is larger than the viewport, and it's also the only element in the viewport, pressing page down will reveal to the previous element, this is because we did a here (the catch is, the last page element is also the first page element)

Discussion:
let lastPageIndex = this.view.indexAt(this.view.getScrollTop() + this.view.renderHeight); lastPageIndex = lastPageIndex === 0 ? 0 : lastPageIndex - 1; const lastPageElement = this.view.element(lastPageIndex); <del> const currentlyFocusedElement = this.getFocusedElements()[0]; </del> <ins> const currentlyFocusedElementIndex = this.getFocus()[0]; const currentlyFocusedElement = this.view.element(currentlyFocusedElementIndex); </ins> <del> if (currentlyFocusedElement !== lastPageElement) { </del> <ins> if (currentlyFocusedElement !== lastPageElement && lastPageIndex > currentlyFocusedElementIndex) { </ins> const lastGoodPageIndex = this.findPreviousIndex(lastPageIndex, false, filter); if (lastGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(lastGoodPageIndex)) {

} } else { const previousScrollTop = this.view.getScrollTop(); <del> this.view.setScrollTop(previousScrollTop + this.view.renderHeight - this.view.elementHeight(lastPageIndex)); </del> <ins> let nextpageScrollTop = previousScrollTop + this.view.renderHeight; if (lastPageIndex > currentlyFocusedElementIndex) { // scroll last page element to the top only if the last page element is below the focused element nextpageScrollTop -= this.view.elementHeight(lastPageIndex); } this.view.setScrollTop(nextpageScrollTop); </ins> if (this.view.getScrollTop() !== previousScrollTop) { this.setFocus([]);

} const firstPageElement = this.view.element(firstPageIndex); <del> const currentlyFocusedElement = this.getFocusedElements()[0]; </del> <ins> const currentlyFocusedElementIndex = this.getFocus()[0]; const currentlyFocusedElement = this.view.element(currentlyFocusedElementIndex); </ins> <del> if (currentlyFocusedElement !== firstPageElement) { </del> <ins> if (currentlyFocusedElement !== firstPageElement && currentlyFocusedElementIndex >= firstPageIndex) { </ins> const firstGoodPageIndex = this.findNextIndex(firstPageIndex, false, filter); if (firstGoodPageIndex > -1 && currentlyFocusedElement !== this.view.element(firstGoodPageIndex)) {

import { Action2, registerAction2 } from 'vs/platform/actions/common/actions'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { CATEGORIES } from 'vs/workbench/common/actions'; <del> import { getNotebookEditorFromEditorPane, ICellViewModel, ICommonCellViewModelLayoutChangeInfo, INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; </del> <ins> import { getNotebookEditorFromEditorPane, ICellViewModel, ICommonCellViewModelLayoutChangeInfo, INotebookDeltaCellStatusBarItems, INotebookEditor, INotebookEditorContribution } from 'vs/workbench/contrib/notebook/browser/notebookBrowser'; </ins> import { registerNotebookContribution } from 'vs/workbench/contrib/notebook/browser/notebookEditorExtensions'; import { NotebookEditorWidget } from 'vs/workbench/contrib/notebook/browser/notebookEditorWidget'; <ins> import { CellStatusbarAlignment, INotebookCellStatusBarItem } from 'vs/workbench/contrib/notebook/common/notebookCommon'; </ins> import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookService'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService';

private readonly _localStore = this._register(new DisposableStore()); private _cellStateListeners: IDisposable[] = []; <del> private _logging: boolean = false; </del> <ins> private _enabled: boolean = false; private _cellStatusItems: string[] = []; </ins> constructor(private readonly _notebookEditor: INotebookEditor) { super(); this._register(this._notebookEditor.onDidChangeModel(() => { <del> this._localStore.clear(); this._cellStateListeners.forEach(listener => listener.dispose()); if (!this._notebookEditor.hasModel()) { return; } this._updateListener(); </del> <ins> this._update(); </ins> })); <del> this._updateListener(); </del> <ins> this._update(); </ins> } <del> toggleLogging(): void { this._logging = !this._logging; </del> <ins> toggle(): void { this._enabled = !this._enabled; this._update(); } private _update() { this._localStore.clear(); this._cellStateListeners.forEach(listener => listener.dispose()); if (!this._notebookEditor.hasModel()) { return; } this._updateListener(); </ins> } private _log(cell: ICellViewModel, e: any) { <del> if (this._logging) { </del> <ins> if (this._enabled) { </ins> const oldHeight = (this._notebookEditor as NotebookEditorWidget).getViewHeight(cell); console.log(`cell#${cell.handle}`, e, `${oldHeight} -> ${cell.layoutInfo.totalHeight}`); }

dispose(deletedCells); }); })); <ins> const vm = this._notebookEditor._getViewModel(); let items: INotebookDeltaCellStatusBarItems[] = []; if (this._enabled) { items = this._getItemsForCells(); } this._cellStatusItems = vm.deltaCellStatusBarItems(this._cellStatusItems, items); } private _getItemsForCells(): INotebookDeltaCellStatusBarItems[] { const items: INotebookDeltaCellStatusBarItems[] = []; for (let i = 0; i < this._notebookEditor.getLength(); i++) { items.push({ handle: i, items: [ <INotebookCellStatusBarItem>{ text: `index: ${i}`, alignment: CellStatusbarAlignment.Left, priority: Number.MAX_SAFE_INTEGER } ] }); } return items; </ins> } override dispose() {

} const controller = editor.getContribution<TroubleshootController>(TroubleshootController.id); <del> controller?.toggleLogging(); </del> <ins> controller?.toggle(); </ins> } });