Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Markdown Static Preview Scrolling Fixes #123727

Merged
merged 14 commits into from May 20, 2021

Conversation

andreamah
Copy link
Contributor

@andreamah andreamah commented May 12, 2021

This PR addresses two bugs with scrolling in markdown static preview:

  1. When toggling between the text editor and custom (static preview) editor, this should ensure that the scrolling position stays persistent. It currently loads the editor at the top regardless of where the user scrolled last.
  2. When opening a static preview in one tab and a text editor for the same file in another column, scrolling the static preview scrolls the text editor, but scrolling the text editor does not scroll the static preview.

Steps to test:
Issue 1:

  • Open a markdown file that is long enough to need scrolling and scroll down.
  • Use the command palette to do View - Reopen Editor With... > Markdown Preview (Experimental)
    • The resulting preview should be where you previously scrolled to in the text editor. Scroll on this page again.
  • Use the command palate to switch back to the text editor. It should load at the point where the static preview left off.

Issue 2:

  • Open a markdown file as a static preview (View - Reopen Editor With... > Markdown Preview (Experimental) in command palette).
  • Open the same file in another column, but in the regular text editor.
  • Scroll both sides. Both sides should scroll along with one another.

This PR addresses #84520

@andreamah andreamah requested a review from mjbvz May 12, 2021 23:14
@andreamah andreamah added this to the May 2021 milestone May 12, 2021
@andreamah andreamah changed the title Initial Markdown Static Preview State Markdown Static Preview Scrolling Fixes May 12, 2021
Copy link
Contributor

@mjbvz mjbvz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like the right direction but I think the implementation could be cleaned up a little. Let me know if you have any questions about the comments

@@ -160,14 +160,18 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
document: vscode.TextDocument,
webview: vscode.WebviewPanel
): Promise<void> {
const lineNumber = this._topmostLineMonitor.previousMDTextEditor?.document.uri.toString() === document.uri.toString() ? this._topmostLineMonitor.previousMDTextEditor?.visibleRanges[0].start.line : undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of exposing previousMDTextEditor, can you hide this behind a method that gets the line for a given uri?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

previousMDTextEditor changed to an internal map with public functions for access.


// When at a markdown file, apply existing scroll settings from static preview if applicable.
// Also save reference to text editor for line number reference later
if (textEditor && isMarkdownFile(textEditor.document!)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Avoid using ! where possible

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fixed now.


if (this.previousStaticEditorInfo.uri?.toString() === textEditor.document.uri.toString()) {
const line = this.previousStaticEditorInfo.line ? this.previousStaticEditorInfo.line : 0;
scrollEditorToLine(line, textEditor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the TopMostLineMonitor being scrolling editors or can this live somewhere else?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to MarkdownPreviewManager

export class TopmostLineMonitor extends Disposable {

private readonly pendingUpdates = new Map<string, number>();
private readonly throttle = 50;
public previousMDTextEditor: vscode.TextEditor | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there cases where you can more than one markdown file that we need to track the scroll position of? Try seeing if you can hit this using multiple editors and editor groups with different files

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the previous text editors to be indexed via string URI so that multiple editor instances can be accessed. This might get populated if the user has a lot of markdown files open (?)

@@ -220,6 +224,11 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview
this._staticPreviews.delete(preview);
});

// Continuously update the scroll info in case user changes the editor.
preview.onScroll((scrollInfo) => {
this._topmostLineMonitor.previousStaticEditorInfo = scrollInfo;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this live in the preview itself?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, accidentally forgot that I passed an instance of the topmost line monitor into the preview. Preview should now do this.

@@ -7,13 +7,21 @@ import * as vscode from 'vscode';
import { Disposable } from '../util/dispose';
import { isMarkdownFile } from './file';

export interface LastScrollLocation {
readonly line: number;
readonly uri: vscode.Uri | undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the cases where uri can be undefined? Is this something we'd expect to happen?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally allowed for undefined for initialization; removed undefined.

@andreamah
Copy link
Contributor Author

I noticed another bug where all other open text editors for a markdown file disappear when one instance enters static preview. It seems that this bug isn't caused by this PR's changes because it also occurs on main. I will try to look into it for this PR also.

@andreamah
Copy link
Contributor Author

I noticed another bug where all other open text editors for a markdown file disappear when one instance enters static preview. It seems that this bug isn't caused by this PR's changes because it also occurs on main. I will try to look into it for this PR also.

When running the debugger, it seems that the other text editors are removed prior to entering the resolveCustomTextEditor function in the preview manager. Thus, I feel like it might be an issue outside of the extension code that is being focused on in this PR?

@andreamah
Copy link
Contributor Author

I noticed another bug where all other open text editors for a markdown file disappear when one instance enters static preview. It seems that this bug isn't caused by this PR's changes because it also occurs on main. I will try to look into it for this PR also.

When running the debugger, it seems that the other text editors are removed prior to entering the resolveCustomTextEditor function in the preview manager. Thus, I feel like it might be an issue outside of the extension code that is being focused on in this PR?

Regarding this, I created #124134


public setPreviousMDTextEditorLine(editor: vscode.TextEditor) {
const uri = editor.document.uri;
this.previousMDTextEditors.set(uri.toString(), editor);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TextEditor object becomes invalid as soon as that editor is closed, so it's kind of dangerous to keep a reference to it around

Instead you can use window.visibleTextEditors to get all current editors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to keep information about closed text editors to get the scroll info when we switch editors. Since keeping text editors won't work, we can just keep the last scroll location as with the static preview scroll locations.

this.previousMDTextEditors.set(uri.toString(), editor);
}

public getPreviousMDTextEditorLineByUri(resource: vscode.Uri) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Add an explicit return types

this.setPreviousMDTextEditorLine(textEditor);
}

this.isPrevEditorCustom = (textEditor === undefined);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isPrevCustomEditor will up being true when you do anything that causes there not to be an active text editor, such as switching to an extension page or maximizing the panel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, will link isPrevCustomEditor to PreviewManager._activePreview == undefined

return editor?.visibleRanges[0].start.line;
}

public setPreviousStaticEditorLine(scrollLocation: LastScrollLocation) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere?

Copy link
Contributor Author

@andreamah andreamah May 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

used in preview.ts.

this.previousStaticEditorInfo.set(scrollLocation.uri.toString(), scrollLocation);
}

public getPreviousStaticEditorLineByUri(resource: vscode.Uri) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used outside of this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, will change to private

if (this.isPrevEditorCustom) {
const line = this.getPreviousStaticEditorLineByUri(textEditor.document.uri);
if (line) {
this._onEditorNeedsScrolling.fire({ line: line, editor: textEditor });
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to have the previewManager instead monitor onDidChangeActiveTextEditor and then ask the TopMostLineMonitor if it need to scroll somewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, that would also functionally work. I can make that change.

@@ -284,6 +286,8 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
});
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Remove extra spaces

export class TopmostLineMonitor extends Disposable {

private readonly pendingUpdates = new Map<string, number>();
private readonly throttle = 50;
private previousEditorInfo = new Map<string, LastScrollLocation>();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike the previous commits, line numbers from static previews and text editors are both tracked in this object. I believe that they were tracked in different objects before because text editors used the reference to the editor object to find line number, but both editors now update using the same way.

@andreamah andreamah enabled auto-merge May 20, 2021 16:00
@andreamah andreamah merged commit ab5df44 into main May 20, 2021
@andreamah andreamah deleted the dev/t-andreamah/markdown-static-preview-scroll-state branch May 20, 2021 16:03
@andreamah andreamah mentioned this pull request Jun 14, 2021
@github-actions github-actions bot locked and limited conversation to collaborators Jul 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants