procon_bypass_man-web 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ProconBypassMan
4
4
  module Web
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  /** @jsx jsx */
2
2
 
3
3
  import { jsx, css } from '@emotion/react'
4
- import React, { useState, useContext } from "react";
4
+ import React, { useState, useReducer, useContext } from "react";
5
5
  import { Button } from "../types/button";
6
6
  import { ButtonState } from "./../lib/button_state";
7
7
  import { ButtonsModal } from "./buttons_modal";
@@ -18,11 +18,11 @@ type ButtonMenuProp = {
18
18
  };
19
19
 
20
20
  const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuProp) => {
21
- const flipRadioName = `${layerKey}_button_menu_${name}`;
22
21
  const buttonState = new ButtonState(name, buttonValue.flip, buttonValue.remap);
23
22
 
24
23
  // for modal
25
- const [openModal, setOpenModal] = useState(false)
24
+ const [isOpenModal, toggleModal] = useReducer((m) => { return !m; }, false);
25
+
26
26
  const [modalCallbackOnSubmit, setModalCallbackOnSubmit] = useState(undefined as any)
27
27
  const [modalCloseCallback, setModalCloseCallback] = useState(undefined as any)
28
28
  const [modalTitle, setModalTitle] = useState("")
@@ -49,11 +49,11 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
49
49
  layersDispatch({ type: flipIfPressedSomeButtonsType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
50
50
  }
51
51
  const openIfPressedSomeButtonsModal = (e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>) => {
52
- setOpenModal(true)
52
+ toggleModal();
53
53
  setModalTitle("特定のキーを押したときだけ")
54
54
  setModalPrefillButtons(flipIfPressedSomeButtons);
55
55
  setModalCallbackOnSubmit(() => setFlipIfPressedSomeButtonsWithPersistence);
56
- setModalCloseCallback(() => setOpenModal);
56
+ setModalCloseCallback(() => toggleModal);
57
57
  }
58
58
 
59
59
  // 無視
@@ -62,11 +62,11 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
62
62
  layersDispatch({ type: ignoreButtonsInFlipingType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
63
63
  }
64
64
  const handleIgnoreButton = (e: React.ChangeEvent<HTMLInputElement>) => {
65
- setOpenModal(true)
65
+ toggleModal();
66
66
  setModalTitle("連打中は特定のボタンの入力を無視する")
67
67
  setModalPrefillButtons(buttonValue.flip?.force_neutral || [] as Array<Button>);
68
68
  setModalCallbackOnSubmit(() => setIgnoreButtonsOnFlipingWithPersistence);
69
- setModalCloseCallback(() => setOpenModal);
69
+ setModalCloseCallback(() => toggleModal);
70
70
  };
71
71
 
72
72
  // リマップ
@@ -74,11 +74,11 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
74
74
  layersDispatch({ type: remapType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
75
75
  }
76
76
  const handleRemapButton = (e: React.ChangeEvent<HTMLInputElement>) => {
77
- setOpenModal(true)
77
+ toggleModal();
78
78
  setModalTitle("リマップ")
79
79
  setModalPrefillButtons(buttonValue.remap?.to || []);
80
80
  setModalCallbackOnSubmit(() => setRemapButtonsWithPersistence);
81
- setModalCloseCallback(() => setOpenModal);
81
+ setModalCloseCallback(() => toggleModal);
82
82
  };
83
83
 
84
84
  return(
@@ -91,13 +91,13 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
91
91
  <input type="radio" onChange={openIfPressedSomeButtonsModal} onClick={openIfPressedSomeButtonsModal} checked={buttonState.isFlipIfPressedSomeButtons()}/>
92
92
  特定のキーを押したときだけ連打する{flipIfPressedSomeButtons.length > 0 && `(${flipIfPressedSomeButtons.join(", ")})`}
93
93
  </label>
94
- </fieldset>
95
94
 
96
- <fieldset><legend><strong>連打オプション</strong></legend>
97
- <label>
98
- <input type="checkbox" onChange={handleIgnoreButton} checked={forceNeutralButtons.length > 0} disabled={buttonState.isDisabledFlip()} />
99
- 連打中は特定のボタンの入力を無視する{forceNeutralButtons.length > 0 && `(${forceNeutralButtons.join(", ")})`}
100
- </label>
95
+ <fieldset><legend><strong>連打オプション</strong></legend>
96
+ <label>
97
+ <input type="checkbox" onChange={handleIgnoreButton} checked={forceNeutralButtons.length > 0} disabled={buttonState.isDisabledFlip()} />
98
+ 連打中は特定のボタンの入力を無視する{forceNeutralButtons.length > 0 && `(${forceNeutralButtons.join(", ")})`}
99
+ </label>
100
+ </fieldset>
101
101
  </fieldset>
102
102
 
103
103
  <fieldset><legend><strong>リマップ設定</strong></legend>
@@ -107,7 +107,7 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
107
107
  </label>
108
108
  </fieldset>
109
109
  <div css={css`position: relative;`}>
110
- {openModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={modalPrefillButtons} positionOnShown={"relative"} />}
110
+ {isOpenModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={modalPrefillButtons} positionOnShown={"relative"} />}
111
111
  </div>
112
112
  </>
113
113
  )
@@ -119,24 +119,24 @@ type Prop = {
119
119
  };
120
120
 
121
121
  export const ButtonSetting: React.FC<Prop> = ({ name, layerKey }) => {
122
- const settingContext = useContext(ButtonsSettingContext);
122
+ const { layersDispatch, layers } = useContext(ButtonsSettingContext);
123
123
  const handleToggle = () => {
124
124
  if(isOpenMenu()) { // 閉じる
125
- settingContext.layersDispatch({ type: closeMenuType, payload: { layerKey: layerKey, button: name }});
125
+ layersDispatch({ type: closeMenuType, payload: { layerKey: layerKey, button: name }});
126
126
  } else { // 開く
127
- settingContext.layersDispatch({ type: openMenuType, payload: { layerKey: layerKey, button: name }});
127
+ layersDispatch({ type: openMenuType, payload: { layerKey: layerKey, button: name }});
128
128
  }
129
129
  }
130
130
 
131
131
  const isOpenMenu = () => {
132
- return settingContext.layers[layerKey][name].open;
132
+ return layers[layerKey][name].open;
133
133
  }
134
- const buttonValue = settingContext.layers[layerKey][name] || {} as ButtonInLayer;
134
+ const buttonValue = layers[layerKey][name] || {} as ButtonInLayer;
135
135
 
136
136
  return (
137
137
  <>
138
138
  <label><input type="checkbox" checked={isOpenMenu()} onChange={handleToggle}/>{name}</label>
139
- {isOpenMenu() && <ButtonMenu name={name} layerKey={layerKey} buttonValue={buttonValue} layersDispatch={settingContext.layersDispatch} />}
139
+ {isOpenMenu() && <ButtonMenu name={name} layerKey={layerKey} buttonValue={buttonValue} layersDispatch={layersDispatch} />}
140
140
  </>
141
141
  );
142
142
  };
@@ -3,7 +3,7 @@
3
3
  import { jsx, css } from '@emotion/react'
4
4
  import React, { useState, useEffect, useContext } from "react";
5
5
  import { ButtonsSettingContext, } from "./../contexts/buttons_setting";
6
- import { Plugin, PluginBody, AvailablePlugins } from "../types/plugin";
6
+ import { Plugin, PluginBody, AvailablePlugins, MacroNameMap } from "../types/plugin";
7
7
  import { installMacroType, uninstallMacroType } from "../reducers/layer_reducer";
8
8
 
9
9
  const macroClassNamespaces = AvailablePlugins.map((v) => {
@@ -34,7 +34,7 @@ export const InstallableMacro = ({ classNamespace }: Props) => {
34
34
  }
35
35
  return(
36
36
  <>
37
- <input type="checkbox" onChange={handleClick} checked={isChecked(classNamespace)} /> {classNamespace}
37
+ <input type="checkbox" onChange={handleClick} checked={isChecked(classNamespace)} /> {MacroNameMap[classNamespace]}
38
38
  </>
39
39
  )
40
40
  }
@@ -3,7 +3,7 @@
3
3
  import { jsx, css } from '@emotion/react'
4
4
  import React, { useState, useEffect, useContext } from "react";
5
5
  import { ButtonsSettingContext, } from "./../contexts/buttons_setting";
6
- import { Plugin, PluginBody, AvailablePlugins } from "../types/plugin";
6
+ import { Plugin, PluginBody, AvailablePlugins, ModeNameMap } from "../types/plugin";
7
7
  import { installModeType, uninstallModeType } from "../reducers/layer_reducer";
8
8
 
9
9
  const modeClassNamespaces = AvailablePlugins.map((v) => {
@@ -17,27 +17,29 @@ const modeClassNamespaces = AvailablePlugins.map((v) => {
17
17
  }).flat().flat();
18
18
 
19
19
  type Props = {
20
- classNamespace: string;
20
+ modeKey: string;
21
21
  };
22
- export const InstallableMode = ({ classNamespace }: Props) => {
22
+ export const InstallableMode = ({ modeKey }: Props) => {
23
+ const modeName = ModeNameMap[modeKey];
23
24
  const { layers, layersDispatch } = useContext(ButtonsSettingContext);
24
25
  const isChecked = (name: string) => {
25
26
  return layers.installed_modes[name] || false;
26
27
  }
27
28
  const handleClick = (e: React.ChangeEvent<HTMLInputElement>) => {
28
- if(isChecked(classNamespace)) {
29
- layersDispatch({ type: uninstallModeType, payload: { installed_mode: classNamespace }});
29
+ if(isChecked(modeKey)) {
30
+ layersDispatch({ type: uninstallModeType, payload: { installed_mode: modeKey }});
30
31
  } else {
31
- layersDispatch({ type: installModeType, payload: { installed_mode: classNamespace }});
32
+ layersDispatch({ type: installModeType, payload: { installed_mode: modeKey }});
32
33
  }
33
34
  }
34
35
  return(
35
36
  <div>
36
- <input type="checkbox" onChange={handleClick} checked={isChecked(classNamespace)} />{classNamespace}
37
+ <input type="checkbox" onChange={handleClick} checked={isChecked(modeKey)} />{modeName}
37
38
  </div>
38
39
  )
39
40
  }
40
41
 
42
+ console.log("modeClassNamespaces: ", modeClassNamespaces)
41
43
  export const InstallableModes = () => {
42
44
  return(
43
45
  <>
@@ -46,7 +48,7 @@ export const InstallableModes = () => {
46
48
  return(
47
49
  <div key={i}>
48
50
  <label>
49
- <InstallableMode classNamespace={classNamespace} />
51
+ <InstallableMode modeKey={classNamespace} />
50
52
  </label>
51
53
  </div>
52
54
  );
@@ -1,7 +1,7 @@
1
1
  /** @jsx jsx */
2
2
 
3
3
  import { jsx, css } from '@emotion/react'
4
- import React, { useState, useContext } from "react";
4
+ import React, { useState, useReducer, useContext } from "react";
5
5
  import { ButtonsSettingContext } from "./../contexts/buttons_setting";
6
6
  import { LayerKey } from "../types/layer_key";
7
7
  import { Button } from "../types/button";
@@ -17,7 +17,7 @@ type MacroSettingProps = {
17
17
  const MacroSetting = ({ macro, layerKey }: MacroSettingProps) => {
18
18
  const { layersDispatch } = useContext(ButtonsSettingContext);
19
19
  // for modal
20
- const [openModal, setOpenModal] = useState(false)
20
+ const [isOpenModal, toggleModal] = useReducer((m) => { return !m; }, false);
21
21
  const [modalCallbackOnSubmit, setModalCallbackOnSubmit] = useState(undefined as any)
22
22
  const [modalCloseCallback, setModalCloseCallback] = useState(undefined as any)
23
23
  const [modalTitle, setModalTitle] = useState("")
@@ -28,11 +28,11 @@ const MacroSetting = ({ macro, layerKey }: MacroSettingProps) => {
28
28
  layersDispatch({ type: applyMacroType, payload: { layerKey: layerKey, macro: macro }});
29
29
  }
30
30
  const handleClick = (e: React.ChangeEvent<HTMLInputElement>) => {
31
- setOpenModal(true)
31
+ toggleModal();
32
32
  setModalTitle("発動キーの設定")
33
33
  setModalPrefillButtons(macro.if_pressed);
34
34
  setModalCallbackOnSubmit(() => setButtonsForModal);
35
- setModalCloseCallback(() => setOpenModal);
35
+ setModalCloseCallback(() => toggleModal);
36
36
  }
37
37
  const isEnable = macro.if_pressed.length > 0;
38
38
 
@@ -47,7 +47,7 @@ const MacroSetting = ({ macro, layerKey }: MacroSettingProps) => {
47
47
  {isEnable && `${macro.if_pressed.join(", ")}で発動`}
48
48
  </li>
49
49
  <div css={css`position: relative;`}>
50
- {openModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={macro.if_pressed} positionOnShown={"relative"} />}
50
+ {isOpenModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={macro.if_pressed} positionOnShown={"relative"} />}
51
51
  </div>
52
52
  </>
53
53
  )
@@ -42,7 +42,6 @@ export const ModeSettings = ({ layerKey }:ListProps) => {
42
42
  }, [] as Array<StructMode>);
43
43
  modes.unshift({ name: "disable" } as StructMode);
44
44
 
45
- // const hasSomeModes = layers.modes.length > 1;
46
45
  const hasSomeModes = modes.length > 1;
47
46
 
48
47
  return(
@@ -0,0 +1,38 @@
1
+ /** @jsx jsx */
2
+
3
+ import { jsx, css } from '@emotion/react'
4
+ import React, { Component, ErrorInfo, ReactNode } from "react";
5
+
6
+ interface Props {
7
+ children: ReactNode;
8
+ }
9
+
10
+ interface State {
11
+ hasError: boolean;
12
+ }
13
+
14
+ // https://react-typescript-cheatsheet.netlify.app/docs/basic/getting-started/error_boundaries/
15
+ class ErrorBoundary extends Component<Props, State> {
16
+ public state: State = {
17
+ hasError: false
18
+ };
19
+
20
+ public static getDerivedStateFromError(_: Error): State {
21
+ // Update state so the next render will show the fallback UI.
22
+ return { hasError: true };
23
+ }
24
+
25
+ public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
26
+ console.error("Uncaught error:", error, errorInfo);
27
+ }
28
+
29
+ public render() {
30
+ if (this.state.hasError) {
31
+ return <h1>Sorry..there was an error</h1>;
32
+ }
33
+
34
+ return this.props.children;
35
+ }
36
+ }
37
+
38
+ export default ErrorBoundary;
@@ -1,7 +1,7 @@
1
1
  /** @jsx jsx */
2
2
 
3
3
  import { jsx, css } from '@emotion/react'
4
- import React, { useState, useEffect, useContext, useRef } from "react";
4
+ import React, { useState, useEffect, useReducer, useContext, useRef } from "react";
5
5
  import { ButtonsSetting } from "../components/buttons_setting";
6
6
  import { Button, buttons } from "../types/button";
7
7
  import { LayerKey, layerKeys } from "../types/layer_key";
@@ -25,7 +25,8 @@ interface LayerRef {
25
25
  };
26
26
 
27
27
  export const ButtonsSettingPage = () => {
28
- const { loaded, setLoaded, layers, layersDispatch, prefixKeys, setPrefixKeys } = useContext(ButtonsSettingContext);
28
+ const [loaded, DidLoad] = useReducer(() => { return true; }, false);
29
+ const { layers, layersDispatch, prefixKeys, setPrefixKeys } = useContext(ButtonsSettingContext);
29
30
  const [selectedLayer, setSelectedLayer] = useState<LayerKey>("up");
30
31
  const layerRefs = layerKeys.map((l) => ({} as LayerRef));
31
32
  const [initializedSetting, setInitializedSetting] = useState({} as ButtonsSettingType)
@@ -117,7 +118,7 @@ export const ButtonsSettingPage = () => {
117
118
  })
118
119
  }
119
120
 
120
- setPrefixKeys(response.data.setting.prefix_keys_for_changing_layer);
121
+ setPrefixKeys(response.data.setting.prefix_keys_for_changing_layer.sort());
121
122
  const layers = layerKeys.reduce((a, key) => {
122
123
  a[key] = response.data.setting_group_by_button.layers[key];
123
124
  return a;
@@ -173,7 +174,7 @@ export const ButtonsSettingPage = () => {
173
174
  });
174
175
  });
175
176
 
176
- setLoaded(true);
177
+ DidLoad();
177
178
  }).catch(function (error) {
178
179
  if (error.response.status === 404) {
179
180
  setInfoMessage("設定ファイルのパスが未設定です")
@@ -181,7 +182,6 @@ export const ButtonsSettingPage = () => {
181
182
  console.log("想定外のエラーです");
182
183
  }
183
184
  })
184
-
185
185
  }, [loaded]);
186
186
 
187
187
  const layersTabStyle = () => {
@@ -219,20 +219,22 @@ export const ButtonsSettingPage = () => {
219
219
  };
220
220
  }
221
221
  const handlePrefixKeysField = () => {
222
- setOpenModal(true)
222
+ toggleModal();
223
223
  setModalTitle("キープレフィックスの変更")
224
224
  setModalPrefillButtons(prefixKeys);
225
225
  setModalCallbackOnSubmit(() => setPrefixKeys);
226
- setModalCloseCallback(() => setOpenModal);
226
+ setModalCloseCallback(() => toggleModal);
227
227
  }
228
228
 
229
229
  // for modal
230
- const [openModal, setOpenModal] = useState(false)
230
+ const [isOpenModal, toggleModal] = useReducer(((m) => { return !m; }), false);
231
231
  const [modalCallbackOnSubmit, setModalCallbackOnSubmit] = useState(undefined as any)
232
232
  const [modalCloseCallback, setModalCloseCallback] = useState(undefined as any)
233
233
  const [modalTitle, setModalTitle] = useState("")
234
234
  const [modalPrefillButtons, setModalPrefillButtons] = useState<Array<Button>>([])
235
235
 
236
+ if(!loaded) { return null; };
237
+
236
238
  return(
237
239
  <>
238
240
  <div css={css`display: table`}>
@@ -243,15 +245,18 @@ export const ButtonsSettingPage = () => {
243
245
  </div>
244
246
 
245
247
  <h3>インストール可能なマクロ</h3>
246
- {loaded && <InstallableMacros />}
248
+ {<InstallableMacros />}
247
249
 
248
250
  <h3>インストール可能なモード</h3>
249
- {loaded && <InstallableModes />}
251
+ {<InstallableModes />}
252
+
253
+ <h3>インストール可能なマクロ</h3>
254
+ {loaded && <InstallableMacros />}
250
255
 
251
256
  <h3>設定中のプレフィックスキー</h3>
252
257
  <div css={css`position: relative; margin-bottom: 20px;`}>
253
258
  <input type="text" value={prefixKeys.join(", ")} readOnly={true} onClick={handlePrefixKeysField} />
254
- {openModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={modalPrefillButtons} positionOnShown={"stay"} />}
259
+ {isOpenModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={modalPrefillButtons} positionOnShown={"stay"} />}
255
260
  </div>
256
261
  </div>
257
262
  <div css={css`display: table-cell`}>
@@ -260,7 +265,7 @@ export const ButtonsSettingPage = () => {
260
265
  <a href="#" onClick={applySetting}>変更した設定でsetting.ymlへ上書きする</a>
261
266
  <div>{infoMessage}</div>
262
267
  <ul>
263
- {loaded && changes().map((c, i) => <li key={i}>{c}</li>)}
268
+ {changes().map((c, i) => <li key={i}>{c}</li>)}
264
269
  </ul>
265
270
  </div>
266
271
  </div>
@@ -274,8 +279,7 @@ export const ButtonsSettingPage = () => {
274
279
  ))}
275
280
  </ul>
276
281
 
277
- {loaded && layerKeys.map((l, index) => (<ButtonsSetting key={index} layerKey={l} layerRef={layerRefs[index]} />))}
278
- {!loaded && "loading..."}
282
+ {layerKeys.map((l, index) => (<ButtonsSetting key={index} layerKey={l} layerRef={layerRefs[index]} />))}
279
283
  </>
280
284
  )
281
285
  }
data/src/pages/top.tsx CHANGED
@@ -17,8 +17,9 @@ import { ButtonsSettingContext } from "./../contexts/buttons_setting";
17
17
  import { ButtonsInLayer, Layers, ButtonsSettingType } from "../types/buttons_setting_type";
18
18
  import { buttons, Button } from "../types/button";
19
19
  import { LayerReducer } from "../reducers/layer_reducer";
20
+ import ErrorBoundary from "../lib/error_boundary";
20
21
 
21
- const ButtonsSettingProfile: React.FC = ({children}) => {
22
+ const ButtonsSettingProvider: React.FC = ({children}) => {
22
23
  const initLayers: Layers = {
23
24
  up: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
24
25
  right: buttons.reduce((a, i) => { a[i] = { open: false }; return a }, {} as ButtonsInLayer),
@@ -28,11 +29,8 @@ const ButtonsSettingProfile: React.FC = ({children}) => {
28
29
  installed_modes: {},
29
30
  }
30
31
  const [prefixKeys, setPrefixKeys] = useState([]);
31
- const [loaded, setLoaded] = useState(false);
32
32
  const [layers, layersDispatch] = useReducer(LayerReducer, initLayers as Layers);
33
33
  const value = {
34
- loaded,
35
- setLoaded,
36
34
  layers,
37
35
  prefixKeys,
38
36
  setPrefixKeys,
@@ -83,18 +81,27 @@ export const Top: React.FC = () => {
83
81
  </li>
84
82
  </ul>
85
83
  </nav>
84
+
86
85
  <Switch>
87
86
  <Route exact path="/" >
88
87
  <Home />
89
88
  </Route>
90
89
  <Route path="/setting">
91
- <GlobalSetting />
90
+ <ErrorBoundary>
91
+ <GlobalSetting />
92
+ </ErrorBoundary>
92
93
  </Route>
93
94
  <Route path="/pbm">
94
- <BpmPage />
95
+ <ErrorBoundary>
96
+ <BpmPage />
97
+ </ErrorBoundary>
95
98
  </Route>
96
99
  <Route path="/buttons_setting">
97
- <ButtonsSettingProfile><ButtonsSettingPage /></ButtonsSettingProfile>
100
+ <ErrorBoundary>
101
+ <ButtonsSettingProvider>
102
+ <ButtonsSettingPage />
103
+ </ButtonsSettingProvider>
104
+ </ErrorBoundary>
98
105
  </Route>
99
106
  <Route path="/recoding_mode">
100
107
  <RecodingModePage />
data/src/types/plugin.ts CHANGED
@@ -19,6 +19,9 @@ export const AvailablePlugins = [
19
19
  ],
20
20
  macros: [
21
21
  { display_name: "splatoon2.fast_return", class_namespace: "ProconBypassMan::Splatoon2::Macro::FastReturn" },
22
+ { display_name: "splatoon2.jump_right", class_namespace: "ProconBypassMan::Splatoon2::Macro::JumpToRightKey" },
23
+ { display_name: "splatoon2.jump_up", class_namespace: "ProconBypassMan::Splatoon2::Macro::JumpToUpKey" },
24
+ { display_name: "splatoon2.jump_left", class_namespace: "ProconBypassMan::Splatoon2::Macro::JumpToLeftKey" },
22
25
  ],
23
26
  }
24
27
  } as Plugin,