-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Make preference node rendering customizable and provide file selection #10766
Make preference node rendering customizable and provide file selection #10766
Conversation
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.
Functionally, this appears to work well. I've made a number of comments, mainly about naming, as I think the names currently used don't make very clear what problem is being addressed. Specifically, I think RenderHint
and associated names could be made more generic and accurate if changed to something like TypeDetails
, and BrowseNode
and associated names would be clearer as FilepathNode
etc.
Another detail of the implementation worth considering is whether to use a ContributionProvider
- whose members generally have to be registered at build time - or a registry that permits runtime extension.
@@ -87,6 +87,7 @@ export async function getExternalTerminalSchema(externalTerminalService: Externa | |||
properties: { | |||
'terminal.external.windowsExec': { | |||
type: 'string', | |||
renderHint: { rendering: 'browse' }, |
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.
Regarding most of the names including 'browse,' I think it would makes sense to change to something that refers to something in the semantic field of file / path / folder, for example, in this case:
type: 'string'
typeDetails: {
isFilepath: true,
selectionProps: ...OpenFileDialogProps
}
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 renamed the fields to better match the file/file path terminology.
packages/preferences/src/browser/views/components/preference-browse-input.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-browse-input.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-browse-input.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-browse-input.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-node-renderer-service.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-node-renderer-service.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-node-renderer-service.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/preference-widget-bindings.ts
Outdated
Show resolved
Hide resolved
packages/preferences/src/browser/views/components/preference-node-renderer-service.ts
Outdated
Show resolved
Hide resolved
@colin-grant-work Thank you very much for your detailed review! Unfortunately it took me some time to come back to this but I followed your suggestions which were all great in my opinion. The new change looks much cleaner now (even though it touches more code). |
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 is just about there. I have only one substantive comment on the Registry
implementation. I traced the performance of the handleDisplayChange
method on master
and with this code, and despite the increase in overhead picking a renderer for each node, there was only a very small increase in the time taken to fully render (0.1 seconds; 0.5sec vs. 0.4sec previously). A small price to pay for a considerable increase in flexibility. 👍
import { | ||
createPreferenceProxy, | ||
PreferenceSchema, | ||
PreferenceService, | ||
PreferenceProxy | ||
createPreferenceProxy, PreferenceProxy, PreferenceSchema, | ||
PreferenceService | ||
} from '@theia/core/lib/browser'; | ||
import { PreferenceSchemaProvider } from '@theia/core/lib/browser/preferences/preference-contribution'; | ||
import { isWindows, isOSX } from '@theia/core/lib/common/os'; | ||
import { ExternalTerminalService, ExternalTerminalConfiguration } from '../common/external-terminal'; | ||
import { nls } from '@theia/core/lib/common/nls'; | ||
import { isOSX, isWindows } from '@theia/core/lib/common/os'; | ||
import { inject, injectable, interfaces, postConstruct } from '@theia/core/shared/inversify'; | ||
import { ExternalTerminalConfiguration, ExternalTerminalService } from '../common/external-terminal'; |
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.
It looks like these changes are probably the work of an auto-formatter of some kind? Since there isn't currently a standard for the repo for the organization of imports (perhaps there should be), it's likely better to turn such auto-formatting off for the time being to limit the diff to relevant changes.
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 are right, sorry for that! I restored the original formatting which I usually do when I check the commit but seems like this slipped through ;-)
this.setPreference(selection); | ||
} | ||
} | ||
|
||
protected setPreference(uri: URI): void { | ||
this.interactable.value = uri.path.toString(); | ||
this.setPreferenceImmediately(uri.path.toString()); | ||
} |
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.
Minor: since these classes already have two setPreference
methods, I think it would be preferable to just call setPreferenceImmediately
directly on line 97 rather than introducing a third method with that prefix.
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 adapted the method to override setPreferenceImmediately
instead and now call that directly. You are right that having 3 methods with similar functionality is definitely curios.
export interface PreferenceNodeRendererCreatorRegistry { | ||
registerPreferenceNodeRendererCreator(registry: PreferenceNodeRendererCreator): Disposable; | ||
unregisterPreferenceNodeRendererCreator(registry: PreferenceNodeRendererCreator): void; | ||
getPreferenceNodeRendererCreator(node: Preference.TreeNode): PreferenceNodeRendererCreator; | ||
} |
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 registry should have an Emitter/Event
to signal that its contents have changed so that users of registry (PreferenceEditorWidget
, in this case) can subscribe and react to changes appropriately.
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 added an event to the interface and implementation but just a simple one for change and no further details (e.g., added or removed creators), I hope that is fine. Since the PreferenceEditorWidget
does not directly use that I was not sure how to apply it but I think having it is definitely a valuable contribution.
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.
@martin-fleck-at, I believe the place to refer to the event would be in the PreferenceEditorWidget
class. It should trigger a total repopulation of the renderer
s field analagous to what happens when the widget starts up.
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.
@colin-grant-work Ah yes, I found it! Somehow I missed that the renderers are cached in the widget so thank you for noticing! I now remove all the cached renderers and re-render the widget as expected. I made a small test commit on a separate branch that toggles the file contribution in case you want to test it: https://github.com/martin-fleck-at/theia/commit/2c4e17b69d9d84f0a4fb586e681da2002187b731
@colin-grant-work Thank you very much for your detailed review and the rendering performance measurement, that is very interesting and good to know! I already squashed the commits now on top of master but if there is anything else, I'll gladly add it. |
- Introduce preference node render registry to support contributions -- Convert previous renderer factory content to default contribution -- Let new renderer factory implementation use service -- Contributions are ranked similar to open handlers - Add 'typeDetails' as generic optional property to preference schema -- Contributions may use type details for further properties - Provide base for leaf node contributions and render hints - Implement concrete string renderer for single file selection -- Usage Example: Windows terminal (external and internal)
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.
Looks good to me. I tested with the supplied test commit, and the preference was accurately rerendered. 👍
What it does
Fixes #10765
Introduce preference node render service to support contributions
Provide base for leaf node contributions and render hints
Implement concrete string renderer for single file selection
How to test
Review checklist
Reminder for reviewers