Skip to content

Commit 13ace83

Browse files
committed
Move the file selector out of the editor itself; closes pterodactyl#2147
1 parent 540cc82 commit 13ace83

File tree

4 files changed

+36
-44
lines changed

4 files changed

+36
-44
lines changed

resources/scripts/components/elements/AceEditor.tsx

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import React, { useCallback, useEffect, useState } from 'react';
22
import ace, { Editor } from 'brace';
33
import styled from 'styled-components/macro';
44
import tw from 'twin.macro';
5-
import Select from '@/components/elements/Select';
6-
// @ts-ignore
75
import modes from '@/modes';
86

97
// @ts-ignore
@@ -21,42 +19,38 @@ const EditorContainer = styled.div`
2119
`;
2220

2321
Object.keys(modes).forEach(mode => require(`brace/mode/${mode}`));
22+
const modelist = ace.acequire('ace/ext/modelist');
2423

2524
export interface Props {
2625
style?: React.CSSProperties;
2726
initialContent?: string;
28-
initialModePath?: string;
27+
mode: string;
28+
filename?: string;
29+
onModeChanged: (mode: string) => void;
2930
fetchContent: (callback: () => Promise<string>) => void;
3031
onContentSaved: (content: string) => void;
3132
}
3233

33-
export default ({ style, initialContent, initialModePath, fetchContent, onContentSaved }: Props) => {
34-
const [ mode, setMode ] = useState('ace/mode/plain_text');
35-
34+
export default ({ style, initialContent, filename, mode, fetchContent, onContentSaved, onModeChanged }: Props) => {
3635
const [ editor, setEditor ] = useState<Editor>();
3736
const ref = useCallback(node => {
38-
if (node) {
39-
setEditor(ace.edit('editor'));
40-
}
37+
if (node) setEditor(ace.edit('editor'));
4138
}, []);
4239

4340
useEffect(() => {
44-
editor && editor.session.setMode(mode);
41+
if (modelist && filename) {
42+
onModeChanged(modelist.getModeForPath(filename).mode.replace(/^ace\/mode\//, ''));
43+
}
44+
}, [ filename ]);
45+
46+
useEffect(() => {
47+
editor && editor.session.setMode(`ace/mode/${mode}`);
4548
}, [ editor, mode ]);
4649

4750
useEffect(() => {
4851
editor && editor.session.setValue(initialContent || '');
4952
}, [ editor, initialContent ]);
5053

51-
useEffect(() => {
52-
if (initialModePath) {
53-
const modelist = ace.acequire('ace/ext/modelist');
54-
if (modelist) {
55-
setMode(modelist.getModeForPath(initialModePath).mode);
56-
}
57-
}
58-
}, [ initialModePath ]);
59-
6054
useEffect(() => {
6155
if (!editor) {
6256
fetchContent(() => Promise.reject(new Error('no editor session has been configured')));
@@ -85,20 +79,6 @@ export default ({ style, initialContent, initialModePath, fetchContent, onConten
8579
return (
8680
<EditorContainer style={style}>
8781
<div id={'editor'} ref={ref}/>
88-
<div css={tw`absolute right-0 bottom-0 z-50`}>
89-
<div css={tw`m-3 rounded bg-neutral-900 border border-black`}>
90-
<Select
91-
value={mode.split('/').pop()}
92-
onChange={e => setMode(`ace/mode/${e.currentTarget.value}`)}
93-
>
94-
{
95-
Object.keys(modes).map(key => (
96-
<option key={key} value={key}>{(modes as { [k: string]: string })[key]}</option>
97-
))
98-
}
99-
</Select>
100-
</div>
101-
</div>
10282
</EditorContainer>
10383
);
10484
};

resources/scripts/components/server/files/FileEditContainer.tsx

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
import React, { lazy, useEffect, useState } from 'react';
2-
import { ServerContext } from '@/state/server';
32
import getFileContents from '@/api/server/files/getFileContents';
4-
import { Actions, useStoreActions } from 'easy-peasy';
5-
import { ApplicationStore } from '@/state';
63
import { httpErrorToHuman } from '@/api/http';
74
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
85
import saveFileContents from '@/api/server/files/saveFileContents';
@@ -15,6 +12,10 @@ import PageContentBlock from '@/components/elements/PageContentBlock';
1512
import ServerError from '@/components/screens/ServerError';
1613
import tw from 'twin.macro';
1714
import Button from '@/components/elements/Button';
15+
import Select from '@/components/elements/Select';
16+
import modes from '@/modes';
17+
import useServer from '@/plugins/useServer';
18+
import useFlash from '@/plugins/useFlash';
1819

1920
const LazyAceEditor = lazy(() => import(/* webpackChunkName: "editor" */'@/components/elements/AceEditor'));
2021

@@ -24,12 +25,13 @@ export default () => {
2425
const [ loading, setLoading ] = useState(action === 'edit');
2526
const [ content, setContent ] = useState('');
2627
const [ modalVisible, setModalVisible ] = useState(false);
28+
const [ mode, setMode ] = useState('plain_text');
2729

2830
const history = useHistory();
2931
const { hash } = useLocation();
3032

31-
const { id, uuid } = ServerContext.useStoreState(state => state.server.data!);
32-
const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
33+
const { id, uuid } = useServer();
34+
const { addError, clearFlashes } = useFlash();
3335

3436
let fetchFileContent: null | (() => Promise<string>) = null;
3537

@@ -75,10 +77,7 @@ export default () => {
7577

7678
if (error) {
7779
return (
78-
<ServerError
79-
message={error}
80-
onBack={() => history.goBack()}
81-
/>
80+
<ServerError message={error} onBack={() => history.goBack()}/>
8281
);
8382
}
8483

@@ -109,15 +108,24 @@ export default () => {
109108
<div css={tw`relative`}>
110109
<SpinnerOverlay visible={loading}/>
111110
<LazyAceEditor
112-
initialModePath={hash.replace(/^#/, '') || 'plain_text'}
111+
mode={mode}
112+
filename={hash.replace(/^#/, '')}
113+
onModeChanged={setMode}
113114
initialContent={content}
114115
fetchContent={value => {
115116
fetchFileContent = value;
116117
}}
117-
onContentSaved={() => save()}
118+
onContentSaved={save}
118119
/>
119120
</div>
120121
<div css={tw`flex justify-end mt-4`}>
122+
<div css={tw`rounded bg-neutral-900 mr-4`}>
123+
<Select value={mode} onChange={e => setMode(e.currentTarget.value)}>
124+
{Object.keys(modes).map(key => (
125+
<option key={key} value={key}>{modes[key]}</option>
126+
))}
127+
</Select>
128+
</div>
121129
{action === 'edit' ?
122130
<Can action={'file.update'}>
123131
<Button onClick={() => save()}>

resources/scripts/modes.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
declare const modes: Record<string, string>;
2+
3+
export default modes;

resources/scripts/modes.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// This file must be plain Javascript since we're using it within Webpack.
12
module.exports = {
23
assembly_x86: 'Assembly (x86)',
34
c_cpp: 'C++',

0 commit comments

Comments
 (0)