@@ -6,152 +6,159 @@ import * as path from 'path'
66 * Manages React webview panels
77 */
88class ReactWebView {
9- //@ts -ignore
10- private panel :vscode . WebviewPanel
11- private extensionPath :string
12- private disposables :vscode . Disposable [ ] = [ ]
13- private onReceive :any // TODO: properly type
14-
15- public constructor ( extensionPath :string ) {
16- this . extensionPath = extensionPath
17-
18- // Create and show a new webview panel
19- this . panel = this . createWebviewPanel ( vscode . ViewColumn . Two )
20-
21- // Set the webview's initial html content
22- this . panel . webview . html = this . getHtmlForWebview ( )
23-
24- // Listen for when the panel is disposed
25- // This happens when the user closes the panel or when the panel is closed programatically
26- this . panel . onDidDispose ( ( ) => this . dispose ( ) , null , this . disposables )
27-
28- // Handle messages from the webview
29- const onReceive = ( action :string | CR . Action ) => vscode . commands . executeCommand ( 'coderoad.receive_action' , action )
30- this . panel . webview . onDidReceiveMessage ( onReceive , null , this . disposables )
31-
32- // update panel on changes
33- const updateWindows = ( ) => {
34- vscode . commands . executeCommand ( 'vscode.setEditorLayout' , { orientation :0 , groups :[ { groups :[ { } ] , size :0.6 } , { groups :[ { } ] , size :0.4 } ] } )
35- this . panel . reveal ( vscode . ViewColumn . Two )
36- }
37- // prevents new panels from going ontop of coderoad panel
38- vscode . window . onDidChangeActiveTextEditor ( ( param ) => {
39- if ( ! param || param . viewColumn !== vscode . ViewColumn . Two ) {
40- updateWindows ( )
41- }
42- } )
43- // prevents moving coderoad panel on top of left panel
44- vscode . window . onDidChangeVisibleTextEditors ( ( param ) => {
45- updateWindows ( )
46- } )
47-
48- // TODO: prevent window from moving to the left when no windows remain on rights
9+ //@ts -ignore
10+ private panel :vscode . WebviewPanel
11+ private extensionPath :string
12+ private disposables :vscode . Disposable [ ] = [ ]
13+ private onReceive :any // TODO: properly type
14+
15+ public constructor ( extensionPath :string ) {
16+ this . extensionPath = extensionPath
17+
18+ // Create and show a new webview panel
19+ this . panel = this . createWebviewPanel ( vscode . ViewColumn . Two )
20+
21+ // Set the webview's initial html content
22+ this . panel . webview . html = this . getHtmlForWebview ( )
23+
24+ // Listen for when the panel is disposed
25+ // This happens when the user closes the panel or when the panel is closed programatically
26+ // this.panel.onDidDispose(() => this.dispose(), null, this.disposables)
27+
28+ // Handle messages from the webview
29+ const onReceive = ( action :string | CR . Action ) => vscode . commands . executeCommand ( 'coderoad.receive_action' , action )
30+ this . panel . webview . onDidReceiveMessage ( onReceive , null , this . disposables )
31+
32+ // update panel on changes
33+ const updateWindows = ( ) => {
34+ vscode . commands . executeCommand ( 'vscode.setEditorLayout' , {
35+ orientation :0 ,
36+ groups :[ { groups :[ { } ] , size :0.6 } , { groups :[ { } ] , size :0.4 } ] ,
37+ } )
38+ this . panel . reveal ( vscode . ViewColumn . Two )
4939}
5040
51- public createOrShow ( column :number ) :void {
52- // If we already have a panel, show it.
53- // Otherwise, create a new panel.
54- if ( this . panel && this . panel . webview ) {
55- console . log ( 'reveal' )
56- this . panel . reveal ( column )
57- } else {
58- console . log ( 'make new panel' )
59- this . panel = this . createWebviewPanel ( column )
60- }
41+ this . panel . onDidDispose ( ( ) => {
42+ updateWindows ( )
43+ } )
44+
45+ // this.panel.onDidChangeViewState(() => {
46+ // console.log('onDidChangeViewState')
47+ // updateWindows()
48+ // })
49+
50+ // prevents new panels from going ontop of coderoad panel
51+ vscode . window . onDidChangeActiveTextEditor ( param => {
52+ if ( ! param || param . viewColumn !== vscode . ViewColumn . Two ) {
53+ updateWindows ( )
54+ }
55+ } )
56+ // // prevents moving coderoad panel on top of left panel
57+ vscode . window . onDidChangeVisibleTextEditors ( param => {
58+ updateWindows ( )
59+ } )
60+
61+ // TODO: prevent window from moving to the left when no windows remain on rights
62+ }
63+
64+ public createOrShow ( column :number ) :void {
65+ // If we already have a panel, show it.
66+ // Otherwise, create a new panel.
67+ if ( this . panel && this . panel . webview ) {
68+ this . panel . reveal ( column )
69+ } else {
70+ this . panel = this . createWebviewPanel ( column )
6171}
62-
63- private createWebviewPanel ( column :number ) :vscode . WebviewPanel {
64- const viewType = 'CodeRoad'
65- const title = 'CodeRoad'
66- const config = {
67- // Enable javascript in the webview
68- enableScripts :true ,
69- // And restric the webview to only loading content from our extension's `media` directory.
70- localResourceRoots :[ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) ] ,
71- // prevents destroying the window when it is in the background
72- retainContextWhenHidden :true ,
73- }
74- return vscode . window . createWebviewPanel ( viewType , title , column , config )
72+ }
73+
74+ private createWebviewPanel ( column :number ) :vscode . WebviewPanel {
75+ const viewType = 'CodeRoad'
76+ const title = 'CodeRoad'
77+ const config = {
78+ // Enable javascript in the webview
79+ enableScripts :true ,
80+ // And restric the webview to only loading content from our extension's `media` directory.
81+ localResourceRoots :[ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) ] ,
82+ // prevents destroying the window when it is in the background
83+ retainContextWhenHidden :true ,
7584}
76-
77- private getNonce ( ) : string {
78- let text = ''
79- const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
80- for ( let i = 0 ; i < 32 ; i ++ ) {
81- text += possible . charAt ( Math . floor ( Math . random ( ) * possible . length ) )
82- }
83- return text
85+ return vscode . window . createWebviewPanel ( viewType , title , column , config )
86+ }
87+
88+ private getNonce ( ) : string {
89+ let text = ''
90+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
91+ for ( let i = 0 ; i < 32 ; i ++ ) {
92+ text += possible . charAt ( Math . floor ( Math . random ( ) * possible . length ) )
8493}
85-
86- public async postMessage ( action :CR . Action ) :Promise < void > {
87- console . log ( 'webview postMessage' )
88- console . log ( action )
89- // Send a message to the webview webview.
90- // You can send any JSON serializable data.
91- const success = await this . panel . webview . postMessage ( action )
92- if ( ! success ) {
93- throw new Error ( `Message post failure:${ JSON . stringify ( action ) } ` )
94- }
95- console . log ( 'postMessage sent' )
94+ return text
95+ }
96+
97+ public async postMessage ( action :CR . Action ) :Promise < void > {
98+ // Send a message to the webview webview.
99+ // You can send any JSON serializable data.
100+ const success = await this . panel . webview . postMessage ( action )
101+ if ( ! success ) {
102+ throw new Error ( `Message post failure:${ JSON . stringify ( action ) } ` )
96103}
104+ }
97105
98- public dispose ( ) :void {
99- // Clean up our resources
100- this . panel . dispose ( )
106+ public dispose ( ) :void {
107+ // Clean up our resources
108+ this . panel . dispose ( )
101109
102- while ( this . disposables . length ) {
103- const x = this . disposables . pop ( )
104- if ( x ) {
105- x . dispose ( )
106- }
107- }
110+ while ( this . disposables . length ) {
111+ const x = this . disposables . pop ( )
112+ if ( x ) {
113+ x . dispose ( )
114+ }
108115}
109-
110- private getHtmlForWebview ( ) :string {
111-
112- // eslint-disable-next-line
113- const manifest = require ( path . join ( this . extensionPath , 'build' , 'asset-manifest.json' ) )
114- const mainScript = manifest . files [ 'main.js' ]
115- // grab first chunk
116- const chunk = Object . keys ( manifest . files ) . filter ( f => f . match ( / ^ s t a t i c \/ j s \/ .+ \. j s $ / ) ) [ 0 ]
117- const chunkScript = manifest . files [ chunk ]
118- const mainStyle = manifest . files [ 'main.css' ]
119-
120- const scriptPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainScript ) )
121- const scriptUri = scriptPathOnDisk . with ( { scheme :'vscode-resource' } )
122- const chunkPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , chunkScript ) )
123- const chunkUri = chunkPathOnDisk . with ( { scheme :'vscode-resource' } )
124- const stylePathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainStyle ) )
125- const styleUri = stylePathOnDisk . with ( { scheme :'vscode-resource' } )
126-
127- // Use a nonce to whitelist which scripts can be run
128- const nonce = this . getNonce ( )
129- const nonce2 = this . getNonce ( )
130- const nonce3 = this . getNonce ( )
131-
132- return `<!DOCTYPE html>
116+ }
117+
118+ private getHtmlForWebview ( ) :string {
119+ // eslint-disable-next-line
120+ const manifest = require ( path . join ( this . extensionPath , 'build' , 'asset-manifest.json' ) )
121+ const mainScript = manifest . files [ 'main.js' ]
122+ // grab first chunk
123+ const chunk = Object . keys ( manifest . files ) . filter ( f => f . match ( / ^ s t a t i c \/ j s \/ .+ \. j s $ / ) ) [ 0 ]
124+ const chunkScript = manifest . files [ chunk ]
125+ const mainStyle = manifest . files [ 'main.css' ]
126+
127+ const scriptPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainScript ) )
128+ const scriptUri = scriptPathOnDisk . with ( { scheme :'vscode-resource' } )
129+ const chunkPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , chunkScript ) )
130+ const chunkUri = chunkPathOnDisk . with ( { scheme :'vscode-resource' } )
131+ const stylePathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainStyle ) )
132+ const styleUri = stylePathOnDisk . with ( { scheme :'vscode-resource' } )
133+
134+ // Use a nonce to whitelist which scripts can be run
135+ const [ n1 , n2 , n3 ] = [ 1 , 2 , 3 ] . map ( this . getNonce )
136+
137+ return `<!DOCTYPE html>
133138<html lang="en">
134- <head>
135- <meta charset="utf-8">
136- <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
137- <meta name="theme-color" content="#000000">
138- <title>React App</title>
139- <link rel="manifest" href="./manifest.json" />
140- <link rel="stylesheet" type="text/css" href="${ styleUri } ">
141- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${ nonce } ' 'nonce-${ nonce2 } ' 'nonce-${ nonce3 } '; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
142- <base href="${ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) . with ( { scheme :'vscode-resource' } ) } /">
143- <style></style>
144- </head>
145-
146- <body>
147- <noscript>You need to enable JavaScript to run this app.</noscript>
148- <div id="root">Loading...</div>
149- <script nonce=${ nonce } src="./webpackBuild.js"></script>
150- <script nonce=${ nonce2 } src="${ chunkUri } "></script>
151- <script nonce="${ nonce3 } " src="${ scriptUri } "></script>
152- </body>
139+ <head>
140+ <meta charset="utf-8">
141+ <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
142+ <meta name="theme-color" content="#000000">
143+ <title>React App</title>
144+ <link rel="manifest" href="./manifest.json" />
145+ <link rel="stylesheet" type="text/css" href="${ styleUri } ">
146+ <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src vscode-resource: https:; script-src 'nonce-${ n1 } ' 'nonce-${ n2 } ' 'nonce-${ n3 } '; style-src vscode-resource: 'unsafe-inline' http: https: data:;">
147+ <base href="${ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) . with ( {
148+ scheme :'vscode-resource' ,
149+ } ) } /">
150+ <style></style>
151+ </head>
152+
153+ <body>
154+ <noscript>You need to enable JavaScript to run this app.</noscript>
155+ <div id="root">Loading...</div>
156+ <script nonce=${ n1 } src="./webpackBuild.js"></script>
157+ <script nonce=${ n2 } src="${ chunkUri } "></script>
158+ <script nonce="${ n3 } " src="${ scriptUri } "></script>
159+ </body>
153160 </html>`
154- }
161+ }
155162}
156163
157164export default ReactWebView