Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upExtract leetcode webview base class & add md settings listener #270
Conversation
} | ||
} | ||
|
||
protected showWebviewInternal(): this is { panel: WebviewPanel } { |
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 14, 2019
Member
Could you explain more about this method? The return type is this
, but the actual returned value is true
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 14, 2019
Author
Contributor
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);
}
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 15, 2019
Member
Then why we are not just calling showWebviewInternal()
but put it in the if block.
I do not see any benefits to do this.
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 15, 2019
•
Author
Contributor
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);
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 15, 2019
Member
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();
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 16, 2019
Author
Contributor
I've brought everything except sideMode
in next PR to this PR. It includes the improvement on the webview base class, like mentioned above.
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 16, 2019
Author
Contributor
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?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 16, 2019
Member
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.
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 16, 2019
Member
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.
localResourceRoots: markdownEngine.localResourceRoots, | ||
}); | ||
this.panel.onDidDispose(this.onDidDisposeWebview, this, this.context.subscriptions); | ||
this.panel.webview.onDidReceiveMessage(this.onDidReceiveMessage, this, this.context.subscriptions); |
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 15, 2019
•
Member
nit: The onDidReceiveMessage
can also be disposed in onDidDisposeWebview
Put it into
subscriptions
is fine though.
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 15, 2019
Author
Contributor
another alternative is to pass this.context.subscriptions
to workspace.onDidChangeConfiguration
, and do not maintain configListener
in LeetCodeWebview
?
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 15, 2019
Member
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.
This comment has been minimized.
This comment has been minimized.
Vigilans
Apr 15, 2019
•
Author
Contributor
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.
This comment has been minimized.
This comment has been minimized.
} | ||
} | ||
|
||
protected showWebviewInternal(): this is { panel: WebviewPanel } { |
This comment has been minimized.
This comment has been minimized.
jdneo
Apr 15, 2019
Member
Then why we are not just calling showWebviewInternal()
but put it in the if block.
I do not see any benefits to do this.
… next PR
My argument for using
|
Thank you for the GIFs. Much more clear now. |
Vigilans commentedApr 14, 2019