Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/rules/typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ paths:
- 컴포넌트/모듈은 1 파일 1 책임.
- **LMS 스크래핑은 DOMParser 기반**(API 아님). fetch 로직은 `src/lib/fetchCourseData.ts` + 개별 모듈(`fetchVodAttendance.ts`, `fetchAssign.ts`, `fetchQuiz.ts` 등)에 둔다.
- 중복 제거는 **키 생성기**(`makeVodKey`, `makeAssignKey`, `makeQuizKey`)를 거친다 — 키 불일치로 중복이 새지 않도록.
- content script UI는 **Shadow DOM**으로 격리(`src/lib/ShadowRootContext.tsx` 컨텍스트 경유).
- background ↔ content는 chrome 메시지 패싱으로 통신(알람 스케줄링 등).
- content script UI는 **Shadow DOM**으로 격리(`src/popover/lib/ShadowRootContext.tsx` 컨텍스트 경유).
- background ↔ content는 chrome 메시지 패싱으로 통신(Google OAuth 토큰 발급 등).
- 사용자에게 보이는 문자열은 i18n(`react-i18next`)을 통하고, 기본 언어는 한국어.
11 changes: 5 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,18 +98,17 @@ To test the extension, load `dist/` as an unpacked extension in Chrome (`chrome:

## Architecture

**Three entry points:**
**Two entry points:**

1. **Content Script** (`src/content/index.tsx`) — Injects a popover dashboard and video player into the LMS pages using Shadow DOM for style isolation.
2. **Background Service Worker** (`src/background.ts`) — Handles Chrome alarm scheduling and notification creation via message passing.
3. **Options Page** (`src/option/index.tsx`, served from `option.html`) — HashRouter SPA with dashboard, VOD/assignment/quiz list pages, and color customization settings.
1. **Content Script** (`src/popover/index.tsx`) — Injects the dashboard, video player, course toggles, and course-status badges (`injectCourseStatus`) into the LMS pages using Shadow DOM for style isolation.
2. **Background Service Worker** (`src/background.ts`) — Brokers Google OAuth tokens via `chrome.identity` (message passing) and opens the docs site on install / toolbar-icon click.

**Data flow:** The extension scrapes raw HTML from LMS pages using DOMParser (not an API), orchestrated by `src/lib/fetchCourseData.ts` and individual fetch modules (`fetchVodAttendance.ts`, `fetchIndexPage.ts`, `fetchAssign.ts`, `fetchQuiz.ts`). Results are cached in Chrome storage with a 24-hour TTL. The main data hook is `src/hooks/useCourseData.tsx`.

**Key patterns:**

- Shadow DOM isolation for content script UI (context via `src/lib/ShadowRootContext.tsx`)
- Chrome message passing between content scripts and background worker for alarm scheduling
- Shadow DOM isolation for content script UI (context via `src/popover/lib/ShadowRootContext.tsx`)
- Chrome message passing between content script and background worker for OAuth token retrieval
- Deduplication via key generators (`makeVodKey`, `makeAssignKey`, `makeQuizKey`)
- Path alias: `@/` maps to `./src`

Expand Down
120 changes: 108 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,110 @@
<div align="center">
<h1>
돋부기
<div align="center"><a target="_blank" href="https://chromewebstore.google.com/detail/hsu-%EB%8F%8B%EB%B6%80%EA%B8%B0-%F0%9F%94%8E/fbhdnbombekihdhjcfiimiibfmikghch"><img alt="Static Badge" src="https://img.shields.io/badge/Chrome_Web_Store-v5.0.5-%234285F4?style=plastic&logo=chromewebstore&logoColor=white&labelColor=black" style="display:inline-block;"></a><!-- x-release-please-version -->
<img alt="Static Badge" src="https://img.shields.io/badge/license-Apache--2.0-%2300465B?style=plastic&labelColor=black" style="display:inline-block;">
<a target="_blank" href="https://www.youtube.com/watch?v=eOFc9TbMWVI">
<img alt="Static Badge" src="https://img.shields.io/badge/%EB%8D%B0%EB%AA%A8_%EB%B0%94%EB%A1%9C%EA%B0%80%EA%B8%B0-000000?style=plastic&logo=YouTube&logoColor=FFFFFF&label=YouTube&labelColor=FF0000">
</a>
<h2>돋부기</h2>

<a target="_blank" href="https://chromewebstore.google.com/detail/hsu-%EB%8F%8B%EB%B6%80%EA%B8%B0-%F0%9F%94%8E/fbhdnbombekihdhjcfiimiibfmikghch"><img alt="Chrome Web Store" src="https://img.shields.io/badge/Chrome_Web_Store-v5.0.5-%234285F4?style=plastic&logo=chromewebstore&logoColor=white&labelColor=black" style="display:inline-block;"></a><!-- x-release-please-version -->
<img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-%2300465B?style=plastic&labelColor=black" style="display:inline-block;">
<a target="_blank" href="https://www.youtube.com/watch?v=eOFc9TbMWVI"><img alt="YouTube" src="https://img.shields.io/badge/%EB%8D%B0%EB%AA%A8_%EB%B0%94%EB%A1%9C%EA%B0%80%EA%B8%B0-000000?style=plastic&logo=YouTube&logoColor=FFFFFF&label=YouTube&labelColor=FF0000"></a>

</div>
</h1>
</div>
<div align="center">
<img src="https://github.com/user-attachments/assets/879f1d30-d720-43db-839a-e3869d060fda" alt="thumbnail">
</div><br/><br/><br/>

> [!NOTE]
> 한성대학교 LMS는 강의, 과제, 퀴즈가 과목마다 흩어져 있어 무엇이 남았고 무엇이 급한지 한눈에 보기 어렵다. 마감을 놓치거나 미수강 강의를 뒤늦게 발견하는 일이 반복된다.
>
> **돋부기**는 LMS 곳곳의 온라인 강의, 과제, 퀴즈를 하나의 대시보드로 모아 마감 상태를 한눈에 보여 준다. 미수강 강의는 출석 인정 기준에 맞춰 자동으로 이어 재생하고, 마감 일정은 Google 캘린더와 동기화한다.
>
> **학생은 흩어진 학습 정보를 한 곳에서 관리하고 마감을 놓치지 않을 수 있다.**

<br><br>

## 주요 기능

#### 할 일 대시보드

흩어진 온라인 강의, 과제, 퀴즈를 한 화면에 모아 마감 상태를 색으로 구분

- 과목을 넘나들지 않고 남은 활동과 제출 여부를 한눈에 확인
- 마감이 임박한 항목을 색상으로 강조

#### 자동 연속 재생

미수강 온라인 강의를 출석 인정 기준에 맞춰 자동으로 이어 재생

- 배속 없이 원래 속도(1배속)로 재생해 출석 인정 기준을 정상 충족
- 강의를 일일이 열지 않고 연속으로 수강

#### Google 캘린더 연동

과제, 퀴즈 마감일을 Google 캘린더에 자동 등록

- 인증 정보는 로컬에만 저장되며 외부로 전송되지 않음
- 평소 쓰던 캘린더에서 마감 일정을 함께 관리

#### 강의 페이지 배지

LMS 강의 페이지에서 각 활동의 출석, 제출 상태를 배지로 표시

> [!TIP]
> 강의 페이지를 열면 각 활동 옆에 출석·제출 상태 배지가 함께 표시돼, 대시보드를 열지 않고도 진행 상황을 확인할 수 있다
Comment thread
6-keem marked this conversation as resolved.

<br><br>

## 설치

#### 사용자

[Chrome 웹 스토어](https://chromewebstore.google.com/detail/hsu-%EB%8F%8B%EB%B6%80%EA%B8%B0-%F0%9F%94%8E/fbhdnbombekihdhjcfiimiibfmikghch)에서 설치한다.

#### 개발자 (로컬 빌드)

```bash
npm install
npm run build
```

`chrome://extensions`에서 개발자 모드를 켜고 빌드된 `dist/` 폴더를 **압축해제된 확장 프로그램으로 로드**한다. 자세한 개발 환경과 작업 절차는 [CONTRIBUTING.md](./CONTRIBUTING.md)를 참고한다.
Comment thread
6-keem marked this conversation as resolved.

<br><br>

## 기술 스택

![](https://go-skill-icons.vercel.app/api/icons?i=react,typescript,vite,tailwindcss&perline=12&theme=dark)

#### Frontend

- React 18 + TypeScript
- Vite + [@crxjs/vite-plugin](https://github.com/crxjs/chrome-extension-tools) (Manifest V3)
- shadcn/ui (Radix primitives) + Tailwind CSS
- framer-motion

#### Extension (진입점 2개)

- Content Script (`src/popover/index.tsx`) — Shadow DOM 기반 대시보드·비디오 플레이어·강의 상태 배지를 LMS 페이지에 주입
- Background Service Worker (`src/background.ts`) — `chrome.identity`로 Google OAuth 토큰 중개, 설치·아이콘 클릭 시 문서 사이트 열기

> [!NOTE]
> LMS API가 아니라 페이지 HTML을 DOMParser로 스크래핑해 데이터를 수집하며, 결과는 Chrome 스토리지에 24시간 TTL로 캐시한다.

<br><br>
Comment thread
6-keem marked this conversation as resolved.

## 문서

사용 설명서, FAQ, 개인정보 처리방침은 문서 사이트에서 확인할 수 있다.

- [문서 사이트](https://hs-shell.github.io/dotbugi)
- [개인정보 처리방침](https://hs-shell.github.io/dotbugi/privacy)
- [이용약관](https://hs-shell.github.io/dotbugi/terms)

<br><br>

## 기여

이 프로젝트는 **이슈 우선** 정책을 따른다. 모든 변경은 이슈를 먼저 등록하고 PR에서 참조해야 한다(`1 PR = 1 Issue`).

- 시작하기 전에 [CONTRIBUTING.md](./CONTRIBUTING.md)와 [행동 강령](./CODE_OF_CONDUCT.md)을 읽어 주세요.
- 커밋과 PR 제목은 [Conventional Commits](https://www.conventionalcommits.org/)를 따른다.

<br><br>

## 라이선스

[Apache-2.0](./LICENSE)
Loading