Skip to content

Commit 16e6f3f

Browse files
committed
Attempting to solve a weird console loading issue by making into class component; doesn't fix but like the class better for this.
Loading the console, switching to file manager, and then switching back is needed to load the data the first time. After that every 2nd load of the console will load the data (and even send the data to the websocket as the daemon is reporting.)
1 parent 6b42296 commit 16e6f3f

File tree

4 files changed

+123
-63
lines changed

4 files changed

+123
-63
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
"react": "^16.8.6",
2020
"react-dom": "^16.8.6",
2121
"react-hot-loader": "^4.9.0",
22+
"react-redux": "^7.1.0",
2223
"react-router-dom": "^5.0.1",
2324
"react-transition-group": "^4.1.0",
2425
"socket.io-client": "^2.2.0",
@@ -42,6 +43,7 @@
4243
"@types/query-string": "^6.3.0",
4344
"@types/react": "^16.8.19",
4445
"@types/react-dom": "^16.8.4",
46+
"@types/react-redux": "^7.1.1",
4547
"@types/react-router-dom": "^4.3.3",
4648
"@types/react-transition-group": "^2.9.2",
4749
"@types/webpack-env": "^1.13.6",

resources/scripts/components/App.tsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { store } from '@/state';
66
import DashboardRouter from '@/routers/DashboardRouter';
77
import ServerRouter from '@/routers/ServerRouter';
88
import AuthenticationRouter from '@/routers/AuthenticationRouter';
9+
import { Provider } from 'react-redux';
910

1011
interface WindowWithUser extends Window {
1112
PterodactylUser?: {
@@ -37,17 +38,19 @@ const App = () => {
3738

3839
return (
3940
<StoreProvider store={store}>
40-
<Router basename={'/'}>
41-
<div className={'mx-auto w-auto'}>
42-
<BrowserRouter basename={'/'}>
43-
<Switch>
44-
<Route path="/server/:id" component={ServerRouter}/>
45-
<Route path="/auth" component={AuthenticationRouter}/>
46-
<Route path="/" component={DashboardRouter}/>
47-
</Switch>
48-
</BrowserRouter>
49-
</div>
50-
</Router>
41+
<Provider store={store}>
42+
<Router basename={'/'}>
43+
<div className={'mx-auto w-auto'}>
44+
<BrowserRouter basename={'/'}>
45+
<Switch>
46+
<Route path="/server/:id" component={ServerRouter}/>
47+
<Route path="/auth" component={AuthenticationRouter}/>
48+
<Route path="/" component={DashboardRouter}/>
49+
</Switch>
50+
</BrowserRouter>
51+
</div>
52+
</Router>
53+
</Provider>
5154
</StoreProvider>
5255
);
5356
};
Lines changed: 75 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import React, { createRef, useEffect, useRef } from 'react';
1+
import React, { createRef } from 'react';
22
import { Terminal } from 'xterm';
33
import * as TerminalFit from 'xterm/lib/addons/fit/fit';
44
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
5-
import { State, useStoreState } from 'easy-peasy';
65
import { ApplicationState } from '@/state/types';
6+
import { connect } from 'react-redux';
7+
import { Websocket } from '@/plugins/Websocket';
78

89
const theme = {
910
background: 'transparent',
@@ -26,67 +27,94 @@ const theme = {
2627
brightWhite: '#ffffff',
2728
};
2829

29-
export default () => {
30-
const { instance, connected } = useStoreState((state: State<ApplicationState>) => state.server.socket);
30+
interface Props {
31+
connected: boolean;
32+
instance: Websocket | null;
33+
}
3134

32-
const ref = createRef<HTMLDivElement>();
33-
const terminal = useRef(new Terminal({
35+
class Console extends React.PureComponent<Readonly<Props>> {
36+
ref = createRef<HTMLDivElement>();
37+
terminal = new Terminal({
3438
disableStdin: true,
3539
cursorStyle: 'underline',
3640
allowTransparency: true,
3741
fontSize: 12,
3842
fontFamily: 'Menlo, Monaco, Consolas, monospace',
3943
rows: 30,
4044
theme: theme,
41-
}));
42-
43-
const handleServerLog = (lines: string[]) => lines.forEach(data => {
44-
return data.split(/\n/g).forEach(line => terminal.current.writeln(line + '\u001b[0m'));
4545
});
4646

47-
const handleConsoleOutput = (line: string) => terminal.current.writeln(line.replace(/(?:\r\n|\r|\n)$/im, '') + '\u001b[0m');
47+
componentDidMount () {
48+
if (this.ref.current) {
49+
this.terminal.open(this.ref.current);
50+
this.terminal.clear();
4851

49-
useEffect(() => {
50-
ref.current && terminal.current.open(ref.current);
52+
// @see https://github.com/xtermjs/xterm.js/issues/2265
53+
// @see https://github.com/xtermjs/xterm.js/issues/2230
54+
TerminalFit.fit(this.terminal);
55+
}
5156

52-
// @see https://github.com/xtermjs/xterm.js/issues/2265
53-
// @see https://github.com/xtermjs/xterm.js/issues/2230
54-
TerminalFit.fit(terminal.current);
55-
}, []);
57+
if (this.props.connected && this.props.instance) {
58+
this.listenForEvents();
59+
}
60+
}
5661

57-
useEffect(() => {
58-
if (connected && instance) {
59-
instance.addListener('server log', handleServerLog);
60-
instance.addListener('console output', handleConsoleOutput);
61-
instance.send('send logs');
62+
componentDidUpdate (prevProps: Readonly<Readonly<Props>>) {
63+
if (!prevProps.connected && this.props.connected) {
64+
this.listenForEvents();
6265
}
63-
}, [connected]);
66+
}
6467

65-
useEffect(() => () => {
66-
if (instance) {
67-
instance.removeListener('server log', handleServerLog);
68-
instance.removeListener('console output', handleConsoleOutput);
68+
componentWillUnmount () {
69+
if (this.props.instance) {
70+
this.props.instance.removeListener('server log', this.handleServerLog);
71+
this.props.instance.removeListener('server log', this.handleConsoleOutput);
6972
}
70-
}, []);
73+
}
7174

72-
return (
73-
<div className={'text-xs font-mono relative'}>
74-
<SpinnerOverlay visible={!connected} large={true}/>
75-
<div
76-
className={'rounded-t p-2 bg-black overflow-scroll w-full'}
77-
style={{
78-
minHeight: '16rem',
79-
maxHeight: '64rem',
80-
}}
81-
>
82-
<div id={'terminal'} ref={ref}/>
83-
</div>
84-
<div className={'rounded-b bg-neutral-900 text-neutral-100 flex'}>
85-
<div className={'flex-no-shrink p-2 font-bold'}>$</div>
86-
<div className={'w-full'}>
87-
<input type={'text'} className={'bg-transparent text-neutral-100 p-2 pl-0 w-full'}/>
75+
listenForEvents () {
76+
const instance = this.props.instance!;
77+
78+
instance.addListener('server log', this.handleServerLog);
79+
instance.addListener('console output', this.handleConsoleOutput);
80+
instance.send('send logs');
81+
}
82+
83+
handleServerLog = (lines: string[]) => lines.forEach(data => {
84+
return data.split(/\n/g).forEach(line => this.terminal.writeln(line + '\u001b[0m'));
85+
});
86+
87+
handleConsoleOutput = (line: string) => this.terminal.writeln(
88+
line.replace(/(?:\r\n|\r|\n)$/im, '') + '\u001b[0m'
89+
);
90+
91+
render () {
92+
return (
93+
<div className={'text-xs font-mono relative'}>
94+
<SpinnerOverlay visible={!this.props.connected} large={true}/>
95+
<div
96+
className={'rounded-t p-2 bg-black overflow-scroll w-full'}
97+
style={{
98+
minHeight: '16rem',
99+
maxHeight: '64rem',
100+
}}
101+
>
102+
<div id={'terminal'} ref={this.ref}/>
103+
</div>
104+
<div className={'rounded-b bg-neutral-900 text-neutral-100 flex'}>
105+
<div className={'flex-no-shrink p-2 font-bold'}>$</div>
106+
<div className={'w-full'}>
107+
<input type={'text'} className={'bg-transparent text-neutral-100 p-2 pl-0 w-full'}/>
108+
</div>
88109
</div>
89110
</div>
90-
</div>
91-
);
92-
};
111+
);
112+
}
113+
}
114+
115+
export default connect(
116+
(state: ApplicationState) => ({
117+
connected: state.server.socket.connected,
118+
instance: state.server.socket.instance,
119+
}),
120+
)(Console);

yarn.lock

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@
605605
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
606606
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
607607

608-
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0":
608+
"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.4.5":
609609
version "7.4.5"
610610
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
611611
dependencies:
@@ -778,6 +778,13 @@
778778
version "4.7.2"
779779
resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.2.tgz#0e670ea254d559241b6eeb3894f8754991e73220"
780780

781+
"@types/hoist-non-react-statics@^3.3.0":
782+
version "3.3.1"
783+
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
784+
dependencies:
785+
"@types/react" "*"
786+
hoist-non-react-statics "^3.3.0"
787+
781788
"@types/lodash@^4.14.119":
782789
version "4.14.119"
783790
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.119.tgz#be847e5f4bc3e35e46d041c394ead8b603ad8b39"
@@ -798,6 +805,15 @@
798805
dependencies:
799806
"@types/react" "*"
800807

808+
"@types/react-redux@^7.1.1":
809+
version "7.1.1"
810+
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.1.tgz#eb01e89cf71cad77df9f442b819d5db692b997cb"
811+
dependencies:
812+
"@types/hoist-non-react-statics" "^3.3.0"
813+
"@types/react" "*"
814+
hoist-non-react-statics "^3.3.0"
815+
redux "^4.0.0"
816+
801817
"@types/react-router-dom@^4.3.3":
802818
version "4.3.3"
803819
resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-4.3.3.tgz#7837e3e9fefbc84a8f6c8a51dca004f4e83e94e3"
@@ -3966,7 +3982,7 @@ interpret@^1.1.0:
39663982
version "1.1.0"
39673983
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614"
39683984

3969-
invariant@^2.2.0, invariant@^2.2.2:
3985+
invariant@^2.2.0, invariant@^2.2.2, invariant@^2.2.4:
39703986
version "2.2.4"
39713987
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
39723988
dependencies:
@@ -6094,7 +6110,7 @@ promise@^7.1.1:
60946110
dependencies:
60956111
asap "~2.0.3"
60966112

6097-
prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2:
6113+
prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
60986114
version "15.7.2"
60996115
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
61006116
dependencies:
@@ -6272,14 +6288,25 @@ react-hot-loader@^4.9.0:
62726288
shallowequal "^1.0.2"
62736289
source-map "^0.7.3"
62746290

6275-
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
6291+
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6:
62766292
version "16.8.6"
62776293
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
62786294

62796295
react-lifecycles-compat@^3.0.4:
62806296
version "3.0.4"
62816297
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
62826298

6299+
react-redux@^7.1.0:
6300+
version "7.1.0"
6301+
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.1.0.tgz#72af7cf490a74acdc516ea9c1dd80e25af9ea0b2"
6302+
dependencies:
6303+
"@babel/runtime" "^7.4.5"
6304+
hoist-non-react-statics "^3.3.0"
6305+
invariant "^2.2.4"
6306+
loose-envify "^1.4.0"
6307+
prop-types "^15.7.2"
6308+
react-is "^16.8.6"
6309+
62836310
react-router-dom@^5.0.1:
62846311
version "5.0.1"
62856312
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be"
@@ -6408,7 +6435,7 @@ redux-thunk@^2.3.0:
64086435
version "2.3.0"
64096436
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
64106437

6411-
redux@^4.0.1:
6438+
redux@^4.0.0, redux@^4.0.1:
64126439
version "4.0.1"
64136440
resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.1.tgz#436cae6cc40fbe4727689d7c8fae44808f1bfef5"
64146441
dependencies:

0 commit comments

Comments
 (0)