procon_bypass_man-web 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,6 +15,10 @@ module ProconBypassMan
15
15
  class App < Sinatra::Base
16
16
  require "yaml"
17
17
 
18
+ before do
19
+ env["rack.logger"] = ProconBypassMan::Web.logger
20
+ end
21
+
18
22
  register Sinatra::Reloader if defined?(Sinatra::Reloader)
19
23
  set :bind, '0.0.0.0'
20
24
 
@@ -119,13 +123,19 @@ module ProconBypassMan
119
123
  end
120
124
  end
121
125
 
126
+ # PBMから受け取って、emmitする
127
+ post '/api/pressed_buttons' do
128
+ status 200
129
+ body ''
130
+ end
131
+
122
132
  get '/' do
123
- send_file File.join(ProconBypassMan::Web.root, 'lib/procon_bypass_man/web', 'public', 'index.html')
133
+ send_file File.join(ProconBypassMan::Web.gem_root, 'lib/procon_bypass_man/web', 'public', 'index.html')
124
134
  end
125
135
 
126
136
  # サーバでパスとして解釈されないように、全部 `/`として受け付けるため
127
137
  get '/:none' do
128
- send_file File.join(ProconBypassMan::Web.root, 'lib/procon_bypass_man/web', 'public', 'index.html')
138
+ send_file File.join(ProconBypassMan::Web.gem_root, 'lib/procon_bypass_man/web', 'public', 'index.html')
129
139
  end
130
140
  end
131
141
 
@@ -0,0 +1,72 @@
1
+ module ProconBypassMan
2
+ module Web
3
+ class SettingParser
4
+ class Layer
5
+ module Syntax
6
+ def initialize(mode: )
7
+ @table = {
8
+ mode: mode&.to_s,
9
+ }.compact
10
+ end
11
+
12
+ def flip(button, if_pressed: nil, force_neutral: nil)
13
+ @table[:flip] ||= {}
14
+ if if_pressed.nil? && force_neutral.nil?
15
+ @table[:flip][button] = nil
16
+ else
17
+ if if_pressed
18
+ if if_pressed.is_a?(Array)
19
+ ifp = if_pressed
20
+ else
21
+ ifp = [if_pressed]
22
+ end
23
+ end
24
+ if force_neutral
25
+ if force_neutral.is_a?(Array)
26
+ fn = force_neutral
27
+ else
28
+ fn = [force_neutral]
29
+ end
30
+ end
31
+ @table[:flip][button] = { if_pressed: ifp, force_neutral: fn, enable: true }
32
+ end
33
+ self
34
+ end
35
+
36
+ def remap(button, to: nil)
37
+ case to
38
+ when Array
39
+ @table[:remap] ||= {}
40
+ @table[:remap][button] = { to: to }
41
+ when String, Symbol
42
+ @table[:remap] ||= {}
43
+ @table[:remap][button] = { to: [to] }
44
+ end
45
+
46
+ self
47
+ end
48
+
49
+ def macro(name, if_pressed: nil)
50
+ @table[:macro] ||= {}
51
+ if if_pressed.nil?
52
+ @table[:macro][name.to_s] = { if_pressed: [] }
53
+ else
54
+ @table[:macro][name.to_s] = { if_pressed: if_pressed }
55
+ end
56
+ self
57
+ end
58
+
59
+ def method_missing(name, *_args)
60
+ ProconBypassMan::Web.logger.info("unknown layer DSL #{name}")
61
+ self
62
+ end
63
+ end
64
+ include Syntax
65
+
66
+ def to_hash
67
+ @table
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,109 @@
1
+ module ProconBypassMan
2
+ module Web
3
+ class SettingParser
4
+ class TopLevelLayer
5
+ module Serializer
6
+ def to_hash
7
+ h = { prefix_keys_for_changing_layer: prefix_keys_for_changing_layer || [] }
8
+ h[:layers] ||= {}
9
+ @layers.each do |key, layer|
10
+ h[:layers][key] = layer&.to_hash
11
+ end
12
+ h
13
+ end
14
+
15
+ def to_hash_group_by_button
16
+ h = { prefix_keys_for_changing_layer: prefix_keys_for_changing_layer || [] }
17
+ h[:layers] ||= {}
18
+ @layers.each do |key, layer|
19
+ h[:layers][key] ||= {}
20
+ next if layer.nil?
21
+
22
+ if !@installed_plugin[:macros].empty?
23
+ h[:installed_macros] = @installed_plugin[:macros]
24
+ end
25
+ if !@installed_plugin[:modes].empty?
26
+ h[:installed_modes] = @installed_plugin[:modes]
27
+ end
28
+
29
+ layer.to_hash.dig(:flip)&.each do |button, value|
30
+ h[:layers][key][button] ||= {}
31
+ h[:layers][key][button][:open] = true
32
+ h[:layers][key][button][:flip] ||= {}
33
+ h[:layers][key][button][:flip][:enable] = true
34
+ if value
35
+ h[:layers][key][button][:flip].merge!(value)
36
+ end
37
+ end
38
+
39
+ if layer.to_hash.dig(:macro)
40
+ h[:layers][key][:macro] = []
41
+ if(macros = layer.to_hash.dig(:macro))
42
+ macros.transform_values! { |x| x[:if_pressed] }
43
+ h[:layers][key][:macro] = macros
44
+ end
45
+ end
46
+
47
+ if layer.to_hash.dig(:mode)
48
+ h[:layers][key][:mode] = { layer.to_hash.dig(:mode) => true }
49
+ end
50
+
51
+ layer.to_hash.dig(:remap)&.each do |button, value|
52
+ h[:layers][key][button] ||= {}
53
+ h[:layers][key][button][:remap] ||= {}
54
+ h[:layers][key][button][:open] = true
55
+ if value
56
+ h[:layers][key][button][:remap].merge!(value)
57
+ end
58
+ end
59
+ end
60
+ h
61
+ end
62
+ end
63
+
64
+ module Syntax
65
+ def initialize
66
+ @installed_plugin = { macros: [], modes: [] }
67
+ @layers = {}
68
+ end
69
+
70
+ def install_macro_plugin(name)
71
+ @installed_plugin[:macros] << name.to_s
72
+ end
73
+
74
+ def install_mode_plugin(name)
75
+ @installed_plugin[:modes] << name.to_s
76
+ end
77
+
78
+ def prefix_keys_for_changing_layer(value=nil)
79
+ if value
80
+ @prefix_keys_for_changing_layer = value
81
+ else
82
+ @prefix_keys_for_changing_layer
83
+ end
84
+ end
85
+
86
+ def layer(dir, mode: nil, &block)
87
+ if(mode == :manual || mode == 'manual')
88
+ mode = nil
89
+ end
90
+
91
+ if block_given?
92
+ @layers[dir] = Layer.new(mode: mode).instance_eval(&block) || Layer.new(mode: mode)
93
+ else
94
+ @layers[dir] = Layer.new(mode: mode)
95
+ end
96
+ end
97
+
98
+ def method_missing(name, *_args)
99
+ ProconBypassMan::Web.logger.info("unknown toplevel DSL #{name}")
100
+ self
101
+ end
102
+ end
103
+
104
+ include Syntax
105
+ include Serializer
106
+ end
107
+ end
108
+ end
109
+ end
@@ -1,4 +1,6 @@
1
1
  require "json"
2
+ require "procon_bypass_man/web/setting_parser/top_level_layer"
3
+ require "procon_bypass_man/web/setting_parser/layer"
2
4
 
3
5
  # pluginの定数を握りつぶす
4
6
  class Module
@@ -9,160 +11,10 @@ class Module
9
11
  end
10
12
  end
11
13
 
14
+ # PBM 0.1.8バージョンの構文に対応
12
15
  module ProconBypassMan
13
16
  module Web
14
17
  class SettingParser
15
- class Core
16
- class Layer
17
- def initialize(mode: )
18
- @table = {
19
- mode: mode&.to_s,
20
- }.compact
21
- end
22
-
23
- def flip(button, if_pressed: nil, force_neutral: nil)
24
- @table[:flip] ||= {}
25
- if if_pressed.nil? && force_neutral.nil?
26
- @table[:flip][button] = nil
27
- else
28
- if if_pressed
29
- if if_pressed.is_a?(Array)
30
- ifp = if_pressed
31
- else
32
- ifp = [if_pressed]
33
- end
34
- end
35
- if force_neutral
36
- if force_neutral.is_a?(Array)
37
- fn = force_neutral
38
- else
39
- fn = [force_neutral]
40
- end
41
- end
42
- @table[:flip][button] = { if_pressed: ifp, force_neutral: fn, enable: true }
43
- end
44
- self
45
- end
46
-
47
- def remap(button, to: nil)
48
- case to
49
- when Array
50
- @table[:remap] ||= {}
51
- @table[:remap][button] = { to: to }
52
- when String, Symbol
53
- @table[:remap] ||= {}
54
- @table[:remap][button] = { to: [to] }
55
- end
56
-
57
- self
58
- end
59
-
60
- def macro(name, if_pressed: nil)
61
- @table[:macro] ||= {}
62
- if if_pressed.nil?
63
- @table[:macro][name.to_s] = { if_pressed: [] }
64
- else
65
- @table[:macro][name.to_s] = { if_pressed: if_pressed }
66
- end
67
- self
68
- end
69
-
70
- def to_hash
71
- @table
72
- end
73
- end
74
-
75
- def install_macro_plugin(name)
76
- @installed_plugin[:macros] << name.to_s
77
- end
78
-
79
- def install_mode_plugin(name)
80
- @installed_plugin[:modes] << name.to_s
81
- end
82
-
83
- def initialize
84
- @installed_plugin = { macros: [], modes: [] }
85
- @layers = {}
86
- end
87
-
88
- def prefix_keys_for_changing_layer(value=nil)
89
- if value
90
- @prefix_keys_for_changing_layer = value
91
- else
92
- @prefix_keys_for_changing_layer
93
- end
94
- end
95
-
96
- def layer(dir, mode: nil, &block)
97
- if(mode == :manual || mode == 'manual')
98
- mode = nil
99
- end
100
-
101
- if block_given?
102
- @layers[dir] = Layer.new(mode: mode).instance_eval(&block) || Layer.new(mode: mode)
103
- else
104
- @layers[dir] = Layer.new(mode: mode)
105
- end
106
- end
107
-
108
- def to_hash
109
- h = { prefix_keys_for_changing_layer: prefix_keys_for_changing_layer || [] }
110
- h[:layers] ||= {}
111
- @layers.each do |key, layer|
112
- h[:layers][key] = layer&.to_hash
113
- end
114
- h
115
- end
116
-
117
- def to_hash_group_by_button
118
- h = { prefix_keys_for_changing_layer: prefix_keys_for_changing_layer || [] }
119
- h[:layers] ||= {}
120
- @layers.each do |key, layer|
121
- h[:layers][key] ||= {}
122
- next if layer.nil?
123
-
124
- if !@installed_plugin[:macros].empty?
125
- h[:installed_macros] = @installed_plugin[:macros]
126
- end
127
- if !@installed_plugin[:modes].empty?
128
- h[:installed_modes] = @installed_plugin[:modes]
129
- end
130
-
131
- layer.to_hash.dig(:flip)&.each do |button, value|
132
- h[:layers][key][button] ||= {}
133
- h[:layers][key][button][:open] = true
134
- h[:layers][key][button][:flip] ||= {}
135
- h[:layers][key][button][:flip][:enable] = true
136
- if value
137
- h[:layers][key][button][:flip].merge!(value)
138
- end
139
- end
140
-
141
- if layer.to_hash.dig(:macro)
142
- h[:layers][key][:macro] = []
143
- if(macros = layer.to_hash.dig(:macro))
144
- macros.transform_values! { |x| x[:if_pressed] }
145
- h[:layers][key][:macro] = macros
146
- end
147
- end
148
-
149
- if layer.to_hash.dig(:mode)
150
- h[:layers][key][:mode] = { layer.to_hash.dig(:mode) => true }
151
- end
152
-
153
- layer.to_hash.dig(:remap)&.each do |button, value|
154
- h[:layers][key][button] ||= {}
155
- h[:layers][key][button][:remap] ||= {}
156
- h[:layers][key][button][:open] = true
157
- if value
158
- h[:layers][key][button][:remap].merge!(value)
159
- end
160
- end
161
- end
162
- h
163
- end
164
- end
165
-
166
18
  def self.parse(text)
167
19
  new(text)
168
20
  end
@@ -182,7 +34,7 @@ module ProconBypassMan
182
34
  end
183
35
 
184
36
  def initialize(text)
185
- @parser = Core.new
37
+ @parser = TopLevelLayer.new
186
38
  @parser.instance_eval(text)
187
39
  end
188
40
  end
@@ -6,19 +6,19 @@ module ProconBypassMan
6
6
  end
7
7
 
8
8
  def root_path
9
- ProconBypassMan::Web::Setting.find_or_create_by&.root_path
9
+ ProconBypassMan::Web::Setting.find_or_create&.root_path
10
10
  end
11
11
 
12
12
  def root_path=(value)
13
- ProconBypassMan::Web::Setting.find_or_create_by&.update!(root_path: value)
13
+ ProconBypassMan::Web::Setting.find_or_create&.update!(root_path: value)
14
14
  end
15
15
 
16
16
  def setting_path
17
- ProconBypassMan::Web::Setting.find_or_create_by&.setting_path
17
+ ProconBypassMan::Web::Setting.find_or_create&.setting_path
18
18
  end
19
19
 
20
20
  def setting_path=(value)
21
- ProconBypassMan::Web::Setting.find_or_create_by&.update!(setting_path: value)
21
+ ProconBypassMan::Web::Setting.find_or_create&.update!(setting_path: value)
22
22
  end
23
23
  end
24
24
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ProconBypassMan
4
4
  module Web
5
- VERSION = "0.1.1"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
@@ -1,4 +1,6 @@
1
1
  require_relative "web/version"
2
+ require "logger"
3
+ require "procon_bypass_man/web/configuration"
2
4
  require "procon_bypass_man/web/server"
3
5
  require "procon_bypass_man/web/db"
4
6
  require "procon_bypass_man/web/models/setting"
@@ -8,13 +10,21 @@ module ProconBypassMan
8
10
  module Web
9
11
  class Error < StandardError; end
10
12
 
11
- def self.root
12
- File.expand_path('../..', File.dirname(__FILE__))
13
+ extend ProconBypassMan::Web::Configuration::ClassAttributes
14
+
15
+ def self.configure(&block)
16
+ @@configuration = ProconBypassMan::Web::Configuration.new
17
+ @@configuration.instance_eval(&block)
18
+ @@configuration
13
19
  end
14
20
 
15
21
  def self.config
16
- { db_path: ENV["DB_PATH"] ||= File.join(root, "pbm_web.db"),
17
- }
22
+ @@configuration ||= ProconBypassMan::Web::Configuration.new
23
+ end
24
+
25
+ # @return [String]
26
+ def self.gem_root
27
+ File.expand_path('../..', __dir__).freeze
18
28
  end
19
29
  end
20
30
  end
@@ -9,6 +9,8 @@ import { ButtonsSettingContext } from "./../contexts/buttons_setting";
9
9
  import { ButtonsSettingType, ButtonsInLayer, ButtonInLayer, Layers, Flip } from "../types/buttons_setting_type";
10
10
  import { LayerKey } from "../types/layer_key";
11
11
  import { disableFlipType, alwaysFlipType, flipIfPressedSelfType, flipIfPressedSomeButtonsType, ignoreButtonsInFlipingType, remapType, openMenuType, closeMenuType } from "../reducers/layer_reducer";
12
+ import { useModal, ModalSetting } from "../hooks/useModal";
13
+ import { ModalProps } from "../components/buttons_modal";
12
14
 
13
15
  type ButtonMenuProp = {
14
16
  name: Button;
@@ -19,27 +21,20 @@ type ButtonMenuProp = {
19
21
 
20
22
  const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuProp) => {
21
23
  const buttonState = new ButtonState(name, buttonValue.flip, buttonValue.remap);
22
-
23
- // for modal
24
- const [isOpenModal, toggleModal] = useReducer((m) => { return !m; }, false);
25
-
26
- const [modalCallbackOnSubmit, setModalCallbackOnSubmit] = useState(undefined as any)
27
- const [modalCloseCallback, setModalCloseCallback] = useState(undefined as any)
28
- const [modalTitle, setModalTitle] = useState("")
29
- const [modalPrefillButtons, setModalPrefillButtons] = useState<Array<Button>>([])
24
+ const [modalProps, openModal] = useModal();
30
25
 
31
26
  // 無効
32
- const handleNullFlipValue = (e: React.ChangeEvent<HTMLInputElement>) => {
27
+ const handleNullFlipValue = (e: React.MouseEvent<HTMLInputElement>) => {
33
28
  layersDispatch({ type: disableFlipType, payload: { layerKey: layerKey, button: name }});
34
29
  };
35
30
 
36
31
  // 常に連打
37
- const handleFlipValue = (e: React.ChangeEvent<HTMLInputElement>) => {
32
+ const handleFlipValue = (e: React.MouseEvent<HTMLInputElement>) => {
38
33
  layersDispatch({ type: alwaysFlipType, payload: { layerKey: layerKey, button: name }});
39
34
  };
40
35
 
41
36
  // 自分自身への条件付き連打
42
- const openIfPressedRadioboxModal = (e: React.ChangeEvent<HTMLInputElement>) => {
37
+ const openIfPressedRadioboxModal = (e: React.MouseEvent<HTMLInputElement>) => {
43
38
  layersDispatch({ type: flipIfPressedSelfType, payload: { layerKey: layerKey, button: name }});
44
39
  };
45
40
 
@@ -48,12 +43,8 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
48
43
  const setFlipIfPressedSomeButtonsWithPersistence = (bs: Array<Button>) => {
49
44
  layersDispatch({ type: flipIfPressedSomeButtonsType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
50
45
  }
51
- const openIfPressedSomeButtonsModal = (e: React.ChangeEvent<HTMLInputElement> | React.MouseEvent<HTMLInputElement>) => {
52
- toggleModal();
53
- setModalTitle("特定のキーを押したときだけ")
54
- setModalPrefillButtons(flipIfPressedSomeButtons);
55
- setModalCallbackOnSubmit(() => setFlipIfPressedSomeButtonsWithPersistence);
56
- setModalCloseCallback(() => toggleModal);
46
+ const openIfPressedSomeButtonsModal = (e: React.MouseEvent<HTMLInputElement>) => {
47
+ openModal({ title: "特定のキーを押したときだけ", prefill: flipIfPressedSomeButtons, callbackOnSubmit: setFlipIfPressedSomeButtonsWithPersistence });
57
48
  }
58
49
 
59
50
  // 無視
@@ -62,11 +53,7 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
62
53
  layersDispatch({ type: ignoreButtonsInFlipingType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
63
54
  }
64
55
  const handleIgnoreButton = (e: React.ChangeEvent<HTMLInputElement>) => {
65
- toggleModal();
66
- setModalTitle("連打中は特定のボタンの入力を無視する")
67
- setModalPrefillButtons(buttonValue.flip?.force_neutral || [] as Array<Button>);
68
- setModalCallbackOnSubmit(() => setIgnoreButtonsOnFlipingWithPersistence);
69
- setModalCloseCallback(() => toggleModal);
56
+ openModal({ title: "連打中は特定のボタンの入力を無視する", prefill: buttonValue.flip?.force_neutral || [] as Array<Button>, callbackOnSubmit: setIgnoreButtonsOnFlipingWithPersistence });
70
57
  };
71
58
 
72
59
  // リマップ
@@ -74,21 +61,20 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
74
61
  layersDispatch({ type: remapType, payload: { layerKey: layerKey, button: name, targetButtons: bs }});
75
62
  }
76
63
  const handleRemapButton = (e: React.ChangeEvent<HTMLInputElement>) => {
77
- toggleModal();
78
- setModalTitle("リマップ")
79
- setModalPrefillButtons(buttonValue.remap?.to || []);
80
- setModalCallbackOnSubmit(() => setRemapButtonsWithPersistence);
81
- setModalCloseCallback(() => toggleModal);
64
+ openModal({ title: "リマップ", prefill: buttonValue.remap?.to || [], callbackOnSubmit: setRemapButtonsWithPersistence });
82
65
  };
83
66
 
84
67
  return(
85
68
  <>
69
+ <div css={css`position: relative;`}>
70
+ {<ButtonsModal {...modalProps as ModalProps} />}
71
+ </div>
86
72
  <fieldset><legend><strong>連打設定</strong></legend>
87
- <label><input type="radio" onChange={handleNullFlipValue} checked={buttonState.isDisabledFlip()}/>無効</label><br />
88
- <label><input type="radio" onChange={handleFlipValue} checked={buttonState.isAlwaysFlip()}/>常に連打する</label><br />
89
- <label><input type="radio" onChange={openIfPressedRadioboxModal} checked={buttonState.isFlipIfPressedSelf()}/>このボタンを押している時だけ連打する({name})</label><br />
73
+ <label><input type="radio" onClick={handleNullFlipValue} checked={buttonState.isDisabledFlip()} readOnly={true} />無効</label><br />
74
+ <label><input type="radio" onClick={handleFlipValue} checked={buttonState.isAlwaysFlip()} readOnly={true} />常に連打する</label><br />
75
+ <label><input type="radio" onClick={openIfPressedRadioboxModal} checked={buttonState.isFlipIfPressedSelf()} readOnly={true} />このボタンを押している時だけ連打する({name})</label><br />
90
76
  <label>
91
- <input type="radio" onChange={openIfPressedSomeButtonsModal} onClick={openIfPressedSomeButtonsModal} checked={buttonState.isFlipIfPressedSomeButtons()}/>
77
+ <input type="radio" onClick={openIfPressedSomeButtonsModal} checked={buttonState.isFlipIfPressedSomeButtons()} readOnly={true} />
92
78
  特定のキーを押したときだけ連打する{flipIfPressedSomeButtons.length > 0 && `(${flipIfPressedSomeButtons.join(", ")})`}
93
79
  </label>
94
80
 
@@ -106,9 +92,6 @@ const ButtonMenu = ({ name, layerKey, buttonValue, layersDispatch }: ButtonMenuP
106
92
  別のボタンに置き換える{buttonState.isRemap() && `(${buttonValue.remap?.to?.join(", ")})`}
107
93
  </label>
108
94
  </fieldset>
109
- <div css={css`position: relative;`}>
110
- {isOpenModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={modalPrefillButtons} positionOnShown={"relative"} />}
111
- </div>
112
95
  </>
113
96
  )
114
97
  }
@@ -4,19 +4,21 @@ import { jsx, css } from '@emotion/react'
4
4
  import React, { useState } from "react";
5
5
  import { Button, buttons } from "../types/button";
6
6
 
7
- type Props = {
7
+ export type ModalProps = {
8
8
  callbackOnSubmit: any;
9
9
  callbackOnClose: any;
10
10
  prefill: Array<Button>;
11
11
  title: string;
12
- positionOnShown: string;
12
+ visible: boolean;
13
13
  };
14
14
 
15
15
  type CheckedButtons = {
16
16
  [key in Button] : boolean
17
17
  }
18
18
 
19
- export const ButtonsModal = ({ callbackOnSubmit, callbackOnClose, title, prefill, positionOnShown }: Props) => {
19
+ export const ButtonsModal = ({ callbackOnSubmit, callbackOnClose, title, prefill, visible }: ModalProps) => {
20
+ if(!visible) { return null };
21
+
20
22
  const [checkedButtonMap, setCheckedButtonMap] = useState(
21
23
  prefill.reduce((a, b) => { a[b] = true; return a },
22
24
  buttons.reduce((a, b) => { a[b] = false; return a }, {} as CheckedButtons)
@@ -45,28 +47,16 @@ export const ButtonsModal = ({ callbackOnSubmit, callbackOnClose, title, prefill
45
47
  font-weight: bold;
46
48
  `)
47
49
  const style = () => {
48
- if(positionOnShown === "relative") {
49
- return css(`
50
- position: absolute;
51
- align: left;
52
- top: -400px;
53
- width: 400px;
54
- height: 400px;
55
- border: solid;
56
- background-color: white;
57
- `);
58
- } else {
59
- return css(`
60
- position: absolute;
61
- align: left;
62
- top: 0px;
63
- left: 20px;
64
- width: 400px;
65
- height: 400px;
66
- border: solid;
67
- background-color: white;
68
- `);
69
- }
50
+ return css(`
51
+ position: absolute;
52
+ align: left;
53
+ top: 0px;
54
+ left: 20px;
55
+ width: 400px;
56
+ height: 400px;
57
+ border: solid;
58
+ background-color: white;
59
+ `);
70
60
  }
71
61
  const aStyle = css`
72
62
  background-color: #4669ff;
@@ -10,29 +10,23 @@ import { Plugin, PluginBody, AvailablePlugins, MacroNameMap } from "../types/plu
10
10
  import { ButtonsModal } from "./buttons_modal";
11
11
  import { applyMacroType } from "../reducers/layer_reducer";
12
12
 
13
+ import { useModal, ModalSetting } from "../hooks/useModal";
14
+ import { ModalProps } from "../components/buttons_modal";
15
+
13
16
  type MacroSettingProps = {
14
17
  layerKey: LayerKey;
15
18
  macro: StructMacro;
16
19
  };
17
20
  const MacroSetting = ({ macro, layerKey }: MacroSettingProps) => {
18
21
  const { layersDispatch } = useContext(ButtonsSettingContext);
19
- // for modal
20
- const [isOpenModal, toggleModal] = useReducer((m) => { return !m; }, false);
21
- const [modalCallbackOnSubmit, setModalCallbackOnSubmit] = useState(undefined as any)
22
- const [modalCloseCallback, setModalCloseCallback] = useState(undefined as any)
23
- const [modalTitle, setModalTitle] = useState("")
24
- const [modalPrefillButtons, setModalPrefillButtons] = useState<Array<Button>>([])
22
+ const [modalProps, openModal] = useModal();
25
23
 
26
24
  const setButtonsForModal = (bs: Array<Button>) => {
27
25
  macro.if_pressed = bs;
28
26
  layersDispatch({ type: applyMacroType, payload: { layerKey: layerKey, macro: macro }});
29
27
  }
30
28
  const handleClick = (e: React.ChangeEvent<HTMLInputElement>) => {
31
- toggleModal();
32
- setModalTitle("発動キーの設定")
33
- setModalPrefillButtons(macro.if_pressed);
34
- setModalCallbackOnSubmit(() => setButtonsForModal);
35
- setModalCloseCallback(() => toggleModal);
29
+ openModal({ title: "キープレフィックスの変更", prefill: macro.if_pressed, callbackOnSubmit: setButtonsForModal });
36
30
  }
37
31
  const isEnable = macro.if_pressed.length > 0;
38
32
 
@@ -47,7 +41,7 @@ const MacroSetting = ({ macro, layerKey }: MacroSettingProps) => {
47
41
  {isEnable && `${macro.if_pressed.join(", ")}で発動`}
48
42
  </li>
49
43
  <div css={css`position: relative;`}>
50
- {isOpenModal && <ButtonsModal callbackOnSubmit={modalCallbackOnSubmit} callbackOnClose={modalCloseCallback} title={modalTitle} prefill={macro.if_pressed} positionOnShown={"relative"} />}
44
+ {<ButtonsModal {...modalProps as ModalProps} />}
51
45
  </div>
52
46
  </>
53
47
  )