728x90

크롬 익스텐션은 manifest를 루트로 로드해야한다.

{
    "manifest_version": 3,
    "name": "Learn on Air",
    "version": "1.0",
    "description": "Learn on Air for Chrome && inflearn",
    "permissions": [
      "activeTab",
      "tabs",
      "storage",
      "https://*/*"
    ],
    "action": {
      "default_popup": "./src/popup/popup.html",
      "default_icon": {
        "16": "public/16.png",
        "48": "public/48.png",
        "128": "public/128.png"
      }
    },
    "content_scripts": [
      {
        "matches": ["http://*/*", "https://*/*"],
        "js": ["./content/contentScript.js"]
      }
    ],
    "icons": {
      "16": "public/16.png",
      "48": "public/48.png",
      "128": "public/128.png"
    }
  }

 

contentScript는 ES6모델을 지원하지 않기 때문에, import와 export가 지원이 안되는데, 이때메 컴포넌트별로 나누어 작업하려면 웹팩을 이용해서 import된 파일을 빌드시켜서 해당 dist를 로드시켜야한다.

    const infoWindow = document.createElement('div');
    infoWindow.id = 'infoWindow';
    infoWindow.style.width = '300px';
    infoWindow.style.height = '500px';
    infoWindow.style.position = 'absolute';
    infoWindow.style.top = '140px';
    infoWindow.style.left = '50px';
    infoWindow.style.backgroundColor = 'lightgray';
    infoWindow.style.border = '1px solid gray';
    infoWindow.style.zIndex = '1001';
    infoWindow.style.padding = '10px';
    infoWindow.innerHTML = `
    <div style="position: absolute; top: 1px; right: 3px; cursor: pointer;">
        &#10005;
    </div>
    <p style="margin-top: 13px; margin-bottom: 17px;">연결상태: 양호</p>
    <p style="margin-top: 13px; margin-bottom: 17px;">졸음상태: 0회, (00:00:00)</p>
    <p style="margin-top: 13px; margin-bottom: 17px;">자리이탈: 0회, (00:00:00)</p>
    <p style="margin-top: 13px; margin-bottom: 17px;">녹화여부: 허용</p>
    <p style="margin-top: 13px; margin-bottom: 17px;">캠화면:</p>
    `;

 

contentScript로 내부기능, 비기능을 전부 작성해야하기 때문에, 자바스크립트에서 HTML을 작성해야했다. React와 Typescript로 작성된 보일러플레이트를 사용하면 웹팩 등 설정들이 다 되어있었는데, 그 코드는 생각보다 나와의 개발스타일도 다르고 빌드과정을 이해하기에는 시간이 없을 것 같아서 바닐라로 처음부터 짜기로 하였다.

if (!isActive) {
        const scriptButton = Array.from(document.querySelectorAll('.css-zl1inp')).find(li => {
            const button = li.querySelector('button');
            return (button && button.getAttribute('title') === '스크립트') || (button && button.getAttribute('title') === '성장 로그');
        });

        if (scriptButton) {
            const li = document.createElement('li');
            li.className = 'css-zl1inp';
            li.id = 'learningAssistantIcon';
            li.innerHTML = `
                <button class="mantine-UnstyledButton-root mantine-Button-root mantine-syxma7" type="button">
                    <div class="mantine-1yjkc96 mantine-Button-inner">
                        <span class="mantine-1vgkxjh mantine-Button-label">
                            <img src="https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw6E6e%2FbtsGRJCy10B%2FDorSShP9f3AJjKRGQnCAZk%2Fimg.png">
                            <p class="mantine-Text-root mantine-qjo01i">학습 보조</p>
                        </span>
                    </div>
                </button>
            `;

 

인프런의 무료강의와 유료강의의 사이드바의 아이콘 수가 다르기 때문에 OR로 지정해주고 해당 아이콘 밑에 학습 보조라는 새로운 아이콘을 삽입시켜주었다.

이제 사용자의 졸음, 자리이탈, 영상 중간에 퀴즈를 정중앙에 나오게 하기 등의 기능을 익스텐션에서 개발하고 팀원들이 따로 개발한 웹페이지에선 사용자들이 퀴즈를 만들 수 있는 기능을 제공할 예정이다. 영상처리모델은 Mediapipe가 정확도나 속도면에서 매우 뛰어났기 때문에 Mediapipe의 landmarker을 채택할 것 같다.

 

728x90

+ Recent posts