import { window , ViewColumn , ExtensionContext , workspace , Range , WebviewPanel , Uri , TextEditor } from 'vscode' ; import * as path from 'path' ; import * as fs from 'fs' ; import { ReviewCommentService } from './review-comment' ; import { createCommentFromObject , CsvEntry , CsvStructure } from './model' ; import { CommentListEntry } from './comment-list-entry' ; import { clearSelection , getSelectionRanges } from './utils/editor-utils' ; import { colorizedBackgroundDecoration } from './utils/decoration-utils' ; export class WebViewComponent { /** Store all configured categories */ private categories : string [ ] = [ ] ; /** Store the color for background-highlighting */ private highlightDecorationColor : string = '' ; /** Panel used to add/edit a comment */ private panel : WebviewPanel | null = null ; /** Reference to the working editor during note edition */ private editor : TextEditor | null = null ; param title param fileName return private showPanel ( title , fileName ) { this . panel ?. dispose ( ) ; this . panel = this . createWebView ( title ) ; this . panel . webview . html = this . getWebviewContent ( fileName ) ; return this . panel ; } constructor ( public context ) { this . categories = workspace . getConfiguration ( ) . get ( 'code-review.categories' ) as string [ ] ; this . highlightDecorationColor = workspace . getConfiguration ( ) . get ( 'code-review.codeSelectionBackgroundColor' ) as string ; } return private getWorkingEditor ( ) { if ( this . editor === null ) { this . editor = window . activeTextEditor ?? window . visibleTextEditors [ 0 ] ; } return this . editor ; } /**
     * Dispose the stored working editor
     */ private disposeWorkingEditor ( ) { this . editor = null ; } deleteComment ( commentService , entry ) { commentService . deleteComment ( entry . id , entry . description ) ; this . panel ?. dispose ( ) ; } editComment ( commentService , selections , data ) { const editor = this . getWorkingEditor ( ) ; clearSelection ( editor ) ; const decoration = colorizedBackgroundDecoration ( selections , editor , this . highlightDecorationColor ) ; const panel = this . showPanel ( 'Edit code review comment' , editor . document . fileName ) ; data = CsvStructure . finalizeParse ( data ) ; panel . webview . postMessage ( { comment : { ... data } } ) ; panel . webview . onDidReceiveMessage ( ( message ) => { switch ( message . command ) { case 'submit' : const formData = JSON . parse ( message . text ) as CsvEntry ; const newEntry = { ... data , title : formData . title || '' , additional : formData . additional || '' , comment : formData . comment || '' , category : formData . category || '' , priority : formData . priority || 0 , private : formData . private || 0 , } ; commentService . updateComment ( newEntry , this . getWorkingEditor ( ) ) ; panel . dispose ( ) ; break ; case 'cancel' : panel . dispose ( ) ; break ; case 'delete' : window . showInformationMessage ( 'Do you really want to delete this comment?' , ... [ 'Yes' , 'No' ] ) . then ( ( answer ) => { if ( answer === 'Yes' ) { commentService . deleteComment ( data . id , data . title ) ; panel . dispose ( ) ; } else { this . editComment ( commentService , selections , data ) ; } } ) ; break ; } } , undefined , this . context . subscriptions ) ; panel . onDidDispose ( ( ) => { decoration . dispose ( ) ; this . disposeWorkingEditor ( ) ; } ) ; } addComment ( commentService ) { const editor = this . getWorkingEditor ( ) ; const decoration = colorizedBackgroundDecoration ( getSelectionRanges ( editor ) , editor , this . highlightDecorationColor ) ; const panel = this . showPanel ( 'Add code review comment' , editor . document . fileName ) ; panel . webview . onDidReceiveMessage ( ( message ) => { switch ( message . command ) { case 'submit' : commentService . addComment ( createCommentFromObject ( message . text ) , this . getWorkingEditor ( ) ) ; break ; case 'cancel' : break ; } panel . dispose ( ) ; } , undefined , this . context . subscriptions ) ; panel . onDidDispose ( ( ) => { decoration . dispose ( ) ; this . disposeWorkingEditor ( ) ; } ) ; } private createWebView ( title ) { return window . createWebviewPanel ( 'text' , title , { viewColumn : ViewColumn . Beside } , { enableScripts : true , retainContextWhenHidden : true , } ) ; } getWebviewContent ( fileName ) { let selectListString = this . categories . reduce ( ( current , category ) => { return current + `<option value="${ category }">${ category }</option>` ; } , '' ) ; const uri = Uri . joinPath ( this . context . extensionUri , 'dist' , 'webview.html' ) ; const pathUri = uri . with ( { scheme : 'vscode-resource' } ) ; return fs . readFileSync ( pathUri . fsPath , 'utf8' ) . replace ( 'SELECT_LIST_STRING' , selectListString ) . replace ( 'FILENAME' , path . basename ( fileName ) ) ; } }