From b884327a53487f73d78eeea3cb10f71bb5506fed Mon Sep 17 00:00:00 2001 From: Steven Date: Sun, 4 Sep 2022 06:48:19 +0800 Subject: [PATCH] chore: update eslint rules --- web/.eslintrc.json | 1 - web/src/components/AboutSiteDialog.tsx | 2 +- web/src/components/ArchivedMemoDialog.tsx | 2 +- web/src/components/ChangePasswordDialog.tsx | 2 +- web/src/components/GitHubBadge.tsx | 4 +- web/src/components/MemoEditor.tsx | 4 +- web/src/components/MemoFilter.tsx | 4 +- web/src/components/MemoList.tsx | 4 +- web/src/components/MemosHeader.tsx | 4 +- web/src/components/ResourcesDialog.tsx | 2 +- web/src/components/SearchBar.tsx | 4 +- web/src/components/SettingDialog.tsx | 2 +- web/src/components/Settings/MemberSection.tsx | 4 +- .../components/Settings/MyAccountSection.tsx | 4 +- .../Settings/PreferencesSection.tsx | 4 +- web/src/components/ShortcutList.tsx | 4 +- web/src/components/Sidebar.tsx | 4 +- web/src/components/TagList.tsx | 4 +- web/src/components/Toast.tsx | 79 ++++++++++--------- web/src/components/UsageHeatMap.tsx | 4 +- web/src/components/UserBanner.tsx | 4 +- web/src/helpers/consts.ts | 3 - web/src/less/shortcut-list.less | 8 +- web/src/less/toast.less | 1 + web/src/pages/Auth.tsx | 4 +- 25 files changed, 69 insertions(+), 93 deletions(-) diff --git a/web/.eslintrc.json b/web/.eslintrc.json index 39b2d4c4..4d4bc935 100644 --- a/web/.eslintrc.json +++ b/web/.eslintrc.json @@ -21,7 +21,6 @@ "endOfLine": "auto" } ], - "@typescript-eslint/no-empty-interface": ["off"], "@typescript-eslint/no-explicit-any": ["off"], "react/react-in-jsx-scope": "off" }, diff --git a/web/src/components/AboutSiteDialog.tsx b/web/src/components/AboutSiteDialog.tsx index 47591922..6217c3b8 100644 --- a/web/src/components/AboutSiteDialog.tsx +++ b/web/src/components/AboutSiteDialog.tsx @@ -7,7 +7,7 @@ import { generateDialog } from "./Dialog"; import GitHubBadge from "./GitHubBadge"; import "../less/about-site-dialog.less"; -interface Props extends DialogProps {} +type Props = DialogProps; const AboutSiteDialog: React.FC = ({ destroy }: Props) => { const { t } = useI18n(); diff --git a/web/src/components/ArchivedMemoDialog.tsx b/web/src/components/ArchivedMemoDialog.tsx index 0d296dbc..7331bd09 100644 --- a/web/src/components/ArchivedMemoDialog.tsx +++ b/web/src/components/ArchivedMemoDialog.tsx @@ -8,7 +8,7 @@ import toastHelper from "./Toast"; import ArchivedMemo from "./ArchivedMemo"; import "../less/archived-memo-dialog.less"; -interface Props extends DialogProps {} +type Props = DialogProps; const ArchivedMemoDialog: React.FC = (props: Props) => { const { destroy } = props; diff --git a/web/src/components/ChangePasswordDialog.tsx b/web/src/components/ChangePasswordDialog.tsx index a13ef701..988bb7d0 100644 --- a/web/src/components/ChangePasswordDialog.tsx +++ b/web/src/components/ChangePasswordDialog.tsx @@ -14,7 +14,7 @@ const validateConfig: ValidatorConfig = { noChinese: true, }; -interface Props extends DialogProps {} +type Props = DialogProps; const ChangePasswordDialog: React.FC = ({ destroy }: Props) => { const { t } = useI18n(); diff --git a/web/src/components/GitHubBadge.tsx b/web/src/components/GitHubBadge.tsx index 37331c89..327be363 100644 --- a/web/src/components/GitHubBadge.tsx +++ b/web/src/components/GitHubBadge.tsx @@ -3,9 +3,7 @@ import * as api from "../helpers/api"; import Icon from "./Icon"; import "../less/github-badge.less"; -interface Props {} - -const GitHubBadge: React.FC = () => { +const GitHubBadge = () => { const [starCount, setStarCount] = useState(0); useEffect(() => { diff --git a/web/src/components/MemoEditor.tsx b/web/src/components/MemoEditor.tsx index 5e2ed62d..7c12810f 100644 --- a/web/src/components/MemoEditor.tsx +++ b/web/src/components/MemoEditor.tsx @@ -9,14 +9,12 @@ import toastHelper from "./Toast"; import Editor, { EditorRefActions } from "./Editor/Editor"; import "../less/memo-editor.less"; -interface Props {} - interface State { isUploadingResource: boolean; fullscreen: boolean; } -const MemoEditor: React.FC = () => { +const MemoEditor = () => { const { t, locale } = useI18n(); const user = useAppSelector((state) => state.user.user); const editorState = useAppSelector((state) => state.editor); diff --git a/web/src/components/MemoFilter.tsx b/web/src/components/MemoFilter.tsx index 429edc55..f0cd3c9b 100644 --- a/web/src/components/MemoFilter.tsx +++ b/web/src/components/MemoFilter.tsx @@ -4,9 +4,7 @@ import * as utils from "../helpers/utils"; import { getTextWithMemoType } from "../helpers/filter"; import "../less/memo-filter.less"; -interface FilterProps {} - -const MemoFilter: React.FC = () => { +const MemoFilter = () => { const query = useAppSelector((state) => state.location.query); useAppSelector((state) => state.shortcut.shortcuts); const { tag: tagQuery, duration, type: memoType, text: textQuery, shortcutId } = query; diff --git a/web/src/components/MemoList.tsx b/web/src/components/MemoList.tsx index 707dbd5a..a0da2835 100644 --- a/web/src/components/MemoList.tsx +++ b/web/src/components/MemoList.tsx @@ -10,9 +10,7 @@ import Only from "./common/OnlyWhen"; import Memo from "./Memo"; import "../less/memo-list.less"; -interface Props {} - -const MemoList: React.FC = () => { +const MemoList = () => { const { t } = useI18n(); const query = useAppSelector((state) => state.location.query); const { memos, isFetching } = useAppSelector((state) => state.memo); diff --git a/web/src/components/MemosHeader.tsx b/web/src/components/MemosHeader.tsx index 9198f7f4..892b5fb5 100644 --- a/web/src/components/MemosHeader.tsx +++ b/web/src/components/MemosHeader.tsx @@ -8,9 +8,7 @@ import "../less/memos-header.less"; let prevRequestTimestamp = Date.now(); -interface Props {} - -const MemosHeader: React.FC = () => { +const MemosHeader = () => { const query = useAppSelector((state) => state.location.query); const shortcuts = useAppSelector((state) => state.shortcut.shortcuts); const [titleText, setTitleText] = useState("MEMOS"); diff --git a/web/src/components/ResourcesDialog.tsx b/web/src/components/ResourcesDialog.tsx index 58518634..21413c29 100644 --- a/web/src/components/ResourcesDialog.tsx +++ b/web/src/components/ResourcesDialog.tsx @@ -11,7 +11,7 @@ import Icon from "./Icon"; import toastHelper from "./Toast"; import "../less/resources-dialog.less"; -interface Props extends DialogProps {} +type Props = DialogProps; interface State { resources: Resource[]; diff --git a/web/src/components/SearchBar.tsx b/web/src/components/SearchBar.tsx index b79f3e89..d14e000e 100644 --- a/web/src/components/SearchBar.tsx +++ b/web/src/components/SearchBar.tsx @@ -4,9 +4,7 @@ import { memoSpecialTypes } from "../helpers/filter"; import Icon from "./Icon"; import "../less/search-bar.less"; -interface Props {} - -const SearchBar: React.FC = () => { +const SearchBar = () => { const memoType = useAppSelector((state) => state.location.query?.type); const handleMemoTypeItemClick = (type: MemoSpecType | undefined) => { diff --git a/web/src/components/SettingDialog.tsx b/web/src/components/SettingDialog.tsx index 9248b534..7df9b92b 100644 --- a/web/src/components/SettingDialog.tsx +++ b/web/src/components/SettingDialog.tsx @@ -8,7 +8,7 @@ import PreferencesSection from "./Settings/PreferencesSection"; import MemberSection from "./Settings/MemberSection"; import "../less/setting-dialog.less"; -interface Props extends DialogProps {} +type Props = DialogProps; type SettingSection = "my-account" | "preferences" | "member"; diff --git a/web/src/components/Settings/MemberSection.tsx b/web/src/components/Settings/MemberSection.tsx index 9a79cec8..528fd5a1 100644 --- a/web/src/components/Settings/MemberSection.tsx +++ b/web/src/components/Settings/MemberSection.tsx @@ -9,14 +9,12 @@ import Dropdown from "../common/Dropdown"; import { showCommonDialog } from "../Dialog/CommonDialog"; import "../../less/settings/member-section.less"; -interface Props {} - interface State { createUserEmail: string; createUserPassword: string; } -const PreferencesSection: React.FC = () => { +const PreferencesSection = () => { const { t } = useI18n(); const currentUser = useAppSelector((state) => state.user.user); const [state, setState] = useState({ diff --git a/web/src/components/Settings/MyAccountSection.tsx b/web/src/components/Settings/MyAccountSection.tsx index 2102f0c9..801bcd80 100644 --- a/web/src/components/Settings/MyAccountSection.tsx +++ b/web/src/components/Settings/MyAccountSection.tsx @@ -15,9 +15,7 @@ const validateConfig: ValidatorConfig = { noChinese: true, }; -interface Props {} - -const MyAccountSection: React.FC = () => { +const MyAccountSection = () => { const { t } = useI18n(); const user = useAppSelector((state) => state.user.user as User); const [username, setUsername] = useState(user.name); diff --git a/web/src/components/Settings/PreferencesSection.tsx b/web/src/components/Settings/PreferencesSection.tsx index a2214249..10e1e8be 100644 --- a/web/src/components/Settings/PreferencesSection.tsx +++ b/web/src/components/Settings/PreferencesSection.tsx @@ -6,8 +6,6 @@ import Selector from "../common/Selector"; import BetaBadge from "../BetaBadge"; import "../../less/settings/preferences-section.less"; -interface Props {} - const localeSelectorItems = [ { text: "English", @@ -30,7 +28,7 @@ const editorFontStyleSelectorItems = [ }, ]; -const PreferencesSection: React.FC = () => { +const PreferencesSection = () => { const { t } = useI18n(); const { setting } = useAppSelector((state) => state.user.user as User); diff --git a/web/src/components/ShortcutList.tsx b/web/src/components/ShortcutList.tsx index b1a0e4b5..58dee81c 100644 --- a/web/src/components/ShortcutList.tsx +++ b/web/src/components/ShortcutList.tsx @@ -10,9 +10,7 @@ import toastHelper from "./Toast"; import showCreateShortcutDialog from "./CreateShortcutDialog"; import "../less/shortcut-list.less"; -interface Props {} - -const ShortcutList: React.FC = () => { +const ShortcutList = () => { const query = useAppSelector((state) => state.location.query); const shortcuts = useAppSelector((state) => state.shortcut.shortcuts); const loadingState = useLoading(); diff --git a/web/src/components/Sidebar.tsx b/web/src/components/Sidebar.tsx index 89943cf9..6d563891 100644 --- a/web/src/components/Sidebar.tsx +++ b/web/src/components/Sidebar.tsx @@ -12,9 +12,7 @@ import ShortcutList from "./ShortcutList"; import TagList from "./TagList"; import "../less/siderbar.less"; -interface Props {} - -const Sidebar: React.FC = () => { +const Sidebar = () => { const { t } = useI18n(); const handleMyAccountBtnClick = () => { diff --git a/web/src/components/TagList.tsx b/web/src/components/TagList.tsx index 7f655d57..87037ec1 100644 --- a/web/src/components/TagList.tsx +++ b/web/src/components/TagList.tsx @@ -14,9 +14,7 @@ interface Tag { subTags: Tag[]; } -interface Props {} - -const TagList: React.FC = () => { +const TagList = () => { const { t } = useI18n(); const { memos, tags: tagsText } = useAppSelector((state) => state.memo); const query = useAppSelector((state) => state.location.query); diff --git a/web/src/components/Toast.tsx b/web/src/components/Toast.tsx index 8e072752..e440d568 100644 --- a/web/src/components/Toast.tsx +++ b/web/src/components/Toast.tsx @@ -1,6 +1,5 @@ import { useEffect } from "react"; import { createRoot, Root } from "react-dom/client"; -import { TOAST_ANIMATION_DURATION } from "../helpers/consts"; import "../less/toast.less"; type ToastType = "normal" | "success" | "info" | "error"; @@ -36,42 +35,26 @@ const Toast: React.FC = (props: ToastItemProps) => { ); }; -class ToastHelper { - private shownToastAmount = 0; - private toastWrapper: HTMLDivElement; - private shownToastContainers: [Root, HTMLDivElement][] = []; +// toast animation duration. +const TOAST_ANIMATION_DURATION = 400; - constructor() { - const wrapperClassName = "toast-list-container"; - const tempDiv = document.createElement("div"); - tempDiv.className = wrapperClassName; - document.body.appendChild(tempDiv); - this.toastWrapper = tempDiv; - } +const initialToastHelper = () => { + const shownToastContainers: [Root, HTMLDivElement][] = []; + let shownToastAmount = 0; - public info = (content: string, duration = 3000) => { - return this.showToast({ type: "normal", content, duration }); - }; + const wrapperClassName = "toast-list-container"; + const tempDiv = document.createElement("div"); + tempDiv.className = wrapperClassName; + document.body.appendChild(tempDiv); + const toastWrapper = tempDiv; - public success = (content: string, duration = 3000) => { - return this.showToast({ type: "success", content, duration }); - }; - - public error = (content: string, duration = 3000) => { - return this.showToast({ type: "error", content, duration }); - }; - - private showToast = (config: ToastConfig) => { + const showToast = (config: ToastConfig) => { const tempDiv = document.createElement("div"); const toast = createRoot(tempDiv); tempDiv.className = `toast-wrapper ${config.type}`; - this.toastWrapper.appendChild(tempDiv); - this.shownToastAmount++; - this.shownToastContainers.push([toast, tempDiv]); - - setTimeout(() => { - tempDiv.classList.add("showup"); - }, 0); + toastWrapper.appendChild(tempDiv); + shownToastAmount++; + shownToastContainers.push([toast, tempDiv]); const cbs = { destory: () => { @@ -82,13 +65,13 @@ class ToastHelper { return; } - this.shownToastAmount--; - if (this.shownToastAmount === 0) { - for (const [root, tempDiv] of this.shownToastContainers) { + shownToastAmount--; + if (shownToastAmount === 0) { + for (const [root, tempDiv] of shownToastContainers) { root.unmount(); tempDiv.remove(); } - this.shownToastContainers.splice(0, this.shownToastContainers.length); + shownToastContainers.splice(0, shownToastContainers.length); } }, TOAST_ANIMATION_DURATION); }, @@ -96,10 +79,32 @@ class ToastHelper { toast.render(); + setTimeout(() => { + tempDiv.classList.add("showup"); + }, 10); + return cbs; }; -} -const toastHelper = new ToastHelper(); + const info = (content: string, duration = 3000) => { + return showToast({ type: "normal", content, duration }); + }; + + const success = (content: string, duration = 3000) => { + return showToast({ type: "success", content, duration }); + }; + + const error = (content: string, duration = 3000) => { + return showToast({ type: "error", content, duration }); + }; + + return { + info, + success, + error, + }; +}; + +const toastHelper = initialToastHelper(); export default toastHelper; diff --git a/web/src/components/UsageHeatMap.tsx b/web/src/components/UsageHeatMap.tsx index fd52a534..c317df5a 100644 --- a/web/src/components/UsageHeatMap.tsx +++ b/web/src/components/UsageHeatMap.tsx @@ -26,9 +26,7 @@ interface DailyUsageStat { count: number; } -interface Props {} - -const UsageHeatMap: React.FC = () => { +const UsageHeatMap = () => { const todayTimeStamp = utils.getDateStampByDate(Date.now()); const todayDay = new Date(todayTimeStamp).getDay() + 1; const nullCell = new Array(7 - todayDay).fill(0); diff --git a/web/src/components/UserBanner.tsx b/web/src/components/UserBanner.tsx index bcde39bc..e0e66748 100644 --- a/web/src/components/UserBanner.tsx +++ b/web/src/components/UserBanner.tsx @@ -7,9 +7,7 @@ import Icon from "./Icon"; import MenuBtnsPopup from "./MenuBtnsPopup"; import "../less/user-banner.less"; -interface Props {} - -const UserBanner: React.FC = () => { +const UserBanner = () => { const { user, owner } = useAppSelector((state) => state.user); const { memos, tags } = useAppSelector((state) => state.memo); const [shouldShowPopupBtns, setShouldShowPopupBtns] = useState(false); diff --git a/web/src/helpers/consts.ts b/web/src/helpers/consts.ts index 3acb0cd5..ef9277e9 100644 --- a/web/src/helpers/consts.ts +++ b/web/src/helpers/consts.ts @@ -4,9 +4,6 @@ export const UNKNOWN_ID = -1; // default animation duration export const ANIMATION_DURATION = 200; -// toast animation duration -export const TOAST_ANIMATION_DURATION = 400; - // millisecond in a day export const DAILY_TIMESTAMP = 3600 * 24 * 1000; diff --git a/web/src/less/shortcut-list.less b/web/src/less/shortcut-list.less index 9a4ec642..29f75147 100644 --- a/web/src/less/shortcut-list.less +++ b/web/src/less/shortcut-list.less @@ -54,10 +54,14 @@ @apply flex-row justify-end items-center hidden shrink-0; > .action-btn { - @apply flex flex-row justify-center items-center w-6 h-6 shrink-0; + @apply flex flex-row justify-center items-center; &.toggle-btn { - @apply w-4 h-auto text-gray-600; + @apply text-gray-600; + + > .icon-img { + @apply w-4 h-auto; + } &:hover { & + .action-btns-wrapper { diff --git a/web/src/less/toast.less b/web/src/less/toast.less index e9784a1d..44250739 100644 --- a/web/src/less/toast.less +++ b/web/src/less/toast.less @@ -6,6 +6,7 @@ > .toast-wrapper { @apply flex flex-col justify-start items-start relative left-full invisible text-base cursor-pointer shadow-lg rounded bg-white mt-6 py-2 px-4; min-width: 6em; + left: calc(100% + 32px); transition: all 0.4s ease; &.showup { diff --git a/web/src/pages/Auth.tsx b/web/src/pages/Auth.tsx index 27ee93ad..a12cc5ee 100644 --- a/web/src/pages/Auth.tsx +++ b/web/src/pages/Auth.tsx @@ -9,8 +9,6 @@ import Only from "../components/common/OnlyWhen"; import toastHelper from "../components/Toast"; import "../less/auth.less"; -interface Props {} - const validateConfig: ValidatorConfig = { minLength: 4, maxLength: 24, @@ -18,7 +16,7 @@ const validateConfig: ValidatorConfig = { noChinese: true, }; -const Auth: React.FC = () => { +const Auth = () => { const { t, locale } = useI18n(); const pageLoadingState = useLoading(true); const [siteHost, setSiteHost] = useState();