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
7 changes: 7 additions & 0 deletions docs/en/updates/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Update Log

## v5.0.1

- Fixed bug where courses were not auto-tracked on first install/update
- Auto-track newly added courses, auto-remove courses no longer in the list
- Fixed incorrect current week highlight on past semester courses
- Extension icon click now opens docs page based on user language setting

## v5.0.0

- Multi-language support (Korean/English/Japanese/Chinese)
Expand Down
7 changes: 7 additions & 0 deletions docs/ja/updates/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# アップデートログ

## v5.0.1

- 初回インストール/アップデート時に科目が自動トラッキングされないバグを修正
- 新しく追加された科目の自動トラッキング、削除された科目の自動除去
- 過去学期の講義で現在の週として誤って表示されるバグを修正
- 拡張機能アイコンクリック時にユーザー言語設定に基づくドキュメントページへ移動

## v5.0.0

- 多言語対応(韓国語/英語/日本語/中国語)
Expand Down
7 changes: 7 additions & 0 deletions docs/updates/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# 업데이트 로그

## v5.0.1

- 첫 설치/업데이트 시 과목 자동 트래킹이 안 되던 버그 수정
- 새로 추가된 과목 자동 트래킹, 사라진 과목 자동 제거
- 이전 학기 강의에서 현재 주차로 잘못 표시되는 버그 수정
- 확장 프로그램 아이콘 클릭 시 사용자 언어 설정 기반 문서 페이지 이동

## v5.0.0

- 다국어 지원 (한국어/영어/일본어/중국어)
Expand Down
7 changes: 7 additions & 0 deletions docs/zh/updates/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# 更新日志

## v5.0.1

- 修复首次安装/更新时科目未自动跟踪的问题
- 自动跟踪新增科目,自动移除已不存在的科目
- 修复过去学期课程错误显示为当前周次的问题
- 点击扩展图标时根据用户语言设置跳转到对应文档页面

## v5.0.0

- 多语言支持(韩语/英语/日语/中文)
Expand Down
8 changes: 7 additions & 1 deletion src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,11 @@ chrome.runtime.onInstalled.addListener((details) => {
});

chrome.action.onClicked.addListener(() => {
chrome.runtime.openOptionsPage();
const BASE_URL = 'https://hs-shell.github.io/dotbugi/';
const LANG_PATHS: Record<string, string> = { en: 'en/', ja: 'ja/', zh: 'zh/' };

chrome.storage.local.get('language', (result) => {
const langPath = LANG_PATHS[result.language] ?? '';
chrome.tabs.create({ url: BASE_URL + langPath });
});
});
44 changes: 33 additions & 11 deletions src/hooks/useGetCourses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,39 @@ export const useGetCourses = () => {
saveDataToStorage('courses', JSON.stringify(courses));

loadDataFromStorage<string[]>('trackedCourseIds', (savedIds) => {
if (savedIds) {
// 빈 배열([])도 유효한 저장 상태로 취급 (사용자가 의도적으로 모두 해제한 경우)
setTrackedCourseIdsState(savedIds);
} else {
// 최초 사용: 비교과(커뮤니티)와 이전 학기 과목 제외하고 전부 트래킹
const defaultIds = courses
.filter((c) => !c.isCommunity && c.isCurrentSemester !== false)
.map((c) => c.courseId);
setTrackedCourseIdsState(defaultIds);
saveDataToStorage('trackedCourseIds', defaultIds);
}
if (!savedIds && courses.length === 0) return;

loadDataFromStorage<string[]>('knownCourseIds', (knownIds) => {
const knownSet = new Set(knownIds ?? []);

if (savedIds) {
const currentCourseIds = new Set(courses.map((c) => c.courseId));
// 현재 강의 목록에 없는 과목은 추적에서 제거
const filtered = savedIds.filter((id) => currentCourseIds.has(id));
// 새로 추가된 과목 자동 추가
const newTrackableIds = courses
.filter((c) => !knownSet.has(c.courseId) && !c.isCommunity)
.map((c) => c.courseId);
const mergedIds = [...filtered, ...newTrackableIds];
setTrackedCourseIdsState(mergedIds);
if (filtered.length !== savedIds.length || newTrackableIds.length > 0) {
saveDataToStorage('trackedCourseIds', mergedIds);
}
} else if (courses.length > 0) {
// 최초 사용: 비교과(커뮤니티)와 이전 학기 과목 제외하고 전부 트래킹
const defaultIds = courses
.filter((c) => !c.isCommunity)
.map((c) => c.courseId);
setTrackedCourseIdsState(defaultIds);
saveDataToStorage('trackedCourseIds', defaultIds);
}

// 현재 과목 목록을 knownCourseIds로 저장
if (courses.length > 0) {
const updatedKnown = [...new Set([...knownSet, ...courses.map((c) => c.courseId)])];
saveDataToStorage('knownCourseIds', updatedKnown);
}
});
});
};

Expand Down
3 changes: 3 additions & 0 deletions src/lib/courseStatus/currentWeek.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ function parseSectionDateRange(text: string, year: number): { start: Date; end:
// ── Highlight & scroll button ───────────────────────────────────────

export function highlightCurrentWeek() {
// .course_box_current는 현재 학기 강의에서만 존재
if (!document.querySelector('.course_box_current')) return;

const now = new Date();
const sections = document.querySelectorAll('li[id^="section-"]');
const fallbackYear = inferYear(sections);
Expand Down
32 changes: 28 additions & 4 deletions src/lib/injectCourseToggles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,37 @@ export function injectCourseToggles() {
saveDataToStorage('communityIds', communityIds);

loadDataFromStorage<string[]>('trackedCourseIds', (savedIds) => {
const trackedIds = savedIds ?? allCourses
.filter((c) => !c.isCommunity && c.isCurrentSemester !== false)
.map((c) => c.courseId);
loadDataFromStorage<string[]>('knownCourseIds', (knownIds) => {
const knownSet = new Set(knownIds ?? []);

const currentCourseIds = new Set(allCourses.map((c) => c.courseId));

let trackedIds: string[];
let changed = false;
if (savedIds) {
// 현재 강의 목록에 없는 과목은 추적에서 제거
const filtered = savedIds.filter((id) => currentCourseIds.has(id));
// 새로 추가된 과목 자동 추가
const newTrackableIds = allCourses
.filter((c) => !knownSet.has(c.courseId) && !c.isCommunity)
.map((c) => c.courseId);
trackedIds = [...filtered, ...newTrackableIds];
changed = filtered.length !== savedIds.length || newTrackableIds.length > 0;
} else {
trackedIds = allCourses
.filter((c) => !c.isCommunity)
.map((c) => c.courseId);
changed = true;
}

if (!savedIds) {
if (changed) {
saveDataToStorage('trackedCourseIds', trackedIds);
}

// knownCourseIds 업데이트
const updatedKnown = [...new Set([...knownSet, ...currentCourseIds])];
saveDataToStorage('knownCourseIds', updatedKnown);

const trackedSet = new Set(trackedIds);
const listItems = document.querySelectorAll('.my-course-lists > li');

Expand Down Expand Up @@ -48,6 +71,7 @@ export function injectCourseToggles() {
courseBox.appendChild(toggle);
}
});
});
});
}

Expand Down
3 changes: 1 addition & 2 deletions src/lib/parseCourses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ function parseCourseFromElement(li: Element): CourseBase | null {
if (!courseId || !courseTitle || !prof) return null;

const isCommunity = li.classList.contains(COMMUNITY_CLASS);
const isCurrentSemester = isCommunity || !!li.querySelector('.course_box_current');
return { courseId, courseTitle, prof, isCommunity, isCurrentSemester };
return { courseId, courseTitle, prof, isCommunity };
}

export function parseCoursesFromDOM(): CourseBase[] {
Expand Down
1 change: 0 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export type CourseBase = {
courseTitle: string;
prof: string;
isCommunity?: boolean;
isCurrentSemester?: boolean;
};

export type Vod = CourseBase & {
Expand Down
Loading