5
5
*/
6
6
7
7
import EventEmitter from 'events' ;
8
- import React from 'react' ;
8
+ import { useEffect , useRef } from 'react' ;
9
9
import { Terminal , ITerminalOptions , ITheme } from 'xterm' ;
10
10
import { FitAddon } from 'xterm-addon-fit'
11
11
import 'xterm/css/xterm.css' ;
12
- import { DisposableCollection } from '@gitpod/gitpod-protocol' ;
13
12
14
13
export interface WorkspaceLogsProps {
15
14
logsEmitter : EventEmitter ;
16
15
errorMessage ?: string ;
17
16
classes ?: string ;
18
17
}
19
18
20
- export interface WorkspaceLogsState {
21
- }
22
-
23
- export default class WorkspaceLogs extends React . Component < WorkspaceLogsProps , WorkspaceLogsState > {
24
- protected xTermParentRef : React . RefObject < HTMLDivElement > ;
25
- protected terminal : Terminal | undefined ;
26
- protected fitAddon : FitAddon | undefined ;
27
-
28
- constructor ( props : WorkspaceLogsProps ) {
29
- super ( props ) ;
30
- this . xTermParentRef = React . createRef ( ) ;
31
- }
19
+ export default function WorkspaceLogs ( props : WorkspaceLogsProps ) {
20
+ const xTermParentRef = useRef < HTMLDivElement > ( null ) ;
21
+ const terminalRef = useRef < Terminal > ( ) ;
22
+ const fitAddon = new FitAddon ( ) ;
32
23
33
- private readonly toDispose = new DisposableCollection ( ) ;
34
- componentDidMount ( ) {
35
- const element = this . xTermParentRef . current ;
36
- if ( element === null ) {
24
+ useEffect ( ( ) => {
25
+ if ( ! xTermParentRef . current ) {
37
26
return ;
38
27
}
39
28
const theme : ITheme = { } ;
@@ -44,46 +33,42 @@ export default class WorkspaceLogs extends React.Component<WorkspaceLogsProps, W
44
33
theme,
45
34
scrollback : 9999999 ,
46
35
} ;
47
- this . terminal = new Terminal ( options ) ;
48
- this . fitAddon = new FitAddon ( ) ;
49
- this . terminal . loadAddon ( this . fitAddon ) ;
50
- this . terminal . open ( element ) ;
51
- this . props . logsEmitter . on ( 'logs' , logs => {
52
- if ( this . fitAddon && this . terminal && logs ) {
53
- this . terminal . write ( logs ) ;
36
+ const terminal = new Terminal ( options ) ;
37
+ terminalRef . current = terminal ;
38
+ terminal . loadAddon ( fitAddon ) ;
39
+ terminal . open ( xTermParentRef . current ) ;
40
+ props . logsEmitter . on ( 'logs' , logs => {
41
+ if ( fitAddon && terminal && logs ) {
42
+ terminal . write ( logs ) ;
54
43
}
55
44
} ) ;
56
- this . toDispose . push ( this . terminal ) ;
57
- this . fitAddon . fit ( ) ;
45
+ fitAddon . fit ( ) ;
46
+ return function cleanUp ( ) {
47
+ terminal . dispose ( ) ;
48
+ }
49
+ } ) ;
58
50
51
+ useEffect ( ( ) => {
59
52
// Fit terminal on window resize (debounced)
60
53
let timeout : NodeJS . Timeout | undefined ;
61
54
const onWindowResize = ( ) => {
62
55
clearTimeout ( timeout ! ) ;
63
- timeout = setTimeout ( ( ) => this . fitAddon ! . fit ( ) , 20 ) ;
56
+ timeout = setTimeout ( ( ) => fitAddon ! . fit ( ) , 20 ) ;
64
57
} ;
65
58
window . addEventListener ( 'resize' , onWindowResize ) ;
66
- this . toDispose . push ( {
67
- dispose : ( ) => {
68
- clearTimeout ( timeout ! ) ;
69
- window . removeEventListener ( 'resize' , onWindowResize ) ;
70
- }
71
- } ) ;
72
- }
73
-
74
- componentDidUpdate ( ) {
75
- if ( this . terminal && this . props . errorMessage ) {
76
- this . terminal . write ( `\n\u001b[38;5;196m${ this . props . errorMessage } \u001b[0m` ) ;
59
+ return function cleanUp ( ) {
60
+ clearTimeout ( timeout ! ) ;
61
+ window . removeEventListener ( 'resize' , onWindowResize ) ;
77
62
}
78
- }
63
+ } ) ;
79
64
80
- componentWillUnmount ( ) {
81
- this . toDispose . dispose ( ) ;
82
- }
65
+ useEffect ( ( ) => {
66
+ if ( terminalRef . current && props . errorMessage ) {
67
+ terminalRef . current . write ( `\n\u001b[38;5;196m${ props . errorMessage } \u001b[0m` ) ;
68
+ }
69
+ } , [ terminalRef . current , props . errorMessage ] ) ;
83
70
84
- render ( ) {
85
- return < div className = { `mt-6 ${ this . props . classes || 'h-72 w-11/12 lg:w-3/5' } rounded-xl bg-black relative` } >
86
- < div className = "absolute top-0 left-0 bottom-0 right-0 m-6" ref = { this . xTermParentRef } > </ div >
87
- </ div > ;
88
- }
71
+ return < div className = { `mt-6 ${ props . classes || 'h-72 w-11/12 lg:w-3/5' } rounded-xl bg-black relative` } >
72
+ < div className = "absolute top-0 left-0 bottom-0 right-0 m-6" ref = { xTermParentRef } > </ div >
73
+ </ div > ;
89
74
}
0 commit comments