Skip to content

Commit

Permalink
Make sure picked scroll anchors are actually in the viewport
Browse files Browse the repository at this point in the history
  • Loading branch information
marijnh committed Jun 27, 2023
1 parent 63d4b12 commit 3df8b37
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 20 deletions.
38 changes: 19 additions & 19 deletions src/editorview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -388,13 +388,12 @@ export class EditorView {
scrollAnchorPos = -1
scrollAnchorHeight = this.viewState.heightMap.height
} else {
let block = this.viewState.lineBlockAtHeight(scrollTop)
let block = this.viewState.scrollAnchorAt(scrollTop)
scrollAnchorPos = block.from
scrollAnchorHeight = block.top
}
}
this.updateState = UpdateState.Measuring
let oldViewport = this.viewport
let changed = this.viewState.measure(this)
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null) break
if (i > 5) {
Expand All @@ -411,7 +410,7 @@ export class EditorView {
try { return m.read(this) }
catch(e) { logException(this.state, e); return BadMeasure }
})
let update = ViewUpdate.create(this, this.state, []), redrawn = false, scrolled = false
let update = ViewUpdate.create(this, this.state, []), redrawn = false
update.flags |= changed
if (!updated) updated = update
else updated.flags |= changed
Expand All @@ -428,25 +427,26 @@ export class EditorView {
if (m.write) m.write(measured[i], this)
} catch(e) { logException(this.state, e) }
}
if (this.viewState.editorHeight) {
if (this.viewState.scrollTarget) {
this.docView.scrollIntoView(this.viewState.scrollTarget)
this.viewState.scrollTarget = null
scrolled = true
} else {
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
this.viewState.lineBlockAt(scrollAnchorPos).top
let diff = newAnchorHeight - scrollAnchorHeight
if (diff > 1 || diff < -1) {
scrollTop = sDOM.scrollTop = scrollTop + diff
scrolled = true
if (redrawn) this.docView.updateSelection(true)
if (!update.viewportChanged && this.measureRequests.length == 0) {
if (this.viewState.editorHeight) {
if (this.viewState.scrollTarget) {
this.docView.scrollIntoView(this.viewState.scrollTarget)
this.viewState.scrollTarget = null
continue
} else {
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
this.viewState.lineBlockAt(scrollAnchorPos).top
let diff = newAnchorHeight - scrollAnchorHeight
if (diff > 1 || diff < -1) {
scrollTop = sDOM.scrollTop = scrollTop + diff
scrollAnchorHeight = -1
continue
}
}
scrollAnchorHeight = -1
}
break
}
if (redrawn) this.docView.updateSelection(true)
if (this.viewport.from == oldViewport.from && this.viewport.to == oldViewport.to &&
!scrolled && this.measureRequests.length == 0) break
}
} finally {
this.updateState = UpdateState.Idle
Expand Down
7 changes: 6 additions & 1 deletion src/viewstate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export class ViewState {
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(
prevDeco, this.stateDeco, update ? update.changes : ChangeSet.empty(this.state.doc.length)))
let prevHeight = this.heightMap.height
let scrollAnchor = this.scrolledToBottom ? null : this.lineBlockAtHeight(this.scrollTop)
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop)
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc,
this.heightOracle.setDoc(this.state.doc), heightChanges)
if (this.heightMap.height != prevHeight) update.flags |= UpdateFlag.Height
Expand Down Expand Up @@ -512,6 +512,11 @@ export class ViewState {
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.heightOracle, 0, 0), this.scaler)
}

scrollAnchorAt(scrollTop: number) {
let block = this.lineBlockAtHeight(scrollTop + 8)
return block.from >= this.viewport.from || this.viewportLines[0].top - scrollTop > 200 ? block : this.viewportLines[0]
}

elementAtHeight(height: number): BlockInfo {
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler)
}
Expand Down

0 comments on commit 3df8b37

Please sign in to comment.