@@ -2,116 +2,118 @@ import * as vscode from 'vscode'
2
2
import * as CR from 'typings'
3
3
import * as path from 'path'
4
4
5
- import getNonce from './utils/nonce'
6
- import onReceive from './onReceive'
7
-
8
5
/**
9
6
* Manages React webview panels
10
7
*/
11
- class ReactPanel {
12
- /**
13
- * Track the currently panel. Only allow a single panel to exist at a time.
14
- */
15
- public static currentPanel : ReactPanel | undefined = undefined
8
+ class 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 . One )
16
20
17
- private readonly _panel : vscode . WebviewPanel
18
- private readonly _extensionPath : string
19
- private _disposables : vscode . Disposable [ ] = [ ]
21
+ // Set the webview's initial html content
22
+ this . panel . webview . html = this . getHtmlForWebview ( )
20
23
21
- public static async createOrShow ( extensionPath : string ) : Promise < void > {
22
- // const hasActiveEditor = vscode.window.activeTextEditor
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 )
23
27
24
- // if (!hasActiveEditor) {
25
- // throw new Error('Should have an open file on launch')
26
- // }
27
- const column = vscode . ViewColumn . One
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
+ console . log ( 'webview loaded' )
32
+ }
28
33
34
+ public async createOrShow ( column : number ) : Promise < void > {
29
35
// If we already have a panel, show it.
30
36
// Otherwise, create a new panel.
31
- if ( ReactPanel . currentPanel ) {
32
- console . log ( '--- HAS CURRENT PANEL --- ' )
33
- ReactPanel . currentPanel . _panel . reveal ( column )
37
+ if ( this . panel && this . panel . webview ) {
38
+ console . log ( 'reveal ' )
39
+ this . panel . reveal ( column )
34
40
} else {
35
- ReactPanel . currentPanel = new ReactPanel ( extensionPath , column )
41
+ console . log ( 'make new panel' )
42
+ this . panel = this . createWebviewPanel ( column )
43
+
36
44
}
37
45
}
38
46
39
- private constructor ( extensionPath : string , column : vscode . ViewColumn ) {
40
- this . _extensionPath = extensionPath
41
-
47
+ private createWebviewPanel ( column : number ) : vscode . WebviewPanel {
42
48
const viewType = 'CodeRoad'
43
49
const title = 'CodeRoad'
44
50
const config = {
45
51
// Enable javascript in the webview
46
52
enableScripts : true ,
47
-
48
53
// And restric the webview to only loading content from our extension's `media` directory.
49
- localResourceRoots : [ vscode . Uri . file ( path . join ( this . _extensionPath , 'build' ) ) ] ,
50
-
54
+ localResourceRoots : [ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) ] ,
51
55
// prevents destroying the window when it is in the background
52
56
retainContextWhenHidden : true ,
53
57
}
58
+ return vscode . window . createWebviewPanel ( viewType , title , column , config )
59
+ }
54
60
55
- // Create and show a new webview panel
56
- this . _panel = vscode . window . createWebviewPanel ( viewType , title , column , config )
57
-
58
- // Set the webview's initial html content
59
- this . _panel . webview . html = this . _getHtmlForWebview ( )
60
-
61
- // Listen for when the panel is disposed
62
- // This happens when the user closes the panel or when the panel is closed programatically
63
- this . _panel . onDidDispose ( ( ) => this . dispose ( ) , null , this . _disposables )
64
-
65
- // Handle messages from the webview
66
- this . _panel . webview . onDidReceiveMessage ( onReceive , null , this . _disposables )
61
+ private getNonce ( ) : string {
62
+ let text = ''
63
+ const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
64
+ for ( let i = 0 ; i < 32 ; i ++ ) {
65
+ text += possible . charAt ( Math . floor ( Math . random ( ) * possible . length ) )
66
+ }
67
+ return text
67
68
}
68
69
69
70
public async postMessage ( action : CR . Action ) : Promise < void > {
71
+ console . log ( 'webview postMessage' )
72
+ console . log ( action )
70
73
// Send a message to the webview webview.
71
74
// You can send any JSON serializable data.
72
- const success = await this . _panel . webview . postMessage ( action )
75
+ const success = await this . panel . webview . postMessage ( action )
73
76
if ( ! success ) {
74
77
throw new Error ( `Message post failure: ${ JSON . stringify ( action ) } ` )
75
78
}
79
+ console . log ( 'postMessage sent' )
76
80
}
77
81
78
82
public dispose ( ) : void {
79
- ReactPanel . currentPanel = undefined
80
-
81
83
// Clean up our resources
82
- this . _panel . dispose ( )
84
+ this . panel . dispose ( )
83
85
84
- while ( this . _disposables . length ) {
85
- const x = this . _disposables . pop ( )
86
+ while ( this . disposables . length ) {
87
+ const x = this . disposables . pop ( )
86
88
if ( x ) {
87
89
x . dispose ( )
88
90
}
89
91
}
90
92
}
91
93
92
- private _getHtmlForWebview ( ) : string {
94
+ private getHtmlForWebview ( ) : string {
93
95
94
96
// eslint-disable-next-line
95
- const manifest = require ( path . join ( this . _extensionPath , 'build' , 'asset-manifest.json' ) )
97
+ const manifest = require ( path . join ( this . extensionPath , 'build' , 'asset-manifest.json' ) )
96
98
const mainScript = manifest . files [ 'main.js' ]
97
99
// grab first chunk
98
100
const chunk = Object . keys ( manifest . files ) . filter ( f => f . match ( / ^ s t a t i c \/ j s \/ .+ \. j s $ / ) ) [ 0 ]
99
101
const chunkScript = manifest . files [ chunk ]
100
102
const mainStyle = manifest . files [ 'main.css' ]
101
103
102
- const scriptPathOnDisk = vscode . Uri . file ( path . join ( this . _extensionPath , 'build' , mainScript ) )
104
+ const scriptPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainScript ) )
103
105
const scriptUri = scriptPathOnDisk . with ( { scheme : 'vscode-resource' } )
104
- const chunkPathOnDisk = vscode . Uri . file ( path . join ( this . _extensionPath , 'build' , chunkScript ) )
106
+ const chunkPathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , chunkScript ) )
105
107
const chunkUri = chunkPathOnDisk . with ( { scheme : 'vscode-resource' } )
106
- const stylePathOnDisk = vscode . Uri . file ( path . join ( this . _extensionPath , 'build' , mainStyle ) )
108
+ const stylePathOnDisk = vscode . Uri . file ( path . join ( this . extensionPath , 'build' , mainStyle ) )
107
109
const styleUri = stylePathOnDisk . with ( { scheme : 'vscode-resource' } )
108
110
109
111
// Use a nonce to whitelist which scripts can be run
110
- const nonce = getNonce ( )
111
- const nonce2 = getNonce ( )
112
- const nonce3 = getNonce ( )
112
+ const nonce = this . getNonce ( )
113
+ const nonce2 = this . getNonce ( )
114
+ const nonce3 = this . getNonce ( )
113
115
114
- const output = `<!DOCTYPE html>
116
+ return `<!DOCTYPE html>
115
117
<html lang="en">
116
118
<head>
117
119
<meta charset="utf-8">
@@ -121,7 +123,7 @@ class ReactPanel {
121
123
<link rel="manifest" href="./manifest.json" />
122
124
<link rel="stylesheet" type="text/css" href="${ styleUri } ">
123
125
<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:;">
124
- <base href="https://github.com/%3Cspan%20class="pl-s1">${ vscode . Uri . file ( path . join ( this . _extensionPath , 'build' ) ) . with ( { scheme : 'vscode-resource' } ) } /">
126
+ <base href="https://github.com/%3Cspan%20class="pl-s1">${ vscode . Uri . file ( path . join ( this . extensionPath , 'build' ) ) . with ( { scheme : 'vscode-resource' } ) } /">
125
127
<style></style>
126
128
</head>
127
129
@@ -133,9 +135,7 @@ class ReactPanel {
133
135
<script nonce="${ nonce3 } " src="${ scriptUri } "></script>
134
136
</body>
135
137
</html>`
136
- console . log ( output )
137
- return output
138
138
}
139
139
}
140
140
141
- export default ReactPanel
141
+ export default ReactWebView
0 commit comments