-
Notifications
You must be signed in to change notification settings - Fork 665
Extract leetcode webview base class & add md settings listener #270
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
Conversation
Vigilans
commented
Apr 14, 2019
- A webview base class
- webview listener for Apply vscode's markdown settings to MarkdownEngine #260
src/webview/LeetCodeWebview.ts
Outdated
} | ||
} | ||
|
||
protected showWebviewInternal(): this is { panel: WebviewPanel } { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain more about this method? The return type is this
, but the actual returned value is true
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
param is type
is a user-defined type guard in typescript's grammar.
It reduced the scope of union type:
function isTypeDefined(obj: Type | undefined): obj is Type {
return obj !== undefined;
}
let a: Type | undefined;
a.method() // ts error, a may be undefined
if (isTypeDefined(a)) {
a.method(); // now a's type is only `Type`, `undefined` is reduced
}
this is type
is a way to guard a class member's type:
microsoft/TypeScript#26212
this is { panel: WebviewPanel }
makes sure this.panel
is not undefined.
So the code here do not need to use this.panel!.method()
to assert defined:
if (this.showWebviewInternal()) {
this.panel.title = `${node.name}: Preview`; // now this.panel's undefined type is reduced
this.panel.reveal(ViewColumn.One);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why we are not just calling showWebviewInternal()
but put it in the if block.
I do not see any benefits to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean the code below?
this.showWebviewInternal();
this.panel!.title = `${node.name}: Preview`; // this.panel's undefined type is not reduced
this.panel!.reveal(ViewColumn.One);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main problem here is, we should extract the fields in ILeetCodeWebviewOption
as the member of the base class. The reason for doing that:
- Each web view has its own unique
viewType
- Each web view has its own location to display - the
viewColumn
- Each web view has the member title to determine the title of the editor.
So after the extraction, what you need to do is:
- Move all the logic about the panel update into
showWebviewInternal()
- Update the title field when needed.
this.title = xxxx
this.showWebviewInternal();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've brought everything except sideMode
in next PR to this PR. It includes the improvement on the webview base class, like mentioned above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you really think there is no relationship? Did you ever test yourself what is the visual effect when the title keeps A so long long long long long name: preview
and A so long long long long long name: solution
in Column 2? Will the user be able to easily change between the tabs?
Why do you pay more attention to something in the next PR which I haven't given illustration yet?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of cause I need to understand what you will do in the next PR since they have some relationship. This will determine whether we need to keep getWebviewOption()
or make them as the class member.
The codes written in a good way should not only have good experience but also good at self-explain. This is very important to attract more community contribution. That's why I'm keeping asking you those questions. From the code itself, I cannot get your point. There's no GIF/picture to illustrate that. Then how could I know your point is that the tab is so long that make the experience bad?
Besides, From my understanding, the reason to rename to the title to Description
is that you hope the size of the tab is not too big when VS Code has two columns. The real reason actually is having limited resolution, and multiple columns is one of the possible reason to cause the limited resolution.
Take the VS Code embedded Markdown extension as an example, You can see there is no optimization when the tab is too long.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not saying that we should not do the optimation. It's acceptable to do it as long as the code logic is easy to understand.
7f1f732
to
9f0999e
Compare
src/webview/LeetCodeWebview.ts
Outdated
localResourceRoots: markdownEngine.localResourceRoots, | ||
}); | ||
this.panel.onDidDispose(this.onDidDisposeWebview, this, this.context.subscriptions); | ||
this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.context.subscriptions); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: The onDidReceiveMessage
can also be disposed in onDidDisposeWebview
Put it into
subscriptions
is fine though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
another alternative is to pass this.context.subscriptions
to workspace.onDidChangeConfiguration
, and do not maintain configListener
in LeetCodeWebview
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just my personal opinion: putting into subscriptions
is a passive way to clean up the memory:
An array to which disposables can be added. When this extension is deactivated the disposables will be disposed.
It's more suitable for the command, global objects, etc. Since once the command is registered, in most cases you will not remove it during the extension is running.
While here, once the panel is disposed. We need to dispose the listener as well to avoid that multiple listeners are working in the meantime. So disposing them in the onDidDisposeWebview()
could be better.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This way?
private listeners: Disposable[] = [];
//...
this.panel.onDidDispose(this.onDidDisposeWebview, this, this.listeners);
this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.listeners);
workspace.onDidChangeConfiguration(this.onDidChangeConfiguration, this, this.listeners);
//...
protected onDidDisposeWebview(): void {
this.panel = undefined;
for (const listener of this.listeners) {
listener.dispose();
}
this.listeners = [];
}
In this way, this.context
will report never used
by tslint. We could make such modification:
public initialize(context: ExtensionContext): void {
this.context = context;
this.context.subscriptions.push(this);
}
It separates the intialization code in activate
function. Or, we could just move this.context
out of webview.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just move this.context
out of webview looks good to me.
src/webview/LeetCodeWebview.ts
Outdated
} | ||
} | ||
|
||
protected showWebviewInternal(): this is { panel: WebviewPanel } { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why we are not just calling showWebviewInternal()
but put it in the if block.
I do not see any benefits to do this.
My argument for using
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the GIFs. Much more clear now.