From 67ad5263715ccba3fe1e85655f22a802c315c744 Mon Sep 17 00:00:00 2001 From: Peng Lyu Date: Fri, 15 Feb 2019 17:48:03 -0800 Subject: [PATCH 001/250] comment control. active thread, comment, input update. --- src/vs/editor/common/modes.ts | 12 ++ src/vs/vscode.proposed.d.ts | 35 ++++ .../electron-browser/mainThreadComments.ts | 135 ++++++++++++- src/vs/workbench/api/node/extHost.api.impl.ts | 13 +- src/vs/workbench/api/node/extHost.protocol.ts | 4 + src/vs/workbench/api/node/extHostComments.ts | 183 ++++++++++++++++++ .../electron-browser/commentService.ts | 18 ++ .../electron-browser/commentThreadWidget.ts | 7 + 8 files changed, 403 insertions(+), 4 deletions(-) diff --git a/src/vs/editor/common/modes.ts b/src/vs/editor/common/modes.ts index b864e628aa8..d84cc6f377b 100644 --- a/src/vs/editor/common/modes.ts +++ b/src/vs/editor/common/modes.ts @@ -1224,10 +1224,22 @@ export enum CommentThreadCollapsibleState { Expanded = 1 } + + +/** + * @internal + */ +export interface CommentWidget { + commentThread: CommentThread; + comment?: Comment; + input: string; +} + /** * @internal */ export interface CommentThread { + commentThreadHandle?: number; // use optional type for now to avoid breaking existing api extensionId: string; threadId: string; resource: string; diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index d0a90d17e21..ecbd03224c1 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -935,10 +935,45 @@ declare module 'vscode' { onDidChangeCommentThreads: Event; } + export interface CommentWidget { + /* + * Comment thread in this Comment Widget + */ + commentThread: CommentThread; + + /* + * Focused Comment + * This comment must be part of CommentWidget.commentThread + */ + comment?: Comment; + + /* + * Textarea content in the comment widget. + * There is only one active input box in a comment widget. + */ + input: string; + } + + export interface CommentControl { + readonly id: string; + readonly label: string; + /** + * The active (focused) comment widget. + */ + readonly widget?: CommentWidget; + createCommentThread(id: string, resource: Uri, range: Range, comments: Comment[], collapsibleState?: CommentThreadCollapsibleState): CommentThread; + dispose(): void; + } + + namespace comment { + export function createCommentControl(id: string, label: string): CommentControl; + } + namespace workspace { export function registerDocumentCommentProvider(provider: DocumentCommentProvider): Disposable; export function registerWorkspaceCommentProvider(provider: WorkspaceCommentProvider): Disposable; } + //#endregion //#region Terminal diff --git a/src/vs/workbench/api/electron-browser/mainThreadComments.ts b/src/vs/workbench/api/electron-browser/mainThreadComments.ts index b8b975d7188..2eabd7a6ee0 100644 --- a/src/vs/workbench/api/electron-browser/mainThreadComments.ts +++ b/src/vs/workbench/api/electron-browser/mainThreadComments.ts @@ -14,7 +14,7 @@ import { ExtHostCommentsShape, ExtHostContext, IExtHostContext, MainContext, Mai import { ICommentService } from 'vs/workbench/contrib/comments/electron-browser/commentService'; import { COMMENTS_PANEL_ID, CommentsPanel, COMMENTS_PANEL_TITLE } from 'vs/workbench/contrib/comments/electron-browser/commentsPanel'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -import { URI } from 'vs/base/common/uri'; +import { URI, UriComponents } from 'vs/base/common/uri'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { generateUuid } from 'vs/base/common/uuid'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -22,6 +22,8 @@ import { ICommentsConfiguration } from 'vs/workbench/contrib/comments/electron-b import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; import { Registry } from 'vs/platform/registry/common/platform'; import { PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; +import { IRange } from 'vs/editor/common/core/range'; +import { Emitter, Event } from 'vs/base/common/event'; export class MainThreadDocumentCommentProvider implements modes.DocumentCommentProvider { private _proxy: ExtHostCommentsShape; @@ -78,6 +80,81 @@ export class MainThreadDocumentCommentProvider implements modes.DocumentCommentP onDidChangeCommentThreads = null; } +export class MainThreadCommentThread { + private _input: string = ''; + get input(): string { + return this._input; + } + + set input(value: string) { + this._input = value; + this._onDidChangeInput.fire(value); + } + + private _onDidChangeInput = new Emitter(); + get onDidChangeInput(): Event { return this._onDidChangeInput.event; } + + private _activeComment?: modes.Comment; + + get activeComment(): modes.Comment { + return this._activeComment; + } + + set activeComment(comment: modes.Comment | undefined) { + this._activeComment = comment; + this._onDidChangeActiveComment.fire(comment); + } + + private _onDidChangeActiveComment = new Emitter(); + get onDidChangeActiveComment(): Event { return this._onDidChangeActiveComment.event; } + + + constructor( + public commentThreadHandle: number, + public control: MainThreadCommentControl, + public extensionId: string, + public threadId: string, + public resource: string, + public range: IRange, + public comments: modes.Comment[], + public collapsibleState?: modes.CommentThreadCollapsibleState, + public reply?: modes.Command + ) { + + } +} +export class MainThreadCommentControl { + get handle(): number { + return this._handle; + } + + private _threads: Map = new Map(); + constructor( + private _proxy: ExtHostCommentsShape, + private _handle: number, + private _id: string, + private _label: string + ) { } + + createCommentThread(commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, comments: modes.Comment[], collapseState: modes.CommentThreadCollapsibleState): modes.CommentThread { + let thread = new MainThreadCommentThread( + commentThreadHandle, + this, + '', + threadId, + resource.toString(), + range, + comments, + collapseState, + undefined + ); + + this._threads.set(commentThreadHandle, thread); + + return thread; + } +} + @extHostNamedCustomer(MainContext.MainThreadComments) export class MainThreadComments extends Disposable implements MainThreadCommentsShape { private _disposables: IDisposable[]; @@ -85,6 +162,11 @@ export class MainThreadComments extends Disposable implements MainThreadComments private _documentProviders = new Map(); private _workspaceProviders = new Map(); private _handlers = new Map(); + private _commentControls = new Map(); + + private _activeCommentThread?: MainThreadCommentThread; + private _activeComment?: modes.Comment; + private _input?: string; private _openPanelListener: IDisposable | null; constructor( @@ -98,6 +180,57 @@ export class MainThreadComments extends Disposable implements MainThreadComments super(); this._disposables = []; this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostComments); + this._disposables.push(this._commentService.onDidChangeActiveCommentThread(thread => { + console.log(thread.threadId); + + let control = (thread as MainThreadCommentThread).control; + + if (!control) { + return; + } + + this._activeCommentThread = thread as MainThreadCommentThread; + + this._activeCommentThread.onDidChangeInput(input => { // todo, dispose + this._input = input; + this._proxy.$onActiveCommentWidgetChange(control.handle, this._activeCommentThread, this._activeComment, this._input); + }); + + this._activeCommentThread.onDidChangeActiveComment(comment => { // todo, dispose + this._activeComment = comment; + this._proxy.$onActiveCommentWidgetChange(control.handle, this._activeCommentThread, this._activeComment, this._input); + }); + + this._proxy.$onActiveCommentWidgetChange(control.handle, this._activeCommentThread, this._activeComment, this._input); + })); + + this._disposables.push(this._commentService.onDidChangeInput(input => { + console.log(input); + let control = this._activeCommentThread ? this._activeCommentThread.control : undefined; + + if (!control) { + return; + } + + this._input = input; + + this._proxy.$onActiveCommentWidgetChange(control.handle, this._activeCommentThread, this._activeComment, this._input); + })); + } + + $registerCommentControl(handle: number, id: string, label: string): void { + const provider = new MainThreadCommentControl(this._proxy, handle, id, label); + this._commentControls.set(handle, provider); + } + + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, comments: modes.Comment[], collapseState: modes.CommentThreadCollapsibleState): modes.CommentThread | undefined { + let provider = this._commentControls.get(handle); + + if (!provider) { + return; + } + + return provider.createCommentThread(commentThreadHandle, threadId, resource, range, comments, collapseState); } $registerDocumentCommentProvider(handle: number, features: CommentProviderFeatures): void { diff --git a/src/vs/workbench/api/node/extHost.api.impl.ts b/src/vs/workbench/api/node/extHost.api.impl.ts index c590299823d..678233b1ee7 100644 --- a/src/vs/workbench/api/node/extHost.api.impl.ts +++ b/src/vs/workbench/api/node/extHost.api.impl.ts @@ -115,12 +115,12 @@ export function createApiFactory( const extHostTerminalService = rpcProtocol.set(ExtHostContext.ExtHostTerminalService, new ExtHostTerminalService(rpcProtocol, extHostConfiguration, extHostLogService, extHostCommands)); const extHostDebugService = rpcProtocol.set(ExtHostContext.ExtHostDebugService, new ExtHostDebugService(rpcProtocol, extHostWorkspace, extensionService, extHostDocumentsAndEditors, extHostConfiguration, extHostTerminalService, extHostCommands)); const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService)); + const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands.converter, extHostDocuments)); const extHostSearch = rpcProtocol.set(ExtHostContext.ExtHostSearch, new ExtHostSearch(rpcProtocol, schemeTransformer, extHostLogService)); const extHostTask = rpcProtocol.set(ExtHostContext.ExtHostTask, new ExtHostTask(rpcProtocol, extHostWorkspace, extHostDocumentsAndEditors, extHostConfiguration)); const extHostWindow = rpcProtocol.set(ExtHostContext.ExtHostWindow, new ExtHostWindow(rpcProtocol)); rpcProtocol.set(ExtHostContext.ExtHostExtensionService, extensionService); const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress))); - const exthostCommentProviders = rpcProtocol.set(ExtHostContext.ExtHostComments, new ExtHostComments(rpcProtocol, extHostCommands.converter, extHostDocuments)); const extHostOutputService = rpcProtocol.set(ExtHostContext.ExtHostOutputService, new ExtHostOutputService(initData.logsLocation, rpcProtocol)); rpcProtocol.set(ExtHostContext.ExtHostStorage, extHostStorage); @@ -640,10 +640,10 @@ export function createApiFactory( return extHostSearch.registerFileIndexProvider(scheme, provider); }), registerDocumentCommentProvider: proposedApiFunction(extension, (provider: vscode.DocumentCommentProvider) => { - return exthostCommentProviders.registerDocumentCommentProvider(extension.identifier, provider); + return extHostComment.registerDocumentCommentProvider(extension.identifier, provider); }), registerWorkspaceCommentProvider: proposedApiFunction(extension, (provider: vscode.WorkspaceCommentProvider) => { - return exthostCommentProviders.registerWorkspaceCommentProvider(extension.identifier, provider); + return extHostComment.registerWorkspaceCommentProvider(extension.identifier, provider); }), registerRemoteAuthorityResolver: proposedApiFunction(extension, (authorityPrefix: string, resolver: vscode.RemoteAuthorityResolver) => { return extensionService.registerRemoteAuthorityResolver(authorityPrefix, resolver); @@ -666,6 +666,12 @@ export function createApiFactory( } }; + const comment: typeof vscode.comment = { + createCommentControl(id: string, label: string) { + return extHostComment.createCommentControl(extension, id, label); + } + } + // namespace: debug const debug: typeof vscode.debug = { get activeDebugSession() { @@ -748,6 +754,7 @@ export function createApiFactory( extensions, languages, scm, + comment, tasks, window, workspace, diff --git a/src/vs/workbench/api/node/extHost.protocol.ts b/src/vs/workbench/api/node/extHost.protocol.ts index cfafeed72ac..d75e96cbc3b 100644 --- a/src/vs/workbench/api/node/extHost.protocol.ts +++ b/src/vs/workbench/api/node/extHost.protocol.ts @@ -119,6 +119,8 @@ export interface CommentProviderFeatures { } export interface MainThreadCommentsShape extends IDisposable { + $registerCommentControl(handle: number, id: string, label: string): void; + $createCommentThread(handle: number, commentThreadHandle: number, threadId: string, resource: UriComponents, range: IRange, comments: modes.Comment[], collapseState: modes.CommentThreadCollapsibleState): modes.CommentThread | undefined; $registerDocumentCommentProvider(handle: number, features: CommentProviderFeatures): void; $unregisterDocumentCommentProvider(handle: number): void; $registerWorkspaceCommentProvider(handle: number, extensionId: ExtensionIdentifier): void; @@ -1091,6 +1093,8 @@ export interface ExtHostProgressShape { export interface ExtHostCommentsShape { $provideDocumentComments(handle: number, document: UriComponents): Promise; $createNewCommentThread(handle: number, document: UriComponents, range: IRange, text: string): Promise; + $onActiveCommentWidgetChange(commentControlhandle: number, commentThread: modes.CommentThread, comment: modes.Comment | undefined, input: string): Promise; + $onCommentWidgetInputChange(commentControlhandle: number, value: string): Promise; $replyToCommentThread(handle: number, document: UriComponents, range: IRange, commentThread: modes.CommentThread, text: string): Promise; $editComment(handle: number, document: UriComponents, comment: modes.Comment, text: string): Promise; $deleteComment(handle: number, document: UriComponents, comment: modes.Comment): Promise; diff --git a/src/vs/workbench/api/node/extHostComments.ts b/src/vs/workbench/api/node/extHostComments.ts index f1beb859241..f3f73b471ce 100644 --- a/src/vs/workbench/api/node/extHostComments.ts +++ b/src/vs/workbench/api/node/extHostComments.ts @@ -14,6 +14,8 @@ import { CommandsConverter } from './extHostCommands'; import { IRange } from 'vs/editor/common/core/range'; import { CancellationToken } from 'vs/base/common/cancellation'; import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions'; +import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions'; +import { Event, Emitter } from 'vs/base/common/event'; interface HandlerData { @@ -21,11 +23,17 @@ interface HandlerData { provider: T; } +type ProviderHandle = number; + export class ExtHostComments implements ExtHostCommentsShape { private static handlePool = 0; private _proxy: MainThreadCommentsShape; + private _commentControls: Map = new Map(); + + private _commentControlsByExtension: Map = new Map(); + private _documentProviders = new Map>(); private _workspaceProviders = new Map>(); @@ -37,6 +45,41 @@ export class ExtHostComments implements ExtHostCommentsShape { this._proxy = mainContext.getProxy(MainContext.MainThreadComments); } + createCommentControl(extension: IExtensionDescription, id: string, label: string): vscode.CommentControl { + const handle = ExtHostComments.handlePool++; + + const commentControl = new ExtHostCommentControl(extension, this._proxy, id, label); + this._commentControls.set(handle, commentControl); + + const commentControls = this._commentControlsByExtension.get(ExtensionIdentifier.toKey(extension.identifier)) || []; + commentControls.push(commentControl); + this._commentControlsByExtension.set(ExtensionIdentifier.toKey(extension.identifier), commentControls); + + return commentControl; + } + + $onActiveCommentWidgetChange(commentControlhandle: number, commentThread: modes.CommentThread, comment: modes.Comment | undefined, input: string): Promise { + const commentControl = this._commentControls.get(commentControlhandle); + + if (!commentControl) { + return Promise.resolve(undefined); + } + + commentControl.$onActiveCommentWidgetChange(commentThread, comment, input); + return Promise.resolve(undefined); + } + + $onCommentWidgetInputChange(commentControlhandle: number, value: string): Promise { + const commentControl = this._commentControls.get(commentControlhandle); + + if (!commentControl || !commentControl.widget) { + return Promise.resolve(undefined); + } + + commentControl.widget.$onCommentWidgetInputChange(value); + return Promise.resolve(undefined); + } + registerWorkspaceCommentProvider( extensionId: ExtensionIdentifier, provider: vscode.WorkspaceCommentProvider @@ -202,6 +245,134 @@ export class ExtHostComments implements ExtHostCommentsShape { } } +export class ExtHostCommentThread implements vscode.CommentThread { + private static _handlePool: number = 0; + readonly handle = ExtHostCommentThread._handlePool++; + get threadId(): string { + return this._threadId; + } + + get resource(): vscode.Uri { + return this._resource; + } + get range(): vscode.Range { + return this._range; + } + get comments(): vscode.Comment[] { + return this._comments; + } + + collapsibleState?: vscode.CommentThreadCollapsibleState; + constructor( + private _proxy: MainThreadCommentsShape, + private _commentControlHandle: number, + private _threadId: string, + private _resource: vscode.Uri, + private _range: vscode.Range, + private _comments: vscode.Comment[], + private _collapseState?: vscode.CommentThreadCollapsibleState + ) { + this._proxy.$createCommentThread( + this._commentControlHandle, + this.handle, + this._threadId, + this._resource, + extHostTypeConverter.Range.from(this._range), + this._comments.map(convertToModeComment), + this._collapseState + ); + } + + getComment(commentId: string): vscode.Comment | undefined { + let comments = this._comments.filter(comment => comment.commentId === commentId); + + if (comments && comments.length) { + return comments[0]; + } + + return; + } +} +export class ExtHostCommentWidget implements vscode.CommentWidget { + + private _onDidChangeInput = new Emitter(); + + get onDidChangeInput(): Event { + return this._onDidChangeInput.event; + } + + private _input: string = ''; + get input(): string { + return this._input; + } + + constructor( + public commentThread: vscode.CommentThread, + public comment: vscode.Comment | undefined, + input: string + ) { + this._input = input; + } + + $onCommentWidgetInputChange(value: string) { + this.updateValue(value); + } + + private updateValue(value: string): void { + this._input = value; + this._onDidChangeInput.fire(value); + } +} + +class ExtHostCommentControl implements vscode.CommentControl { + private static _handlePool: number = 0; + + get id(): string { + return this._id; + } + + get label(): string { + return this._label; + } + + public widget?: ExtHostCommentWidget; + + private handle: number = ExtHostCommentControl._handlePool++; + private _threads: Map = new Map(); + + constructor( + _extension: IExtensionDescription, + private _proxy: MainThreadCommentsShape, + private _id: string, + private _label: string + ) { + this._proxy.$registerCommentControl(this.handle, _id, _label); + } + + createCommentThread(id: string, resource: vscode.Uri, range: vscode.Range, comments: vscode.Comment[], collapsibleState?: vscode.CommentThreadCollapsibleState): vscode.CommentThread { + const commentThread = new ExtHostCommentThread(this._proxy, this.handle, id, resource, range, comments, collapsibleState); + this._threads.set(commentThread.handle, commentThread); + + return commentThread; + } + + $onActiveCommentWidgetChange(commentThread: modes.CommentThread, comment: modes.Comment | undefined, input: string) { + let extHostCommentThread = this._threads.get(commentThread.commentThreadHandle); + + const extHostCommentWidget = new ExtHostCommentWidget( + extHostCommentThread, + comment ? extHostCommentThread.getComment(comment.commentId) : undefined, + input + ); + + this.widget = extHostCommentWidget; + } + + dispose(): void { + throw new Error('Method not implemented.'); + } +} + function convertCommentInfo(owner: number, extensionId: ExtensionIdentifier, provider: vscode.DocumentCommentProvider, vscodeCommentInfo: vscode.CommentInfo, commandsConverter: CommandsConverter): modes.CommentInfo { return { extensionId: extensionId.value, @@ -260,6 +431,18 @@ function convertFromComment(comment: modes.Comment): vscode.Comment { }; } +function convertToModeComment(vscodeComment: vscode.Comment): modes.Comment { + const iconPath = vscodeComment.userIconPath ? vscodeComment.userIconPath.toString() : vscodeComment.gravatar; + + return { + commentId: vscodeComment.commentId, + body: extHostTypeConverter.MarkdownString.from(vscodeComment.body), + userName: vscodeComment.userName, + userIconPath: iconPath, + isDraft: vscodeComment.isDraft + }; +} + function convertToComment(provider: vscode.DocumentCommentProvider | vscode.WorkspaceCommentProvider, vscodeComment: vscode.Comment, commandsConverter: CommandsConverter): modes.Comment { const canEdit = !!(provider as vscode.DocumentCommentProvider).editComment && vscodeComment.canEdit; const canDelete = !!(provider as vscode.DocumentCommentProvider).deleteComment && vscodeComment.canDelete; diff --git a/src/vs/workbench/contrib/comments/electron-browser/commentService.ts b/src/vs/workbench/contrib/comments/electron-browser/commentService.ts index 8d89ebd79b1..d2bc0d9464d 100644 --- a/src/vs/workbench/contrib/comments/electron-browser/commentService.ts +++ b/src/vs/workbench/contrib/comments/electron-browser/commentService.ts @@ -35,6 +35,8 @@ export interface ICommentService { readonly onDidSetResourceCommentInfos: Event; readonly onDidSetAllCommentThreads: Event; readonly onDidUpdateCommentThreads: Event; + readonly onDidChangeActiveCommentThread: Event; + readonly onDidChangeInput: Event; readonly onDidSetDataProvider: Event; readonly onDidDeleteDataProvider: Event; setDocumentComments(resource: URI, commentInfos: ICommentInfo[]): void; @@ -57,6 +59,8 @@ export interface ICommentService { addReaction(owner: string, resource: URI, comment: Comment, reaction: CommentReaction): Promise; deleteReaction(owner: string, resource: URI, comment: Comment, reaction: CommentReaction): Promise; getReactionGroup(owner: string): CommentReaction[] | undefined; + setActiveCommentThread(commentThread: CommentThread | null); + setInput(input: string); } export class CommentService extends Disposable implements ICommentService { @@ -77,12 +81,26 @@ export class CommentService extends Disposable implements ICommentService { private readonly _onDidUpdateCommentThreads: Emitter = this._register(new Emitter()); readonly onDidUpdateCommentThreads: Event = this._onDidUpdateCommentThreads.event; + private readonly _onDidChangeActiveCommentThread: Emitter = this._register(new Emitter()); + readonly onDidChangeActiveCommentThread: Event = this._onDidChangeActiveCommentThread.event; + + private readonly _onDidChangeInput: Emitter = this._register(new Emitter()); + readonly onDidChangeInput: Event = this._onDidChangeInput.event; + private _commentProviders = new Map(); constructor() { super(); } + setActiveCommentThread(commentThread: CommentThread | null) { + this._onDidChangeActiveCommentThread.fire(commentThread); + } + + setInput(input: string) { + this._onDidChangeInput.fire(input); + } + setDocumentComments(resource: URI, commentInfos: ICommentInfo[]): void { this._onDidSetResourceCommentInfos.fire({ resource, commentInfos }); } diff --git a/src/vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts b/src/vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts index e7fbb504a5e..94c6ee1e9f8 100644 --- a/src/vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts +++ b/src/vs/workbench/contrib/comments/electron-browser/commentThreadWidget.ts @@ -192,6 +192,10 @@ export class ReviewZoneWidget extends ZoneWidget { this._bodyElement = dom.$('.body'); container.appendChild(this._bodyElement); + + dom.addDisposableListener(this._bodyElement, dom.EventType.FOCUS_IN, e => { + this.commentService.setActiveCommentThread(this._commentThread); + }); } protected _fillHead(container: HTMLElement): void { @@ -335,6 +339,9 @@ export class ReviewZoneWidget extends ZoneWidget { this._commentEditor.setModel(model); this._localToDispose.push(this._commentEditor); this._localToDispose.push(this._commentEditor.getModel().onDidChangeContent(() => this.setCommentEditorDecorations())); + this._localToDispose.push(this._commentEditor.getModel().onDidChangeContent(() => { + this.commentService.setInput(this._commentEditor.getModel().getValue()); + })); this.setCommentEditorDecorations(); // Only add the additional step of clicking a reply button to expand the textarea when there are existing comments From da83a7ece5857560b1b69bef21afbd0b46028683 Mon Sep 17 00:00:00 2001 From: Rachel Macfarlane Date: Wed, 20 Feb 2019 10:05:58 -0800 Subject: [PATCH 002/250] Fixes #69029, File On should be marked as a required field in issue reporter --- src/vs/code/electron-browser/issue/issueReporterPage.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/code/electron-browser/issue/issueReporterPage.ts b/src/vs/code/electron-browser/issue/issueReporterPage.ts index 70d9888849b..a8f85ec258d 100644 --- a/src/vs/code/electron-browser/issue/issueReporterPage.ts +++ b/src/vs/code/electron-browser/issue/issueReporterPage.ts @@ -19,8 +19,8 @@ export default (): string => `
- -