Skip to content

Commit

Permalink
Merge branch 'main' into preact
Browse files Browse the repository at this point in the history
  • Loading branch information
AsakuraMizu committed Sep 22, 2023
2 parents d9640cb + 54bce5c commit 71ba2db
Show file tree
Hide file tree
Showing 31 changed files with 1,048 additions and 790 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,15 @@
# Changelog

## 4.6.1

- Change i18n backend to [Lingui](https://lingui.dev/) and support language switching ([#134](https://github.com/Harry-Chen/Learn-Helper/issues/134))
- FIX csrf injection ([#135](https://github.com/Harry-Chen/Learn-Helper/issues/135))
- Try to FIX PKU course compatibility ([#139](https://github.com/Harry-Chen/Learn-Helper/issues/139))
- FIX open in new window ([#140](https://github.com/Harry-Chen/Learn-Helper/issues/140))
- FIX card list scroll height reset after open item ([AsakuraMizu/Learn-Helper#2](https://github.com/AsakuraMizu/Learn-Helper/issues/2))
- FIX card filter not reset after switching semester ([AsakuraMizu/Learn-Helper#3](https://github.com/AsakuraMizu/Learn-Helper/issues/3))
- Remove fontawesome and use [unplugin-icons](https://github.com/unplugin/unplugin-icons) to render icons, reduce package size

## v4.6.0

(Contributed by @AsakuraMizu as part of OSPP'2023 project)
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG_ZH.md
@@ -1,5 +1,15 @@
# 更新记录

## 4.6.1

- [FIX] 更换 i18n 后端,支持切换语言 ([#134](https://github.com/Harry-Chen/Learn-Helper/issues/134))
- [FIX] csrf 注入失败导致无法提交作业等问题 ([#135](https://github.com/Harry-Chen/Learn-Helper/issues/135))
- [FIX] 尝试修复北大课程兼容 ([#139](https://github.com/Harry-Chen/Learn-Helper/issues/139))
- [FIX] 无法正确在新窗口打开 ([#140](https://github.com/Harry-Chen/Learn-Helper/issues/140))
- [FIX] 打开项目后滚动重置 ([AsakuraMizu/Learn-Helper#2](https://github.com/AsakuraMizu/Learn-Helper/issues/2))
- [FIX] 切换学期后过滤未重置 ([AsakuraMizu/Learn-Helper#3](https://github.com/AsakuraMizu/Learn-Helper/issues/3))
- [FIX] 移除 fontawesome,使用 [unplugin-icons](https://github.com/unplugin/unplugin-icons) 渲染图标,减小包体积

## 4.6.0

(由 @AsakuraMizu 作为 2023 年 OSPP 项目贡献)
Expand Down
4 changes: 4 additions & 0 deletions README.md
Expand Up @@ -79,6 +79,10 @@ yarn serve:chrome

Due to technical restrictions, dev mode works only for chrome.

### Auto login in development

Copy `.env.development` to `.env.development.local` and fill in your username & password to login automatically on start.

## Revision History

See [CHANGELOG.md](https://github.com/Harry-Chen/Learn-Helper/blob/master/CHANGELOG.md).
7 changes: 4 additions & 3 deletions package.json
Expand Up @@ -27,6 +27,8 @@
"@preact/preset-vite": "^2.5.0",
"@samrum/vite-plugin-web-extension": "^5.0.0",
"@types/babel__core": "^7.20.2",
"@svgr/core": "^8.1.0",
"@svgr/plugin-jsx": "^8.1.0",
"@types/lodash": "^4.14.195",
"@types/node": "^18.11.11",
"@types/randomstring": "^1.1.8",
Expand All @@ -48,16 +50,15 @@
"rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.19.4",
"typescript": "^5.1.6",
"unplugin-icons": "^0.17.0",
"vite": "^4.4.4",
"vite-plugin-zip-pack": "^1.0.6",
"web-ext": "^7.6.2"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@fortawesome/fontawesome-svg-core": "^6.4.0",
"@fortawesome/free-solid-svg-icons": "^6.4.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@iconify-json/fa6-solid": "^1.1.15",
"@lingui/core": "^4.5.0",
"@lingui/macro": "^4.5.0",
"@lingui/react": "^4.5.0",
Expand Down
87 changes: 43 additions & 44 deletions src/components/App.tsx
@@ -1,7 +1,7 @@
import React, { useState, type ErrorInfo, useRef, useEffect } from 'react';
import { ErrorBoundary, type FallbackProps } from 'react-error-boundary';
import classnames from 'classnames';
import { msg, Trans, t } from '@lingui/macro';
import { Trans, t } from '@lingui/macro';
import { useLingui } from '@lingui/react';

import {
Expand All @@ -22,9 +22,18 @@ import {
ListItemIcon,
ListItemText,
} from '@mui/material';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { bindMenu, bindTrigger, usePopupState } from 'material-ui-popup-state/hooks';

import IconLanguage from '~icons/fa6-solid/language';
import IconCircleHalfStroke from '~icons/fa6-solid/circle-half-stroke';
import IconSun from '~icons/fa6-solid/sun';
import IconMoon from '~icons/fa6-solid/moon';
import IconBars from '~icons/fa6-solid/bars';
import IconAngleLeft from '~icons/fa6-solid/angle-left';
import IconStarOfLife from '~icons/fa6-solid/star-of-life';
import IconFilter from '~icons/fa6-solid/filter';
import IconXmark from '~icons/fa6-solid/xmark';

import { useAppDispatch, useAppSelector } from '../redux/hooks';
import {
setTitleFilter,
Expand All @@ -34,6 +43,7 @@ import {
tryLoginSilently,
syncLanguage,
} from '../redux/actions';
import { selectCardListTitle } from '../redux/selectors';
import { formatSemester } from '../utils/format';
import { removeStoredCredential } from '../utils/storage';
import { interceptCsrfRequest } from '../utils/csrf';
Expand Down Expand Up @@ -71,11 +81,11 @@ const LanguageSwitcher = () => {
<>
<IconButton
color="inherit"
aria-label="Set color mode"
aria-label="Set language"
size="large"
{...bindTrigger(popupState)}
>
<FontAwesomeIcon icon="language" />
<IconLanguage />
</IconButton>
<Menu {...bindMenu(popupState)}>
<MenuItem key="zh" selected={i18n.locale === 'zh'} onClick={() => handle('zh')}>
Expand Down Expand Up @@ -105,28 +115,28 @@ const ColorModeSwitcher = () => {
size="large"
{...bindTrigger(popupState)}
>
<FontAwesomeIcon icon="circle-half-stroke" />
<IconCircleHalfStroke />
</IconButton>
<Menu {...bindMenu(popupState)}>
<MenuItem key="system" selected={mode === 'system'} onClick={() => handle('system')}>
<ListItemIcon>
<FontAwesomeIcon icon="circle-half-stroke" />
<IconCircleHalfStroke />
</ListItemIcon>
<ListItemText>
<Trans>跟随系统</Trans>
</ListItemText>
</MenuItem>
<MenuItem key="light" selected={mode === 'light'} onClick={() => handle('light')}>
<ListItemIcon>
<FontAwesomeIcon icon="sun" />
<IconSun />
</ListItemIcon>
<ListItemText>
<Trans></Trans>
</ListItemText>
</MenuItem>
<MenuItem key="dark" selected={mode === 'dark'} onClick={() => handle('dark')}>
<ListItemIcon>
<FontAwesomeIcon icon="moon" />
<IconMoon />
</ListItemIcon>
<ListItemText>
<Trans></Trans>
Expand All @@ -152,7 +162,7 @@ const AppBar = () => {
onClick={openSidebar}
size="large"
>
<FontAwesomeIcon icon="bars" />
<IconBars />
</IconButton>
<Typography component="div" sx={{ flexGrow: 1 }}></Typography>
<LanguageSwitcher />
Expand All @@ -167,9 +177,7 @@ const AppDrawer = () => {
const dispatch = useAppDispatch();

const paneHidden = useAppSelector((state) => state.ui.paneHidden);
const cardListTitle = useAppSelector((state) =>
state.helper.loggedIn ? state.ui.cardListTitle : [msg`加载中...`],
);
const cardListTitle = useAppSelector(selectCardListTitle);
const semesterTitle = useAppSelector((state) => formatSemester(state.data.semester));
const isLatestSemester = useAppSelector(
(state) => state.data.semester.id === state.data.fetchedSemester.id,
Expand Down Expand Up @@ -201,7 +209,7 @@ const AppDrawer = () => {
onClick={() => dispatch(togglePaneHidden(true))}
size="large"
>
<FontAwesomeIcon icon="angle-left" />
<IconAngleLeft />
</IconButton>
<Typography variant="subtitle1" className={styles.sidebar_master_title} noWrap>
{semesterTitle}
Expand All @@ -211,9 +219,9 @@ const AppDrawer = () => {
<IconButton
className={styles.sidebar_master_notify_icon}
onClick={() => dispatch(toggleChangeSemesterDialog(true))}
size="large"
size="small"
>
<FontAwesomeIcon icon="star-of-life" />
<IconStarOfLife />
</IconButton>
</Tooltip>
)}
Expand All @@ -233,36 +241,27 @@ const AppDrawer = () => {
onClick={toggleFilter}
size="large"
>
<FontAwesomeIcon
icon="filter"
className={classnames(styles.filter_icon, {
[styles.filter_icon_shown]: !filterShown,
})}
/>
<FontAwesomeIcon
icon="times"
className={classnames(styles.filter_icon, {
[styles.filter_icon_shown]: filterShown,
})}
/>
{filterShown ? <IconXmark /> : <IconFilter />}
</IconButton>
<div className={styles.filter_input}>
<InputBase
inputRef={inputRef}
className={styles.filter_input_inner}
placeholder={t`筛选`}
value={filter}
onChange={(ev) => {
setFilter(ev.target.value);
dispatch(setTitleFilter(ev.target.value.trim() || undefined));
}}
inputProps={{
onBlur: () => {
if (!filterShown && filter === '') setFilterShown(false);
},
}}
/>
</div>
{filterShown && (
<div>
<InputBase
inputRef={inputRef}
className={styles.filter_input_inner}
placeholder={t`筛选`}
value={filter}
onChange={(ev) => {
setFilter(ev.target.value);
dispatch(setTitleFilter(ev.target.value.trim() || undefined));
}}
inputProps={{
onBlur: () => {
if (!filterShown && filter === '') setFilterShown(false);
},
}}
/>
</div>
)}
</div>
</Toolbar>
</div>
Expand Down
51 changes: 29 additions & 22 deletions src/components/ContentCard.tsx
Expand Up @@ -15,7 +15,16 @@ import {
Avatar,
Tooltip,
} from '@mui/material';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';

import IconCheck from '~icons/fa6-solid/check';
import IconStar from '~icons/fa6-solid/star';
import IconClipboard from '~icons/fa6-solid/clipboard';
import IconClipboardCheck from '~icons/fa6-solid/clipboard-check';
import IconTrash from '~icons/fa6-solid/trash';
import IconTrashCan from '~icons/fa6-solid/trash-can';
import IconUpload from '~icons/fa6-solid/upload';
import IconDownload from '~icons/fa6-solid/download';
import IconPaperclip from '~icons/fa6-solid/paperclip';

import styles from '../css/card.module.css';
import type { CardProps } from '../types/ui';
Expand All @@ -28,7 +37,7 @@ import {
setDetailUrl,
} from '../redux/actions';
import { useAppDispatch } from '../redux/hooks';
import { formatDate } from '../utils/format';
import { formatDate, formatHomeworkGradeLevel } from '../utils/format';
import { initiateFileDownload } from '../utils/download';

const ContentCard = ({ content }: CardProps) => {
Expand Down Expand Up @@ -63,13 +72,11 @@ const ContentCard = ({ content }: CardProps) => {
<Chip
avatar={
<Avatar className={styles.card_func_icon}>
<FontAwesomeIcon
icon={
content.type === ContentType.HOMEWORK && content.submitted
? 'check'
: COURSE_MAIN_FUNC[content.type].icon
}
/>
{content.type === ContentType.HOMEWORK && content.submitted ? (
<IconCheck />
) : (
COURSE_MAIN_FUNC[content.type].icon
)}
</Avatar>
}
label={
Expand Down Expand Up @@ -118,7 +125,7 @@ const ContentCard = ({ content }: CardProps) => {
(content.graded
? (content.grade
? content.gradeLevel
? content.gradeLevel
? _(formatHomeworkGradeLevel(content.gradeLevel))
: t`${content.grade}分`
: t`无评分`) + t`(${content.graderName ?? ''})`
: t`未批阅`)
Expand Down Expand Up @@ -153,9 +160,9 @@ const ContentCard = ({ content }: CardProps) => {
ev.stopPropagation();
}}
onMouseDown={(ev) => ev.stopPropagation()}
size="large"
size="small"
>
<FontAwesomeIcon icon="star" />
<IconStar />
</IconButton>
</Tooltip>
<Tooltip title={content.hasRead ? t`标记为未读` : t`标记为已读`}>
Expand All @@ -170,9 +177,9 @@ const ContentCard = ({ content }: CardProps) => {
ev.stopPropagation();
}}
onMouseDown={(ev) => ev.stopPropagation()}
size="large"
size="small"
>
<FontAwesomeIcon icon={content.hasRead ? 'clipboard' : 'clipboard-check'} />
{content.hasRead ? <IconClipboard /> : <IconClipboardCheck />}
</IconButton>
</Tooltip>
<Tooltip title={content.ignored ? t`取消忽略此项` : t`忽略此项`}>
Expand All @@ -191,9 +198,9 @@ const ContentCard = ({ content }: CardProps) => {
ev.stopPropagation();
}}
onMouseDown={(ev) => ev.stopPropagation()}
size="large"
size="small"
>
<FontAwesomeIcon icon={content.ignored ? 'trash' : 'trash-alt'} />
{content.ignored ? <IconTrash /> : <IconTrashCan />}
</IconButton>
</Tooltip>
{content.type === ContentType.HOMEWORK && (
Expand All @@ -207,9 +214,9 @@ const ContentCard = ({ content }: CardProps) => {
ev.stopPropagation();
}}
onMouseDown={(ev) => ev.stopPropagation()}
size="large"
size="small"
>
<FontAwesomeIcon icon="upload" />
<IconUpload />
</IconButton>
</Tooltip>
)}
Expand All @@ -222,9 +229,9 @@ const ContentCard = ({ content }: CardProps) => {
onClick={() => {
initiateFileDownload(content.remoteFile.downloadUrl);
}}
size="large"
size="small"
>
<FontAwesomeIcon icon="download" />
<IconDownload />
</IconButton>
</Tooltip>
)}
Expand All @@ -239,9 +246,9 @@ const ContentCard = ({ content }: CardProps) => {
if (content.attachment)
initiateFileDownload(content.attachment.downloadUrl, content.attachment.name);
}}
size="large"
size="small"
>
<FontAwesomeIcon icon="paperclip" />
<IconPaperclip />
</IconButton>
</Tooltip>
)}
Expand Down

0 comments on commit 71ba2db

Please sign in to comment.