All files / lib/components/Game/Screen/FreeForm/Page/Block/Button index.tsx

0% Statements 0/30
0% Branches 0/16
0% Functions 0/7
0% Lines 0/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                                                                                                                                                                                                   
/* eslint-disable react/no-array-index-key */
import React, { useContext, useEffect, useRef } from 'react';
import { css } from '@emotion/react';
import {
  ButtonBlock as ButtonBlockModel,
  ButtonBlockStyle,
  supportActionList as buttonBlockSupportActionList
} from '@uniquegood/realworld-web-interface/lib/models/game/Block/Button';
import { useGameStateContext } from '@lib/providers/GameState';
import { useRunStatement } from '@lib/utils/Game/Statement';
 
export default function ButtonBlock({ id, actionMap, style, contents }: ButtonBlockModel) {
  const { render, saveOnServer } = useGameStateContext();
  const { runStatement } = useRunStatement();
 
  const buttonRef = useRef<HTMLButtonElement | null>(null);
  const isProcessingRef = useRef(false);
 
  useEffect(() => {
    const listeners = buttonBlockSupportActionList.reduce((arr, action) => {
      const statementList = actionMap[action]?.statementList;
      if (statementList && buttonRef.current) {
        const listener = async () => {
          if (isProcessingRef.current) {
            return;
          }
          isProcessingRef.current = true;
          for await (const statement of statementList) {
            await runStatement({
              statement,
              withParameter: {
                blockId: id,
                originActionType: action
              }
            });
          }
          saveOnServer();
          render();
          isProcessingRef.current = false;
        };
        buttonRef.current.addEventListener(`${action}`, listener);
        arr.push({ type: action, listener });
      }
 
      return arr;
    }, [] as { type: string; listener: () => unknown }[]);
 
    return () => {
      listeners.forEach(({ type, listener }) => {
        if (!buttonRef.current || !type) {
          return;
        }
        buttonRef.current.removeEventListener(type, listener);
      });
    };
  }, []);
 
  const containerStyle = React.useMemo(() => {
    const styleObj = ButtonBlockStyle.parse(style);
    return css`
      text-align: ${styleObj.align};
      background-color: ${styleObj.backgroundColor};
      border-width: ${styleObj.borderWidth}px;
      border-color: ${styleObj.borderColor};
      border-radius: ${styleObj.borderRadius}px;
      font-size: ${styleObj.fontSize}px;
      color: ${styleObj.fontColor};
      font-family: ${styleObj.fontFamily};
      font-weight: ${styleObj.isBold ? 'bold' : 'normal'};
      font-style: ${styleObj.isItalic ? 'italic' : 'normal'};
      text-decoration: ${styleObj.isUnderline ? 'underline' : 'none'};
    `;
  }, [style]);
 
  return (
    <button ref={buttonRef} type="button" css={[buttonStyle, containerStyle]}>
      <p
        style={{
          textAlign: style.align
        }}
      >
        {contents}
      </p>
    </button>
  );
}
 
const buttonStyle = css`
  width: 100%;
  height: 100%;
  border: none;
  white-space: pre-line;
  cursor: pointer;
 
  padding: 8px 12px;
  border-radius: 8px;
`;