읽기 순서를 임의로 결정하는 크롬 확장 기능을 위한 for Google Meet [React+Type Script] 만들기

최근 우리 회사의 개발자들은 블로그를 쓰는 운동을 하고 있다.
소재를 찾다가 좋은 기사를 발견했으니 아이디어를 빌려주세요.
고마워요🙏
※ 펙슬리는 절대 아닙니다
https://techblog.roxx.co.jp/entry/2021/04/23/064837
매주 팀 내에서 독서회와 부문별 엔지니어 윤독회를 열지만 매번 독서 순서를 정하는 것이 번거롭기 때문에 cherome 확장 기능을 만들어 참가한 멤버들을 카드를 씻은 후 리스트로 돌려준다.
또한 당사의 독서는 Google Meet에서 많이 열리기 때문에 Google Meet의 확장 기능이 될 수밖에 없습니다. 이해해 주십시오.

만든 물건


현재 Meet의 구성원을 무작위로 정렬하고 나열할 수 있는 확장 기능이 만들어졌습니다.
※ 스토어에는 공개되지 않음
image
여기서 공개되니까 꼭 봐주세요.
https://github.com/SotaYamaguchi/shuffle-members-extension-for-google-meet

기술 선정


UI 구성이 포함되어 있어 익숙한 프레임을 사용하고자 React+Type Script를 적용했습니다.
크롬 extension을 만들 때 다음 템플릿을 사용하면 React+Type Script를 넣은 상태에서 쉽게 사용할 수 있습니다.
https://github.com/chibat/chrome-extension-typescript-starter

포장류


Chrome 확장을 읽는 유형 정의@types/chrome가 사용됩니다.
image

popup.tsx 및 콘텐츠script.tsx

  • popup.tsx
  • 브라우저의cherome 확장 기능 버튼을 누르면 나오는 것들
  • content_script.tsx
  • 열린 탭에서 실행할 수 있는script
  • 상기 두 곳에서 데이터를 교환하기 위해서는 아래 크롬의 API를 사용하십시오chrome.tabs.sendMessage() chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {} )https://developer.chrome.com/docs/extensions/reference/tabs/
    https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessage

    popup 측 설치


    사용자 목록 표시


    사용자 일람 drawer를 표시하지 않으면 참여 멤버 이름이 있는 DOM이 생성되지 않습니다.
    처음 렌더링할 때 sendMessage로 콘텐츠 만들기스크립트 옆에 이벤트 점화

    참가 멤버 일람의 취득 처리


    oukajinigetMemberList () 실행 일람을 통해 단추를 가져오고sendMessage,conntent를 보냅니다script 측면에서 script를 실행하고 문자열로 참가 구성원 일람을 얻습니다
    가공 후view 옆에 표시하여 참가 멤버 일람표를 표시합니다
    popup.tsx
      const currentChromeTab = (callback: (tabId: number) => void) => {
        chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
          // 現在表示しているタブを取得
          const tab = tabs[0];
          if (tab.id) {
            callback(tab.id);
          }
        });
      };
    
      const getMemberList = () => {
        currentChromeTab((tabId) => {
          chrome.tabs.sendMessage(
            tabId,
            undefined, // message は不要なため undefined とする
            (msg) => {
              if (typeof msg === "string") {
                const shuffledMembers = shuffle(msg.split(","));
                setCurrentTime(new Date());
                setMembers(shuffledMembers);
              }
            }
          );
        });
      };
    
      // init
      useEffect(() => {
        currentChromeTab((tabId) => {
          // ユーザー一覧 drawer を表示させる
          chrome.tabs.sendMessage(tabId, undefined);
        });
      }, []);
    

    content_script 측 설치


    사용자 목록drawer의 표시 판정


    처음 표시될 때 사용자가 drawer를 일람하는 디스플레이 판정이 진행되며, 표시되지 않을 때 자동으로 켜집니다

    참가 구성원의 이름 목록 가져오기


    참가 성원명은 씨엘마이라는 학급명을 가진 덤의 자손들에게 보존되기 때문에 취득
    content-script.tsx
    const openAllUserDrawer = () => {
      /*
       * 各ボタンの aria-label 属性にラベルに表示するボタン名が格納されている
       * 全てのボタンを DOM から取得して全員を表示ボタンを探す
       */
      const ariaLabelElems = document.querySelectorAll("[aria-label]");
      for (let i = 0; i < ariaLabelElems.length; i++) {
        if (
          ariaLabelElems[i].getAttribute("aria-label") === ALL_USER_BUTTON_LABEL
        ) {
          const chatOpenButton = ariaLabelElems[i] as HTMLButtonElement;
          chatOpenButton.click();
        }
      }
    };
    
    const getUserNameList = (sendResponse: (response?: any) => void) => {
      let names: string[] = [];
      const elems = document.querySelectorAll(".cylMye");
      if (!elems.length) {
        // .cylMye が存在しない = ユーザー一覧 drawer が表示されていない
        openAllUserDrawer();
        return;
      }
      for (let i = 0; i < elems.length; i++) {
        names = [...names, findUserNameFromElm(elems[i])];
      }
      // 重複した名前を省く
      names = Array.from(new Set(names));
      sendResponse(names.join(","));
    };
    
    chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
      getUserNameList(sendResponse);
    });
    

    구성원의 함수를 흐트러뜨리다


    이번에는 랜덤 편차를 없애기 위해낚시꾼이 간판을 뒤섞다.
    알고리즘은 이런 방법을 채택했다
    shuffle.ts
    const shuffle = (value: string[]) => {
      for (let i = value.length - 1; i >= 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [value[i], value[j]] = [value[j], value[i]];
      }
      return value;
    };
    
    export default shuffle;
    

    zip 파일 생성


    Giithub Actions를 사용하여 마스터 지점 push에 갈 때build+ 실행 결과를 실행합니다.zip으로 압축하여 발행에 포함합니다.yml에 기재
    .github/workflows/build.yml
          - name: yarn install & build
            run: |
              yarn
              yarn build --if-present
          - name: zip output
            run: |
              cd dist
              zip release *.*
          ・
          ・
          ・
          - name: upload Release Asset
            id: upload-release-asset
            uses: actions/upload-release-asset@v1
            env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            with:
              upload_url: ${{ steps.create_release.outputs.upload_url }}
              asset_path: ./dist/release.zip
              asset_name: chrome-extention.zip
              asset_content_type: application/zip
    

    총결산


    참가 인원을 집계할 수 있어 편리하니 꼭 사용하세요.
    앞으로 공개될 때까지 해보고 싶다.

    좋은 웹페이지 즐겨찾기