1
- import PropTypes from 'prop-types' ;
2
- import React from 'react' ;
1
+ import React , { useRef } from 'react' ;
2
+
3
+ import { bindActionCreators } from 'redux' ;
4
+
5
+ import { useSelector , useDispatch } from 'react-redux' ;
3
6
import classNames from 'classnames' ;
4
7
import { Console as ConsoleFeed } from 'console-feed' ;
5
8
import {
@@ -22,132 +25,120 @@ import infoContrastUrl from '../../../images/console-info-contrast.svg?byUrl';
22
25
import UpArrowIcon from '../../../images/up-arrow.svg' ;
23
26
import DownArrowIcon from '../../../images/down-arrow.svg' ;
24
27
25
- class Console extends React . Component {
26
- componentDidUpdate ( prevProps ) {
27
- this . consoleMessages . scrollTop = this . consoleMessages . scrollHeight ;
28
- if ( this . props . theme !== prevProps . theme ) {
29
- this . props . clearConsole ( ) ;
30
- this . props . dispatchConsoleEvent ( this . props . consoleEvents ) ;
31
- }
28
+ import * as IDEActions from '../../IDE/actions/ide' ;
29
+ import * as ConsoleActions from '../../IDE/actions/console' ;
30
+ import { useDidUpdate } from '../../../utils/custom-hooks' ;
32
31
33
- if ( this . props . fontSize !== prevProps . fontSize ) {
34
- this . props . clearConsole ( ) ;
35
- this . props . dispatchConsoleEvent ( this . props . consoleEvents ) ;
36
- }
32
+ const getConsoleFeedStyle = ( theme , times , fontSize ) => {
33
+ const style = { } ;
34
+ const CONSOLE_FEED_LIGHT_ICONS = {
35
+ LOG_WARN_ICON : `url(${ warnLightUrl } )` ,
36
+ LOG_ERROR_ICON : `url(${ errorLightUrl } )` ,
37
+ LOG_DEBUG_ICON : `url(${ debugLightUrl } )` ,
38
+ LOG_INFO_ICON : `url(${ infoLightUrl } )`
39
+ } ;
40
+ const CONSOLE_FEED_DARK_ICONS = {
41
+ LOG_WARN_ICON : `url(${ warnDarkUrl } )` ,
42
+ LOG_ERROR_ICON : `url(${ errorDarkUrl } )` ,
43
+ LOG_DEBUG_ICON : `url(${ debugDarkUrl } )` ,
44
+ LOG_INFO_ICON : `url(${ infoDarkUrl } )`
45
+ } ;
46
+ const CONSOLE_FEED_CONTRAST_ICONS = {
47
+ LOG_WARN_ICON : `url(${ warnContrastUrl } )` ,
48
+ LOG_ERROR_ICON : `url(${ errorContrastUrl } )` ,
49
+ LOG_DEBUG_ICON : `url(${ debugContrastUrl } )` ,
50
+ LOG_INFO_ICON : `url(${ infoContrastUrl } )`
51
+ } ;
52
+ const CONSOLE_FEED_SIZES = {
53
+ TREENODE_LINE_HEIGHT : 1.2 ,
54
+ BASE_FONT_SIZE : fontSize ,
55
+ ARROW_FONT_SIZE : fontSize ,
56
+ LOG_ICON_WIDTH : fontSize ,
57
+ LOG_ICON_HEIGHT : 1.45 * fontSize ,
58
+ } ;
59
+
60
+ if ( times > 1 ) {
61
+ Object . assign ( style , CONSOLE_FEED_WITHOUT_ICONS ) ;
62
+ }
63
+ switch ( theme ) {
64
+ case 'light' :
65
+ return Object . assign ( CONSOLE_FEED_LIGHT_STYLES , CONSOLE_FEED_LIGHT_ICONS , CONSOLE_FEED_SIZES , style ) ;
66
+ case 'dark' :
67
+ return Object . assign ( CONSOLE_FEED_DARK_STYLES , CONSOLE_FEED_DARK_ICONS , CONSOLE_FEED_SIZES , style ) ;
68
+ case 'contrast' :
69
+ return Object . assign ( CONSOLE_FEED_CONTRAST_STYLES , CONSOLE_FEED_CONTRAST_ICONS , CONSOLE_FEED_SIZES , style ) ;
70
+ default :
71
+ return '' ;
37
72
}
73
+ } ;
38
74
39
- getConsoleFeedStyle ( theme , times ) {
40
- const style = { } ;
41
- const CONSOLE_FEED_LIGHT_ICONS = {
42
- LOG_WARN_ICON : `url(${ warnLightUrl } )` ,
43
- LOG_ERROR_ICON : `url(${ errorLightUrl } )` ,
44
- LOG_DEBUG_ICON : `url(${ debugLightUrl } )` ,
45
- LOG_INFO_ICON : `url(${ infoLightUrl } )`
46
- } ;
47
- const CONSOLE_FEED_DARK_ICONS = {
48
- LOG_WARN_ICON : `url(${ warnDarkUrl } )` ,
49
- LOG_ERROR_ICON : `url(${ errorDarkUrl } )` ,
50
- LOG_DEBUG_ICON : `url(${ debugDarkUrl } )` ,
51
- LOG_INFO_ICON : `url(${ infoDarkUrl } )`
52
- } ;
53
- const CONSOLE_FEED_CONTRAST_ICONS = {
54
- LOG_WARN_ICON : `url(${ warnContrastUrl } )` ,
55
- LOG_ERROR_ICON : `url(${ errorContrastUrl } )` ,
56
- LOG_DEBUG_ICON : `url(${ debugContrastUrl } )` ,
57
- LOG_INFO_ICON : `url(${ infoContrastUrl } )`
58
- } ;
59
- const CONSOLE_FEED_SIZES = {
60
- TREENODE_LINE_HEIGHT : 1.2 ,
61
- BASE_FONT_SIZE : this . props . fontSize ,
62
- ARROW_FONT_SIZE : this . props . fontSize ,
63
- LOG_ICON_WIDTH : this . props . fontSize ,
64
- LOG_ICON_HEIGHT : 1.45 * this . props . fontSize ,
65
- } ;
75
+ const Console = ( ) => {
76
+ const consoleEvents = useSelector ( state => state . console ) ;
77
+ const isExpanded = useSelector ( state => state . ide . consoleIsExpanded ) ;
78
+ const { theme, fontSize } = useSelector ( state => state . preferences ) ;
66
79
67
- if ( times > 1 ) {
68
- Object . assign ( style , CONSOLE_FEED_WITHOUT_ICONS ) ;
69
- }
70
- switch ( theme ) {
71
- case 'light' :
72
- return Object . assign ( CONSOLE_FEED_LIGHT_STYLES , CONSOLE_FEED_LIGHT_ICONS , CONSOLE_FEED_SIZES , style ) ;
73
- case 'dark' :
74
- return Object . assign ( CONSOLE_FEED_DARK_STYLES , CONSOLE_FEED_DARK_ICONS , CONSOLE_FEED_SIZES , style ) ;
75
- case 'contrast' :
76
- return Object . assign ( CONSOLE_FEED_CONTRAST_STYLES , CONSOLE_FEED_CONTRAST_ICONS , CONSOLE_FEED_SIZES , style ) ;
77
- default :
78
- return '' ;
79
- }
80
- }
80
+ const {
81
+ collapseConsole, expandConsole, clearConsole, dispatchConsoleEvent
82
+ } = bindActionCreators ( { ...IDEActions , ...ConsoleActions } , useDispatch ( ) ) ;
81
83
82
- render ( ) {
83
- const consoleClass = classNames ( {
84
- 'preview-console' : true ,
85
- 'preview-console--collapsed' : ! this . props . isExpanded
86
- } ) ;
84
+ useDidUpdate ( ( ) => {
85
+ clearConsole ( ) ;
86
+ dispatchConsoleEvent ( consoleEvents ) ;
87
+ } , [ theme , fontSize ] ) ;
87
88
88
- return (
89
- < section className = { consoleClass } >
90
- < header className = "preview-console__header" >
91
- < h2 className = "preview-console__header-title" > Console</ h2 >
92
- < div className = "preview-console__header-buttons" >
93
- < button className = "preview-console__clear" onClick = { this . props . clearConsole } aria-label = "Clear console" >
94
- Clear
95
- </ button >
96
- < button
97
- className = "preview-console__collapse"
98
- onClick = { this . props . collapseConsole }
99
- aria-label = "Close console"
100
- >
101
- < DownArrowIcon focusable = "false" aria-hidden = "true" />
102
- </ button >
103
- < button className = "preview-console__expand" onClick = { this . props . expandConsole } aria-label = "Open console" >
104
- < UpArrowIcon focusable = "false" aria-hidden = "true" />
105
- </ button >
106
- </ div >
107
- </ header >
108
- < div ref = { ( element ) => { this . consoleMessages = element ; } } className = "preview-console__messages" >
109
- { this . props . consoleEvents . map ( ( consoleEvent ) => {
110
- const { method, times } = consoleEvent ;
111
- const { theme } = this . props ;
112
- return (
113
- < div key = { consoleEvent . id } className = { `preview-console__message preview-console__message--${ method } ` } >
114
- { times > 1 &&
115
- < div
116
- className = "preview-console__logged-times"
117
- style = { { fontSize : this . props . fontSize , borderRadius : this . props . fontSize / 2 } }
118
- >
119
- { times }
120
- </ div >
121
- }
122
- < ConsoleFeed
123
- styles = { this . getConsoleFeedStyle ( theme , times ) }
124
- logs = { [ consoleEvent ] }
125
- />
126
- </ div >
127
- ) ;
128
- } ) }
129
- </ div >
130
- </ section >
131
- ) ;
132
- }
133
- }
89
+ const cm = useRef ( { } ) ;
134
90
135
- Console . propTypes = {
136
- consoleEvents : PropTypes . arrayOf ( PropTypes . shape ( {
137
- method : PropTypes . string . isRequired ,
138
- args : PropTypes . arrayOf ( PropTypes . string )
139
- } ) ) ,
140
- isExpanded : PropTypes . bool . isRequired ,
141
- collapseConsole : PropTypes . func . isRequired ,
142
- expandConsole : PropTypes . func . isRequired ,
143
- clearConsole : PropTypes . func . isRequired ,
144
- dispatchConsoleEvent : PropTypes . func . isRequired ,
145
- theme : PropTypes . string . isRequired ,
146
- fontSize : PropTypes . number . isRequired
147
- } ;
91
+ useDidUpdate ( ( ) => { cm . current . scrollTop = cm . current . scrollHeight ; } ) ;
92
+
93
+ const consoleClass = classNames ( {
94
+ 'preview-console' : true ,
95
+ 'preview-console--collapsed' : ! isExpanded
96
+ } ) ;
148
97
149
- Console . defaultProps = {
150
- consoleEvents : [ ]
98
+ return (
99
+ < section className = { consoleClass } >
100
+ < header className = "preview-console__header" >
101
+ < h2 className = "preview-console__header-title" > Console</ h2 >
102
+ < div className = "preview-console__header-buttons" >
103
+ < button className = "preview-console__clear" onClick = { clearConsole } aria-label = "Clear console" >
104
+ Clear
105
+ </ button >
106
+ < button
107
+ className = "preview-console__collapse"
108
+ onClick = { collapseConsole }
109
+ aria-label = "Close console"
110
+ >
111
+ < DownArrowIcon focusable = "false" aria-hidden = "true" />
112
+ </ button >
113
+ < button className = "preview-console__expand" onClick = { expandConsole } aria-label = "Open console" >
114
+ < UpArrowIcon focusable = "false" aria-hidden = "true" />
115
+ </ button >
116
+ </ div >
117
+ </ header >
118
+ < div ref = { cm } className = "preview-console__messages" >
119
+ { consoleEvents . map ( ( consoleEvent ) => {
120
+ const { method, times } = consoleEvent ;
121
+ return (
122
+ < div key = { consoleEvent . id } className = { `preview-console__message preview-console__message--${ method } ` } >
123
+ { times > 1 &&
124
+ < div
125
+ className = "preview-console__logged-times"
126
+ style = { { fontSize, borderRadius : fontSize / 2 } }
127
+ >
128
+ { times }
129
+ </ div >
130
+ }
131
+ < ConsoleFeed
132
+ styles = { getConsoleFeedStyle ( theme , times , fontSize ) }
133
+ logs = { [ consoleEvent ] }
134
+ />
135
+ </ div >
136
+ ) ;
137
+ } ) }
138
+ </ div >
139
+ </ section >
140
+ ) ;
151
141
} ;
152
142
143
+
153
144
export default Console ;
0 commit comments