From a26e4168fd12b98b0ebc004627133c6231055a70 Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Mon, 30 Oct 2023 21:49:10 +0600 Subject: [PATCH] fix eslint --- .eslintrc.js | 7 ++- package.json | 3 +- src/api/notes/index.ts | 6 +-- src/api/notes/types.ts | 2 +- .../auth/login/LoginAnimatedScene/index.tsx | 1 + .../boris/BorisContactItem/index.tsx | 10 +--- src/components/boris/BorisContacts/index.tsx | 1 - .../boris/BorisGraphicStats/index.tsx | 3 -- .../boris/BorisStatsBackend/index.tsx | 2 +- .../charts/BasicCurveChart/index.tsx | 4 +- .../comment/CommentContent/index.tsx | 4 +- .../comment/CommentDistance/index.tsx | 34 +++++++------ src/components/comment/CommentForm/index.tsx | 6 +-- .../comment/CommentFormAttaches/index.tsx | 4 +- .../CommentFormFormatButtons/index.tsx | 2 +- src/components/common/Avatar/index.tsx | 1 - .../common/ImageLoadingWrapper/index.tsx | 2 - .../common/WithDescription/index.tsx | 2 +- src/components/containers/Columns/index.tsx | 3 +- src/components/editors/AudioGrid/index.tsx | 2 +- src/components/editors/ImageGrid/index.tsx | 2 +- src/components/flow/CellShade/index.tsx | 10 ++-- src/components/flow/FlowLoginStamp/index.tsx | 4 +- src/components/flow/FlowSwiperHero/index.tsx | 1 - src/components/input/Button/index.tsx | 2 +- src/components/lab/LabImage/index.tsx | 1 - src/components/menu/MenuButton/index.tsx | 1 + src/components/menu/VerticalMenu/index.tsx | 1 - .../node/NodeImageSwiperBlock/index.tsx | 2 + .../node/NodeRelatedBlock/index.tsx | 7 +-- src/components/notes/NoteCard/index.tsx | 4 +- .../notifications/NotificationBadge/index.tsx | 2 - .../profile/ProfileAvatar/index.tsx | 2 - .../ProfileSidebarNotifications/index.tsx | 1 - src/components/sidebar/SidebarStack/index.tsx | 6 +-- src/constants/api.ts | 10 ++-- src/constants/sidebar/index.ts | 1 - src/constants/themes/index.ts | 4 +- src/containers/boris/BorisSidebar/index.tsx | 1 - .../dialogs/TelegramAttachDialog/index.tsx | 2 +- src/containers/lab/LabGrid/index.tsx | 1 - src/containers/main/Header/index.tsx | 2 +- src/containers/node/NodeBacklinks/index.tsx | 1 - src/containers/node/NodeCommentForm/index.tsx | 1 - .../notifications/NotificationList/index.tsx | 34 +++++++------ .../profile/ProfileAccounts/index.tsx | 5 +- .../profile/ProfilePageLeft/index.tsx | 2 - .../profile/ProfileQuickInfo/index.tsx | 2 - .../profile/ProfileSidebarMenu/index.tsx | 3 +- .../profile/ProfileToggles/index.tsx | 1 - .../settings/SettingsNotes/index.tsx | 2 +- .../settings/UserSettingsView/index.tsx | 2 - .../sidebars/ProfileSidebar/index.tsx | 4 +- src/containers/sidebars/TagSidebar/index.tsx | 1 - src/hooks/auth/useOAuth.ts | 5 +- src/hooks/auth/usePatchUser.ts | 3 +- src/hooks/auth/useSuperPowers.ts | 4 +- src/hooks/auth/useTelegramAccount.ts | 7 ++- src/hooks/auth/useUserDescription.ts | 4 +- src/hooks/boris/useBoris.ts | 14 +++--- src/hooks/dom/useConfirmation.ts | 6 +-- src/hooks/dom/useGlobalLoader.ts | 2 + src/hooks/dom/useSSRLoadingIndicator.ts | 2 +- src/hooks/dom/useScrollEnd.ts | 4 +- src/hooks/dom/useWindowSize.ts | 7 +-- src/hooks/notes/useNotes.ts | 50 +++++++++---------- src/hooks/sidebar/useTagSidebar.ts | 1 - src/hooks/sortable/useSortableActions.ts | 24 +++++---- src/hooks/useFormAutosubmit.ts | 1 + src/layouts/FlowLayout/index.tsx | 2 - src/layouts/LabLayout/index.tsx | 2 +- src/layouts/NodeLayout/index.tsx | 5 +- src/layouts/RoomLayout/index.tsx | 3 +- src/pages/node/[id].tsx | 2 +- src/types/sidebar/index.ts | 4 +- src/utils/dom.ts | 1 - src/utils/formatText.ts | 3 +- src/utils/providers/AuthProvider.tsx | 1 - src/utils/providers/ThemeProvider.tsx | 3 ++ yarn.lock | 20 ++++++-- 80 files changed, 199 insertions(+), 205 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 25092ae2..46b6af84 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,10 +1,15 @@ module.exports = { extends: ['plugin:react/recommended', 'plugin:@next/next/recommended'], rules: { + 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks + 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 'react/prop-types': 0, 'react/display-name': 0, 'react/react-in-jsx-scope': 0, '@next/next/no-img-element': 0, + 'unused-imports/no-unused-imports': 'warn', + // 'no-unused-vars': 'warn', + 'quotes': [2, 'single', { 'avoidEscape': true }], 'import/order': [ 'error', { @@ -40,7 +45,7 @@ module.exports = { ecmaVersion: 7, sourceType: 'module', }, - plugins: ['import', 'react-hooks'], + plugins: ['import', 'react-hooks', 'unused-imports'], parser: '@typescript-eslint/parser', settings: { react: { diff --git a/package.json b/package.json index 848d90c6..a47fc5d3 100644 --- a/package.json +++ b/package.json @@ -91,7 +91,8 @@ "eslint": "^7.32.0", "eslint-plugin-import": "^2.25.4", "eslint-plugin-react": "^7.28.0", - "eslint-plugin-react-hooks": "^4.3.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-unused-imports": "^3.0.0", "husky": "^7.0.4", "lint-staged": "^12.1.6", "next-transpile-modules": "^9.0.0", diff --git a/src/api/notes/index.ts b/src/api/notes/index.ts index 898008f8..0e114dd5 100644 --- a/src/api/notes/index.ts +++ b/src/api/notes/index.ts @@ -4,9 +4,9 @@ import { ApiCreateNoteRequest, ApiUpdateNoteResponse, ApiUpdateNoteRequest, -} from "~/api/notes/types"; -import { URLS } from "~/constants/urls"; -import { api, cleanResult } from "~/utils/api"; +} from '~/api/notes/types'; +import { URLS } from '~/constants/urls'; +import { api, cleanResult } from '~/utils/api'; export const apiListNotes = ({ limit, offset, search }: ApiListNotesRequest) => api diff --git a/src/api/notes/types.ts b/src/api/notes/types.ts index bc94d315..7fefdd30 100644 --- a/src/api/notes/types.ts +++ b/src/api/notes/types.ts @@ -1,4 +1,4 @@ -import { Note } from "~/types/notes"; +import { Note } from '~/types/notes'; export interface ApiGetNotesRequest { limit: number; diff --git a/src/components/auth/login/LoginAnimatedScene/index.tsx b/src/components/auth/login/LoginAnimatedScene/index.tsx index f2638034..6cfbfcd0 100644 --- a/src/components/auth/login/LoginAnimatedScene/index.tsx +++ b/src/components/auth/login/LoginAnimatedScene/index.tsx @@ -86,6 +86,7 @@ const LoginAnimatedScene: FC = memo(() => { const listener = throttle(100, onMouseMove); document.addEventListener('mousemove', listener); return () => document.removeEventListener('mousemove', listener); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); if (isTablet) { diff --git a/src/components/boris/BorisContactItem/index.tsx b/src/components/boris/BorisContactItem/index.tsx index bc2178b5..d46569b5 100644 --- a/src/components/boris/BorisContactItem/index.tsx +++ b/src/components/boris/BorisContactItem/index.tsx @@ -1,10 +1,8 @@ -import React, { FC, ReactNode, useCallback } from 'react'; +import { FC, ReactNode } from 'react'; import { WithDescription } from '~/components/common/WithDescription'; import { Icon } from '~/components/input/Icon'; -import styles from './styles.module.scss'; - interface Props { icon: string; title: string; @@ -22,12 +20,6 @@ const BorisContactItem: FC = ({ prefix, suffix, }) => { - const onClick = useCallback(() => { - if (!link) return; - - window.open(link); - }, []); - return (
{prefix} diff --git a/src/components/boris/BorisContacts/index.tsx b/src/components/boris/BorisContacts/index.tsx index 67a9b675..0a033b2a 100644 --- a/src/components/boris/BorisContacts/index.tsx +++ b/src/components/boris/BorisContacts/index.tsx @@ -1,7 +1,6 @@ import React, { FC } from 'react'; import { BorisContactItem } from '~/components/boris/BorisContactItem'; -import { Group } from '~/components/containers/Group'; import { Padder } from '~/components/containers/Padder'; import { Button } from '~/components/input/Button'; diff --git a/src/components/boris/BorisGraphicStats/index.tsx b/src/components/boris/BorisGraphicStats/index.tsx index 3ef97068..542630bd 100644 --- a/src/components/boris/BorisGraphicStats/index.tsx +++ b/src/components/boris/BorisGraphicStats/index.tsx @@ -1,10 +1,7 @@ import React, { VFC } from 'react'; -import { parseISO } from 'date-fns'; -import { StatsCountdownCard } from '~/components/charts/StatsCountdownCard'; import { StatsGraphCard } from '~/components/charts/StatsGraphCard'; -import { foundationDate } from '~/constants/boris/constants'; import styles from './styles.module.scss'; diff --git a/src/components/boris/BorisStatsBackend/index.tsx b/src/components/boris/BorisStatsBackend/index.tsx index 834b6ca5..e63e3534 100644 --- a/src/components/boris/BorisStatsBackend/index.tsx +++ b/src/components/boris/BorisStatsBackend/index.tsx @@ -20,7 +20,7 @@ const BorisStatsBackend: FC = ({ isLoading, stats }) => { ); const nodesByMonth = useMemo( () => stats.nodes.by_month?.slice(0, -1), - [stats.comments.by_month], + [stats.nodes.by_month], ); if (!stats && !isLoading) { diff --git a/src/components/charts/BasicCurveChart/index.tsx b/src/components/charts/BasicCurveChart/index.tsx index e86b4973..d81cd4ec 100644 --- a/src/components/charts/BasicCurveChart/index.tsx +++ b/src/components/charts/BasicCurveChart/index.tsx @@ -1,7 +1,5 @@ import React, { useMemo, VFC } from 'react'; -import { lighten } from 'color2k'; - import { makeBezierCurve, PathPoint } from '~/utils/dom/makeBezierCurve'; import { SVGProps } from '~/utils/types'; @@ -40,7 +38,7 @@ const BasicCurveChart: VFC = ({ ], [], ), - [height, width, items, gap], + [items, borderGap, height, max, width], ); if (!points.length) { diff --git a/src/components/comment/CommentContent/index.tsx b/src/components/comment/CommentContent/index.tsx index 9f7ebfb8..2e4e1e48 100644 --- a/src/components/comment/CommentContent/index.tsx +++ b/src/components/comment/CommentContent/index.tsx @@ -11,15 +11,13 @@ import React, { import classnames from 'classnames'; -import { CommentForm } from '~/components/comment/CommentForm'; import { Authorized } from '~/components/containers/Authorized'; import { Group } from '~/components/containers/Group'; import { AudioPlayer } from '~/components/media/AudioPlayer'; import { COMMENT_BLOCK_RENDERERS } from '~/constants/comment'; import { UploadType } from '~/constants/uploads'; -import { imagePresets } from '~/constants/urls'; import { IComment, IFile } from '~/types'; -import { formatCommentText, getPrettyDate, getURL } from '~/utils/dom'; +import { formatCommentText, getPrettyDate } from '~/utils/dom'; import { append, assocPath, path, reduce } from '~/utils/ramda'; import { CommentEditingForm } from '../CommentEditingForm'; diff --git a/src/components/comment/CommentDistance/index.tsx b/src/components/comment/CommentDistance/index.tsx index 194f5a6a..a74d2e27 100644 --- a/src/components/comment/CommentDistance/index.tsx +++ b/src/components/comment/CommentDistance/index.tsx @@ -10,23 +10,25 @@ interface CommentDistanceProps { secondDate?: Date; } -const CommentDistance: FC = memo(({ firstDate, secondDate }) => { - const distance = useMemo(() => { - if (!firstDate || !secondDate) { - return undefined; +const CommentDistance: FC = memo( + ({ firstDate, secondDate }) => { + const distance = useMemo(() => { + if (!firstDate || !secondDate) { + return undefined; + } + + return formatDistance(secondDate, firstDate, { + locale: ru, + addSuffix: false, + }); + }, [firstDate, secondDate]); + + if (!distance) { + return null; } - return formatDistance(secondDate, firstDate, { - locale: ru, - addSuffix: false, - }); - }, []); - - if (!distance) { - return null; - } - - return
прошло {distance}
; -}); + return
прошло {distance}
; + }, +); export { CommentDistance }; diff --git a/src/components/comment/CommentForm/index.tsx b/src/components/comment/CommentForm/index.tsx index 1ff23cb8..4f3b0d7b 100644 --- a/src/components/comment/CommentForm/index.tsx +++ b/src/components/comment/CommentForm/index.tsx @@ -1,4 +1,4 @@ -import { FC, useCallback, useMemo, useState } from 'react'; +import { FC, useCallback, useState } from 'react'; import { FormikProvider } from 'formik'; import { observer } from 'mobx-react-lite'; @@ -9,14 +9,12 @@ import { CommentFormFormatButtons } from '~/components/comment/CommentFormFormat import { LocalCommentFormTextarea } from '~/components/comment/LocalCommentFormTextarea'; import { Filler } from '~/components/containers/Filler'; import { Button } from '~/components/input/Button'; -import { UploadDropzone } from '~/components/upload/UploadDropzone'; import { ERROR_LITERAL } from '~/constants/errors'; import { EMPTY_COMMENT } from '~/constants/node'; import { useCommentFormFormik } from '~/hooks/comments/useCommentFormFormik'; import { useInputPasteUpload } from '~/hooks/dom/useInputPasteUpload'; -import { IComment, INode } from '~/types'; +import { IComment } from '~/types'; import { - UploaderContextProvider, useUploaderContext, } from '~/utils/context/UploaderContextProvider'; diff --git a/src/components/comment/CommentFormAttaches/index.tsx b/src/components/comment/CommentFormAttaches/index.tsx index 927e464c..3589ae2d 100644 --- a/src/components/comment/CommentFormAttaches/index.tsx +++ b/src/components/comment/CommentFormAttaches/index.tsx @@ -30,14 +30,14 @@ const CommentFormAttaches: FC = () => { (newFiles: IFile[]) => { setFiles([...filesAudios, ...newFiles.filter((it) => it)]); }, - [setFiles, filesImages, filesAudios], + [setFiles, filesAudios], ); const onAudioMove = useCallback( (newFiles: IFile[]) => { setFiles([...filesImages, ...newFiles]); }, - [setFiles, filesImages, filesAudios], + [setFiles, filesImages], ); const onFileDelete = useCallback( diff --git a/src/components/comment/CommentFormFormatButtons/index.tsx b/src/components/comment/CommentFormFormatButtons/index.tsx index 8175c9b7..e90ba9ab 100644 --- a/src/components/comment/CommentFormFormatButtons/index.tsx +++ b/src/components/comment/CommentFormFormatButtons/index.tsx @@ -115,7 +115,7 @@ const CommentFormFormatButtons: FC = ({ element, handler }) => { label="Коммент" className={styles.button} > - {`/ /`} + {'/ /'} ); diff --git a/src/components/common/Avatar/index.tsx b/src/components/common/Avatar/index.tsx index 6503b0ce..dea2ef51 100644 --- a/src/components/common/Avatar/index.tsx +++ b/src/components/common/Avatar/index.tsx @@ -4,7 +4,6 @@ import classNames from 'classnames'; import { Square } from '~/components/common/Square'; import { imagePresets } from '~/constants/urls'; -import { useColorGradientFromString } from '~/hooks/color/useColorGradientFromString'; import { getURLFromString } from '~/utils/dom'; import { DivProps } from '~/utils/types'; diff --git a/src/components/common/ImageLoadingWrapper/index.tsx b/src/components/common/ImageLoadingWrapper/index.tsx index 3941a41b..186f559c 100644 --- a/src/components/common/ImageLoadingWrapper/index.tsx +++ b/src/components/common/ImageLoadingWrapper/index.tsx @@ -1,10 +1,8 @@ import React, { CSSProperties, FC, - useCallback, useMemo, useReducer, - useState, } from 'react'; import classNames from 'classnames'; diff --git a/src/components/common/WithDescription/index.tsx b/src/components/common/WithDescription/index.tsx index 0a311046..f7586824 100644 --- a/src/components/common/WithDescription/index.tsx +++ b/src/components/common/WithDescription/index.tsx @@ -16,7 +16,7 @@ const WithDescription: FC = ({ icon, title, subtitle, link }) => { if (!link) return; window.open(link); - }, []); + }, [link]); return (
= ({ const timeout = setTimeout(() => setColumns([...childs]), 150); return () => clearTimeout(timeout); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [ref.current]); useScrollEnd(columns, onScrollEnd, { active: hasMore, threshold: 2 }); diff --git a/src/components/editors/AudioGrid/index.tsx b/src/components/editors/AudioGrid/index.tsx index 6900a847..1102eb47 100644 --- a/src/components/editors/AudioGrid/index.tsx +++ b/src/components/editors/AudioGrid/index.tsx @@ -15,7 +15,7 @@ const AudioGrid: FC = ({ files, setFiles, locked }) => { (newFiles: IFile[]) => { setFiles(newFiles); }, - [setFiles, files], + [setFiles], ); const onDrop = useCallback( diff --git a/src/components/editors/ImageGrid/index.tsx b/src/components/editors/ImageGrid/index.tsx index 2556ee2a..26d91aac 100644 --- a/src/components/editors/ImageGrid/index.tsx +++ b/src/components/editors/ImageGrid/index.tsx @@ -18,7 +18,7 @@ const ImageGrid: FC = ({ files, setFiles, locked }) => { (newFiles: IFile[]) => { setFiles(newFiles.filter((it) => it)); }, - [setFiles, files], + [setFiles], ); const onDrop = useCallback( diff --git a/src/components/flow/CellShade/index.tsx b/src/components/flow/CellShade/index.tsx index 32ac90b2..758d4097 100644 --- a/src/components/flow/CellShade/index.tsx +++ b/src/components/flow/CellShade/index.tsx @@ -25,12 +25,16 @@ const CellShade: FC = ({ color, size = 50, angle = 7, ...rest }) => { return `linear-gradient(${angle}deg, ${normalized} ${size}px, ${transparentize( normalized, - 1 + 1, )} ${size * 5}px)`; - }, [color, size]); + }, [angle, color, size]); return ( -
+
); }; diff --git a/src/components/flow/FlowLoginStamp/index.tsx b/src/components/flow/FlowLoginStamp/index.tsx index 3a8818c7..c54cf410 100644 --- a/src/components/flow/FlowLoginStamp/index.tsx +++ b/src/components/flow/FlowLoginStamp/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, useCallback } from 'react'; +import React, { useCallback } from 'react'; import { Filler } from '~/components/containers/Filler'; import { Button } from '~/components/input/Button'; @@ -10,7 +10,7 @@ import styles from './styles.module.scss'; const FlowLoginStamp = () => { const showModal = useShowModal(Dialog.Login); - const onClick = useCallback(() => showModal({}), []); + const onClick = useCallback(() => showModal({}), [showModal]); return (
diff --git a/src/components/flow/FlowSwiperHero/index.tsx b/src/components/flow/FlowSwiperHero/index.tsx index 0833678b..ccdffcc0 100644 --- a/src/components/flow/FlowSwiperHero/index.tsx +++ b/src/components/flow/FlowSwiperHero/index.tsx @@ -1,7 +1,6 @@ import React, { FC, useCallback, useMemo, useState } from 'react'; import classNames from 'classnames'; -import Image from 'next/image'; import SwiperCore, { Autoplay, EffectFade, Lazy, Navigation } from 'swiper'; import { Swiper, SwiperSlide } from 'swiper/react'; import SwiperClass from 'swiper/types/swiper-class'; diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx index 9c7075ee..99a38ced 100644 --- a/src/components/input/Button/index.tsx +++ b/src/components/input/Button/index.tsx @@ -90,7 +90,7 @@ const Button: FC = memo( } return 24; - }, []); + }, [size]); return ( diff --git a/src/components/lab/LabImage/index.tsx b/src/components/lab/LabImage/index.tsx index 8bc085a4..e62244d0 100644 --- a/src/components/lab/LabImage/index.tsx +++ b/src/components/lab/LabImage/index.tsx @@ -3,7 +3,6 @@ import React, { FC } from 'react'; import Image from 'next/future/image'; import SwiperCore, { A11y, Navigation, Pagination } from 'swiper'; -import { ImagePreloader } from '~/components/media/ImagePreloader'; import { Placeholder } from '~/components/placeholders/Placeholder'; import { INodeComponentProps } from '~/constants/node'; import { imagePresets } from '~/constants/urls'; diff --git a/src/components/menu/MenuButton/index.tsx b/src/components/menu/MenuButton/index.tsx index 0239fc8d..563fc125 100644 --- a/src/components/menu/MenuButton/index.tsx +++ b/src/components/menu/MenuButton/index.tsx @@ -61,6 +61,7 @@ const MenuButton: FC = ({ useEffect(() => { popper.update?.(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [visible]); return ( diff --git a/src/components/menu/VerticalMenu/index.tsx b/src/components/menu/VerticalMenu/index.tsx index 23c20e41..434e27cc 100644 --- a/src/components/menu/VerticalMenu/index.tsx +++ b/src/components/menu/VerticalMenu/index.tsx @@ -2,7 +2,6 @@ import { PropsWithChildren } from 'react'; import classNames from 'classnames'; -import { Anchor } from '~/components/common/Anchor'; import { DivProps, LinkProps } from '~/utils/types'; import styles from './styles.module.scss'; diff --git a/src/components/node/NodeImageSwiperBlock/index.tsx b/src/components/node/NodeImageSwiperBlock/index.tsx index c756e39f..e8a82db0 100644 --- a/src/components/node/NodeImageSwiperBlock/index.tsx +++ b/src/components/node/NodeImageSwiperBlock/index.tsx @@ -89,6 +89,7 @@ const NodeImageSwiperBlock: FC = observer(({ node }) => { useEffect(() => { controlledSwiper?.slideTo(0, 0); return () => controlledSwiper?.slideTo(0, 0); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [images, node?.id]); useEffect(() => { @@ -97,6 +98,7 @@ const NodeImageSwiperBlock: FC = observer(({ node }) => { } else { controlledSwiper?.keyboard.enable(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isModalActive]); if (!images?.length) { diff --git a/src/components/node/NodeRelatedBlock/index.tsx b/src/components/node/NodeRelatedBlock/index.tsx index 39ee5572..7b69e32a 100644 --- a/src/components/node/NodeRelatedBlock/index.tsx +++ b/src/components/node/NodeRelatedBlock/index.tsx @@ -1,14 +1,11 @@ -import React, { FC, useCallback } from 'react'; +import React, { FC } from 'react'; import { Pressable } from '~/components/common/Pressable'; import { NodeRelated } from '~/components/node/NodeRelated'; import { NodeRelatedPlaceholder } from '~/components/node/NodeRelated/placeholder'; -import { Dialog } from '~/constants/modal'; -import { useShowModal } from '~/hooks/modal/useShowModal'; import { useTagSidebar } from '~/hooks/sidebar/useTagSidebar'; -import { INode, ITag } from '~/types'; +import { INode } from '~/types'; import { INodeRelated } from '~/types/node'; -import { useSidebar } from '~/utils/providers/SidebarProvider'; interface IProps { isLoading: boolean; diff --git a/src/components/notes/NoteCard/index.tsx b/src/components/notes/NoteCard/index.tsx index b2d54601..b8b06c95 100644 --- a/src/components/notes/NoteCard/index.tsx +++ b/src/components/notes/NoteCard/index.tsx @@ -25,14 +25,14 @@ const NoteCard: VFC = ({ }) => { const [editing, setEditing] = useState(false); - const toggleEditing = useCallback(() => setEditing(v => !v), []); + const toggleEditing = useCallback(() => setEditing((v) => !v), []); const onUpdate = useCallback( (text: string, callback?: () => void) => update(text, () => { setEditing(false); callback?.(); }), - [], + [update], ); return ( diff --git a/src/components/notifications/NotificationBadge/index.tsx b/src/components/notifications/NotificationBadge/index.tsx index 20c32a29..59a209d0 100644 --- a/src/components/notifications/NotificationBadge/index.tsx +++ b/src/components/notifications/NotificationBadge/index.tsx @@ -3,8 +3,6 @@ import React, { FC } from 'react'; import { Anchor } from '~/components/common/Anchor'; import { InlineUsername } from '~/components/common/InlineUsername'; import { Square } from '~/components/common/Square'; -import { Card } from '~/components/containers/Card'; -import { FlowRecentItem } from '~/components/flow/FlowRecentItem'; import { NotificationItem, NotificationType } from '~/types/notifications'; import { formatText, getPrettyDate, getURLFromString } from '~/utils/dom'; diff --git a/src/components/profile/ProfileAvatar/index.tsx b/src/components/profile/ProfileAvatar/index.tsx index 7cdd652c..2666966e 100644 --- a/src/components/profile/ProfileAvatar/index.tsx +++ b/src/components/profile/ProfileAvatar/index.tsx @@ -2,9 +2,7 @@ import React, { ChangeEvent, FC, useCallback } from 'react'; import { Avatar } from '~/components/common/Avatar'; import { Button } from '~/components/input/Button'; -import { imagePresets } from '~/constants/urls'; import { IFile } from '~/types'; -import { getURL } from '~/utils/dom'; import styles from './styles.module.scss'; diff --git a/src/components/profile/ProfileSidebarNotifications/index.tsx b/src/components/profile/ProfileSidebarNotifications/index.tsx index 7a700117..b2958bce 100644 --- a/src/components/profile/ProfileSidebarNotifications/index.tsx +++ b/src/components/profile/ProfileSidebarNotifications/index.tsx @@ -2,7 +2,6 @@ import { useState, VFC } from 'react'; import { Group } from '~/components/containers/Group'; import { Button } from '~/components/input/Button'; -import { Icon } from '~/components/input/Icon'; import { HorizontalMenu } from '~/components/menu/HorizontalMenu'; import { useStackContext } from '~/components/sidebar/SidebarStack'; import { SidebarStackCard } from '~/components/sidebar/SidebarStackCard'; diff --git a/src/components/sidebar/SidebarStack/index.tsx b/src/components/sidebar/SidebarStack/index.tsx index 0f8e64ab..07fdd7fe 100644 --- a/src/components/sidebar/SidebarStack/index.tsx +++ b/src/components/sidebar/SidebarStack/index.tsx @@ -38,7 +38,7 @@ const SidebarCards: FC = ({ children }) => { return []; } - return Array.isArray(children) ? children.filter(it => it) : [children]; + return Array.isArray(children) ? children.filter((it) => it) : [children]; }, [children]); if (isNil(activeTab) || !nonEmptyChildren[activeTab]) { @@ -48,7 +48,7 @@ const SidebarCards: FC = ({ children }) => { return
{nonEmptyChildren[activeTab]}
; }; -const SidebarStack = function({ +const SidebarStack = function ({ children, tab, onTabChange, @@ -58,7 +58,7 @@ const SidebarStack = function({ const closeAllTabs = useCallback(() => { setActiveTab(undefined); onTabChange?.(undefined); - }, []); + }, [onTabChange]); const onChangeTab = useCallback( (index: number) => { diff --git a/src/constants/api.ts b/src/constants/api.ts index b3318a30..0835efaf 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -22,8 +22,8 @@ export const API = { GET_SOCIALS: '/oauth', DROP_SOCIAL: (provider, id) => `/oauth/${provider}/${id}`, - ATTACH_SOCIAL: `/oauth`, - LOGIN_WITH_SOCIAL: `/oauth`, + ATTACH_SOCIAL: '/oauth', + LOGIN_WITH_SOCIAL: '/oauth', ATTACH_TELEGRAM: '/oauth/telegram/attach', }, NODES: { @@ -55,11 +55,11 @@ export const API = { GITHUB_ISSUES: 'https://api.github.com/repos/muerwre/vault-frontend/issues', }, TAG: { - NODES: `/tags/nodes`, - AUTOCOMPLETE: `/tags/autocomplete`, + NODES: '/tags/nodes', + AUTOCOMPLETE: '/tags/autocomplete', }, LAB: { - NODES: `/nodes/lab`, + NODES: '/nodes/lab', STATS: '/nodes/lab/stats', UPDATES: '/nodes/lab/updates', }, diff --git a/src/constants/sidebar/index.ts b/src/constants/sidebar/index.ts index f96d1634..587b493e 100644 --- a/src/constants/sidebar/index.ts +++ b/src/constants/sidebar/index.ts @@ -1,4 +1,3 @@ -import { SettingsSidebar } from '~/containers/sidebars/ProfileSidebar'; export enum SidebarName { Settings = 'settings', diff --git a/src/constants/themes/index.ts b/src/constants/themes/index.ts index 00a8ed90..3956b523 100644 --- a/src/constants/themes/index.ts +++ b/src/constants/themes/index.ts @@ -17,7 +17,7 @@ export const themeColors: Record = { 'linear-gradient(165deg, #ff7549 -50%, #ff3344 150%)', 'linear-gradient(170deg, #582cd0, #592071)', ], - background: `url('/images/noise_top.png') 0% 0% #23201f`, + background: 'url(\'/images/noise_top.png\') 0% 0% #23201f', }, [Theme.Horizon]: { name: 'Веспера', @@ -26,6 +26,6 @@ export const themeColors: Record = { 'linear-gradient(165deg, #fab795 -50%, #fab795 150%)', 'linear-gradient(170deg, #25b0bc, #7693d6)', ], - background: `url("/images/horizon_bg.svg") 50% 50% / cover rgb(28, 30, 38)`, + background: 'url("/images/horizon_bg.svg") 50% 50% / cover rgb(28, 30, 38)', }, }; diff --git a/src/containers/boris/BorisSidebar/index.tsx b/src/containers/boris/BorisSidebar/index.tsx index ba295baf..6e37b04b 100644 --- a/src/containers/boris/BorisSidebar/index.tsx +++ b/src/containers/boris/BorisSidebar/index.tsx @@ -4,7 +4,6 @@ import { BorisContacts } from '~/components/boris/BorisContacts'; import { BorisStats } from '~/components/boris/BorisStats'; import { Group } from '~/components/containers/Group'; import { SuperPowersToggle } from '~/containers/auth/SuperPowersToggle'; -import { useAuth } from '~/hooks/auth/useAuth'; import { useTelegramAccount } from '~/hooks/auth/useTelegramAccount'; import { BorisUsageStats } from '~/types/boris'; diff --git a/src/containers/dialogs/TelegramAttachDialog/index.tsx b/src/containers/dialogs/TelegramAttachDialog/index.tsx index 2a284db3..a7283d0a 100644 --- a/src/containers/dialogs/TelegramAttachDialog/index.tsx +++ b/src/containers/dialogs/TelegramAttachDialog/index.tsx @@ -21,7 +21,7 @@ const TelegramAttachDialog: FC = ({ const onAttach = useCallback( (data: TelegramUser) => attach(data, onRequestClose), - [onRequestClose], + [attach, onRequestClose], ); const buttons = useMemo( diff --git a/src/containers/lab/LabGrid/index.tsx b/src/containers/lab/LabGrid/index.tsx index 792a00e9..09146b4d 100644 --- a/src/containers/lab/LabGrid/index.tsx +++ b/src/containers/lab/LabGrid/index.tsx @@ -2,7 +2,6 @@ import { FC, memo } from 'react'; import { Hoverable } from '~/components/common/Hoverable'; import { Columns } from '~/components/containers/Columns'; -import { InfiniteScroll } from '~/components/containers/InfiniteScroll'; import { LabNoResults } from '~/components/lab/LabNoResults'; import { LabNode } from '~/components/lab/LabNode'; import { useLabContext } from '~/utils/context/LabContextProvider'; diff --git a/src/containers/main/Header/index.tsx b/src/containers/main/Header/index.tsx index 10b43801..19c06218 100644 --- a/src/containers/main/Header/index.tsx +++ b/src/containers/main/Header/index.tsx @@ -43,7 +43,7 @@ const Header: FC = observer(() => { borisCommentedAt && ((fetched && !user.last_seen_boris) || isBefore(new Date(user.last_seen_boris), new Date(borisCommentedAt))), - [borisCommentedAt, isUser, user.last_seen_boris, fetched], + [isUser, indicatorEnabled, borisCommentedAt, fetched, user.last_seen_boris], ); // Needed for SSR diff --git a/src/containers/node/NodeBacklinks/index.tsx b/src/containers/node/NodeBacklinks/index.tsx index cf8515ad..98ef80c7 100644 --- a/src/containers/node/NodeBacklinks/index.tsx +++ b/src/containers/node/NodeBacklinks/index.tsx @@ -2,7 +2,6 @@ import { FC, useMemo } from 'react'; import { SubTitle } from '~/components/common/SubTitle'; import { Card } from '~/components/containers/Card'; -import { Padder } from '~/components/containers/Padder'; import { Backlink } from '~/components/node/Backlink'; import { NodeBackLink } from '~/types'; import { has } from '~/utils/ramda'; diff --git a/src/containers/node/NodeCommentForm/index.tsx b/src/containers/node/NodeCommentForm/index.tsx index cebf4d5a..21325787 100644 --- a/src/containers/node/NodeCommentForm/index.tsx +++ b/src/containers/node/NodeCommentForm/index.tsx @@ -5,7 +5,6 @@ import { observer } from 'mobx-react-lite'; import { CommentForm } from '~/components/comment/CommentForm'; import { CommentWrapper } from '~/components/containers/CommentWrapper'; import { UploadDropzone } from '~/components/upload/UploadDropzone'; -import { EMPTY_USER } from '~/constants/auth'; import { Dialog } from '~/constants/modal'; import { UploadSubject, UploadTarget } from '~/constants/uploads'; import { useAuth } from '~/hooks/auth/useAuth'; diff --git a/src/containers/notifications/NotificationList/index.tsx b/src/containers/notifications/NotificationList/index.tsx index f71b36d2..c011d877 100644 --- a/src/containers/notifications/NotificationList/index.tsx +++ b/src/containers/notifications/NotificationList/index.tsx @@ -23,23 +23,27 @@ const NotificationList: FC = () => { useEffect(() => { return () => markAsRead(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const renderItem = useCallback((item: NotificationItem) => { - const isNew = - !lastSeen || - !item.created_at || - isAfter(parseISO(item.created_at), lastSeen); - switch (item.type) { - case NotificationType.Comment: - case NotificationType.Boris: - return ; - case NotificationType.Node: - return ; - default: - return null; - } - }, []); + const renderItem = useCallback( + (item: NotificationItem) => { + const isNew = + !lastSeen || + !item.created_at || + isAfter(parseISO(item.created_at), lastSeen); + switch (item.type) { + case NotificationType.Comment: + case NotificationType.Boris: + return ; + case NotificationType.Node: + return ; + default: + return null; + } + }, + [lastSeen], + ); if (isLoading) { return ; diff --git a/src/containers/profile/ProfileAccounts/index.tsx b/src/containers/profile/ProfileAccounts/index.tsx index 57d30691..d176843d 100644 --- a/src/containers/profile/ProfileAccounts/index.tsx +++ b/src/containers/profile/ProfileAccounts/index.tsx @@ -1,14 +1,11 @@ -import React, { FC, Fragment, useCallback, useMemo } from 'react'; +import React, { FC, Fragment } from 'react'; -import { Superpower } from '~/components/boris/Superpower'; import { Group } from '~/components/containers/Group'; import { Button } from '~/components/input/Button'; import { Icon } from '~/components/input/Icon'; import { Placeholder } from '~/components/placeholders/Placeholder'; import { SOCIAL_ICONS } from '~/constants/auth/socials'; -import { Dialog } from '~/constants/modal'; import { useOAuth } from '~/hooks/auth/useOAuth'; -import { useModal } from '~/hooks/modal/useModal'; import styles from './styles.module.scss'; diff --git a/src/containers/profile/ProfilePageLeft/index.tsx b/src/containers/profile/ProfilePageLeft/index.tsx index b6f13062..e268fbaa 100644 --- a/src/containers/profile/ProfilePageLeft/index.tsx +++ b/src/containers/profile/ProfilePageLeft/index.tsx @@ -1,11 +1,9 @@ import React, { FC } from 'react'; import { Avatar } from '~/components/common/Avatar'; -import { Markdown } from '~/components/containers/Markdown'; import { Placeholder } from '~/components/placeholders/Placeholder'; import { imagePresets } from '~/constants/urls'; import { IUser } from '~/types/auth'; -import { formatText } from '~/utils/dom'; import styles from './styles.module.scss'; diff --git a/src/containers/profile/ProfileQuickInfo/index.tsx b/src/containers/profile/ProfileQuickInfo/index.tsx index 84b133c3..7d232428 100644 --- a/src/containers/profile/ProfileQuickInfo/index.tsx +++ b/src/containers/profile/ProfileQuickInfo/index.tsx @@ -2,12 +2,10 @@ import React, { FC } from 'react'; import classNames from 'classnames'; -import { Avatar } from '~/components/common/Avatar'; import { Filler } from '~/components/containers/Filler'; import { Group } from '~/components/containers/Group'; import { useUserActiveStatus } from '~/hooks/auth/useUserActiveStatus'; import { IUser } from '~/types/auth'; -import { path } from '~/utils/ramda'; import styles from './styles.module.scss'; diff --git a/src/containers/profile/ProfileSidebarMenu/index.tsx b/src/containers/profile/ProfileSidebarMenu/index.tsx index abee8aac..f60f60d4 100644 --- a/src/containers/profile/ProfileSidebarMenu/index.tsx +++ b/src/containers/profile/ProfileSidebarMenu/index.tsx @@ -2,7 +2,6 @@ import React, { useCallback, VFC } from 'react'; import classNames from 'classnames'; -import { Superpower } from '~/components/boris/Superpower'; import { Filler } from '~/components/containers/Filler'; import { Group } from '~/components/containers/Group'; import { Zone } from '~/components/containers/Zone'; @@ -32,7 +31,7 @@ const ProfileSidebarMenu: VFC = ({ onClose }) => { const onLogout = useCallback(() => { logout(); onClose(); - }, [onClose]); + }, [logout, onClose]); return (
diff --git a/src/containers/profile/ProfileToggles/index.tsx b/src/containers/profile/ProfileToggles/index.tsx index 6a25bf96..6827ac18 100644 --- a/src/containers/profile/ProfileToggles/index.tsx +++ b/src/containers/profile/ProfileToggles/index.tsx @@ -1,7 +1,6 @@ import React, { FC } from 'react'; import { Group } from '~/components/containers/Group'; -import { Zone } from '~/components/containers/Zone'; import { SuperPowersToggle } from '~/containers/auth/SuperPowersToggle'; interface ProfileTogglesProps {} diff --git a/src/containers/settings/SettingsNotes/index.tsx b/src/containers/settings/SettingsNotes/index.tsx index 864f4b33..cb4cf6c7 100644 --- a/src/containers/settings/SettingsNotes/index.tsx +++ b/src/containers/settings/SettingsNotes/index.tsx @@ -20,7 +20,7 @@ const List = () => { async (id: number) => { confirm('Удалить? Это удалит заметку навсегда', () => remove(id)); }, - [remove], + [confirm, remove], ); return ( diff --git a/src/containers/settings/UserSettingsView/index.tsx b/src/containers/settings/UserSettingsView/index.tsx index 8b9bafee..b7ffc947 100644 --- a/src/containers/settings/UserSettingsView/index.tsx +++ b/src/containers/settings/UserSettingsView/index.tsx @@ -6,11 +6,9 @@ import { Group } from '~/components/containers/Group'; import { Zone } from '~/components/containers/Zone'; import { InputText } from '~/components/input/InputText'; import { Textarea } from '~/components/input/Textarea'; -import { ERROR_LITERAL } from '~/constants/errors'; import { ProfileAccounts } from '~/containers/profile/ProfileAccounts'; import { useWindowSize } from '~/hooks/dom/useWindowSize'; import { useSettings } from '~/utils/providers/SettingsProvider'; -import { has } from '~/utils/ramda'; import styles from './styles.module.scss'; diff --git a/src/containers/sidebars/ProfileSidebar/index.tsx b/src/containers/sidebars/ProfileSidebar/index.tsx index 2834ec0d..f8bf25a1 100644 --- a/src/containers/sidebars/ProfileSidebar/index.tsx +++ b/src/containers/sidebars/ProfileSidebar/index.tsx @@ -10,7 +10,6 @@ import { SidebarWrapper } from '~/components/sidebar/SidebarWrapper'; import { SidebarName } from '~/constants/sidebar'; import { ProfileSidebarMenu } from '~/containers/profile/ProfileSidebarMenu'; import { useAuth } from '~/hooks/auth/useAuth'; -import { useUser } from '~/hooks/auth/useUser'; import type { SidebarComponentProps } from '~/types/sidebar'; import { isNil } from '~/utils/ramda'; @@ -41,13 +40,14 @@ const SettingsSidebar: VFC = ({ page: !isNil(val) ? tabs[val] : undefined, }); }, - [open, onRequestClose], + [openSidebar], ); useEffect(() => { if (!isUser) { onRequestClose(); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isUser]); if (!isUser) { diff --git a/src/containers/sidebars/TagSidebar/index.tsx b/src/containers/sidebars/TagSidebar/index.tsx index 26a82d2a..ebfed8d2 100644 --- a/src/containers/sidebars/TagSidebar/index.tsx +++ b/src/containers/sidebars/TagSidebar/index.tsx @@ -2,7 +2,6 @@ import { useMemo, VFC } from 'react'; import { InfiniteScroll } from '~/components/containers/InfiniteScroll'; import { Icon } from '~/components/input/Icon'; -import { LoaderCircle } from '~/components/input/LoaderCircle'; import { SidebarStack } from '~/components/sidebar/SidebarStack'; import { SidebarStackCard } from '~/components/sidebar/SidebarStackCard'; import { SidebarWrapper } from '~/components/sidebar/SidebarWrapper'; diff --git a/src/hooks/auth/useOAuth.ts b/src/hooks/auth/useOAuth.ts index 8a1f9a82..e85e69a5 100644 --- a/src/hooks/auth/useOAuth.ts +++ b/src/hooks/auth/useOAuth.ts @@ -95,7 +95,6 @@ export const useOAuth = () => { ); const accounts = useMemo(() => data || [], [data]); - const refresh = useCallback(() => mutate(), []); const hasTelegram = useMemo( () => accounts.some((acc) => acc.provider === 'telegram'), @@ -104,7 +103,7 @@ export const useOAuth = () => { const showTelegramModal = useCallback( () => showModal(Dialog.TelegramAttach, {}), - [], + [showModal], ); return { @@ -117,6 +116,6 @@ export const useOAuth = () => { dropAccount, accounts, isLoading: !data && isLoading, - refresh, + refresh: mutate, }; }; diff --git a/src/hooks/auth/usePatchUser.ts b/src/hooks/auth/usePatchUser.ts index 5c2713a0..e8b3bdbd 100644 --- a/src/hooks/auth/usePatchUser.ts +++ b/src/hooks/auth/usePatchUser.ts @@ -5,7 +5,6 @@ import { ApiUpdateUserRequest } from '~/api/auth/types'; import { UploadSubject, UploadTarget } from '~/constants/uploads'; import { useUser } from '~/hooks/auth/useUser'; import { useUploader } from '~/hooks/data/useUploader'; -import { IFile } from '~/types'; import { showErrorToast } from '~/utils/errors/showToast'; export const usePatchUser = () => { @@ -39,7 +38,7 @@ export const usePatchUser = () => { showErrorToast(error); } }, - [uploadFile, save], + [uploadFile, update], ); return { updatePhoto, save }; diff --git a/src/hooks/auth/useSuperPowers.ts b/src/hooks/auth/useSuperPowers.ts index 2078316b..51307401 100644 --- a/src/hooks/auth/useSuperPowers.ts +++ b/src/hooks/auth/useSuperPowers.ts @@ -1,6 +1,6 @@ -import { useMemo } from "react"; +import { useMemo } from 'react'; -import { useAuth } from "~/hooks/auth/useAuth"; +import { useAuth } from '~/hooks/auth/useAuth'; export const useSuperPowers = () => { const { isTester, setIsTester } = useAuth(); diff --git a/src/hooks/auth/useTelegramAccount.ts b/src/hooks/auth/useTelegramAccount.ts index f770520a..f603b1de 100644 --- a/src/hooks/auth/useTelegramAccount.ts +++ b/src/hooks/auth/useTelegramAccount.ts @@ -30,10 +30,13 @@ export const useTelegramAccount = () => { setLoading(false); } }, - [], + [refresh, refreshNotificationSettings], ); - const connect = useCallback(() => showModal(Dialog.TelegramAttach, {}), []); + const connect = useCallback( + () => showModal(Dialog.TelegramAttach, {}), + [showModal], + ); const connected = useMemo( () => accounts.some((it) => it.provider === 'telegram'), diff --git a/src/hooks/auth/useUserDescription.ts b/src/hooks/auth/useUserDescription.ts index 096831c5..f42ebc2b 100644 --- a/src/hooks/auth/useUserDescription.ts +++ b/src/hooks/auth/useUserDescription.ts @@ -5,12 +5,12 @@ import { IUser } from '~/types/auth'; export const useUserDescription = (user?: Partial) => { const randomPhrase = useRandomPhrase('USER_DESCRIPTION'); + const isActive = useUserActiveStatus(user?.last_seen); + if (!user) { return ''; } - const isActive = useUserActiveStatus(user.last_seen); - if (!isActive) { return 'Юнит деактивирован'; } diff --git a/src/hooks/boris/useBoris.ts b/src/hooks/boris/useBoris.ts index 5a1ec35b..b0a79bfb 100644 --- a/src/hooks/boris/useBoris.ts +++ b/src/hooks/boris/useBoris.ts @@ -1,14 +1,14 @@ -import { useCallback, useEffect } from "react"; +import { useEffect } from 'react'; -import isBefore from "date-fns/isBefore"; +import isBefore from 'date-fns/isBefore'; -import { useRandomPhrase } from "~/constants/phrases"; -import { useLastSeenBoris } from "~/hooks/auth/useLastSeenBoris"; -import { useBorisStats } from "~/hooks/boris/useBorisStats"; -import { IComment } from "~/types"; +import { useRandomPhrase } from '~/constants/phrases'; +import { useLastSeenBoris } from '~/hooks/auth/useLastSeenBoris'; +import { useBorisStats } from '~/hooks/boris/useBorisStats'; +import { IComment } from '~/types'; export const useBoris = (comments: IComment[]) => { - const title = useRandomPhrase("BORIS_TITLE"); + const title = useRandomPhrase('BORIS_TITLE'); const { lastSeen, setLastSeen } = useLastSeenBoris(); diff --git a/src/hooks/dom/useConfirmation.ts b/src/hooks/dom/useConfirmation.ts index eb7fc605..01b02263 100644 --- a/src/hooks/dom/useConfirmation.ts +++ b/src/hooks/dom/useConfirmation.ts @@ -1,8 +1,8 @@ -import { useCallback } from "react"; +import { useCallback } from 'react'; export const useConfirmation = () => - useCallback((prompt = "", onApprove: () => {}, onReject?: () => {}) => { - if (!window.confirm(prompt || "Уверен?")) { + useCallback((prompt = '', onApprove: () => {}, onReject?: () => {}) => { + if (!window.confirm(prompt || 'Уверен?')) { onReject?.(); return; } diff --git a/src/hooks/dom/useGlobalLoader.ts b/src/hooks/dom/useGlobalLoader.ts index 6d61e836..03f21924 100644 --- a/src/hooks/dom/useGlobalLoader.ts +++ b/src/hooks/dom/useGlobalLoader.ts @@ -29,9 +29,11 @@ export const useGlobalLoader = () => { } hideLoader(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [flow.isRefreshed, getInitialNodes]); useEffect(() => { void getInitialNodes(); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [isUser]); }; diff --git a/src/hooks/dom/useSSRLoadingIndicator.ts b/src/hooks/dom/useSSRLoadingIndicator.ts index 25c13ae1..6e4df290 100644 --- a/src/hooks/dom/useSSRLoadingIndicator.ts +++ b/src/hooks/dom/useSSRLoadingIndicator.ts @@ -30,7 +30,7 @@ export const useSSRLoadingIndicator = (delay = 0) => { Router.events.on('routeChangeStart', show); Router.events.on('routeChangeComplete', hide); Router.events.on('routeChangeError', hide); - }, []); + }, [delay]); return shown; }; diff --git a/src/hooks/dom/useScrollEnd.ts b/src/hooks/dom/useScrollEnd.ts index bc08f14d..04c5398c 100644 --- a/src/hooks/dom/useScrollEnd.ts +++ b/src/hooks/dom/useScrollEnd.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useMemo } from 'react'; +import { useEffect, useMemo } from 'react'; import { throttle } from 'throttle-debounce'; @@ -44,5 +44,5 @@ export const useScrollEnd = ( window.addEventListener('scroll', eventHandler); return () => window.removeEventListener('scroll', eventHandler); - }, [item, active, innerHeight, debouncedCallback]); + }, [item, active, innerHeight, debouncedCallback, threshold]); }; diff --git a/src/hooks/dom/useWindowSize.ts b/src/hooks/dom/useWindowSize.ts index 9fbeb9ee..cedd29c6 100644 --- a/src/hooks/dom/useWindowSize.ts +++ b/src/hooks/dom/useWindowSize.ts @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from 'react'; export const useWindowSize = () => { const [size, setSize] = useState({ @@ -22,9 +22,10 @@ export const useWindowSize = () => { useEffect(() => { onResize(); - window.addEventListener("resize", onResize); + window.addEventListener('resize', onResize); - return () => window.removeEventListener("resize", onResize); + return () => window.removeEventListener('resize', onResize); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return size; diff --git a/src/hooks/notes/useNotes.ts b/src/hooks/notes/useNotes.ts index 3b612358..5b734056 100644 --- a/src/hooks/notes/useNotes.ts +++ b/src/hooks/notes/useNotes.ts @@ -1,42 +1,40 @@ -import { useCallback, useMemo } from "react"; +import { useCallback, useMemo } from 'react'; -import useSWRInfinite, { SWRInfiniteKeyLoader } from "swr/infinite"; +import useSWRInfinite, { SWRInfiniteKeyLoader } from 'swr/infinite'; import { apiCreateNote, apiDeleteNote, apiListNotes, apiUpdateNote, -} from "~/api/notes"; -import { ApiGetNotesRequest } from "~/api/notes/types"; -import { useAuth } from "~/hooks/auth/useAuth"; -import { GetLabNodesRequest, ILabNode } from "~/types/lab"; -import { Note } from "~/types/notes"; -import { flatten, uniqBy } from "~/utils/ramda"; +} from '~/api/notes'; +import { ApiGetNotesRequest } from '~/api/notes/types'; +import { useAuth } from '~/hooks/auth/useAuth'; +import { GetLabNodesRequest, ILabNode } from '~/types/lab'; +import { Note } from '~/types/notes'; +import { flatten, uniqBy } from '~/utils/ramda'; const DEFAULT_COUNT = 20; -const getKey: (isUser: boolean, search: string) => SWRInfiniteKeyLoader = ( - isUser, - search, -) => (index, prev: ILabNode[]) => { - if (!isUser) return null; - if (index > 0 && (!prev?.length || prev.length < 20)) return null; +const getKey: (isUser: boolean, search: string) => SWRInfiniteKeyLoader = + (isUser, search) => (index, prev: ILabNode[]) => { + if (!isUser) return null; + if (index > 0 && (!prev?.length || prev.length < 20)) return null; - const props: GetLabNodesRequest = { - limit: DEFAULT_COUNT, - offset: index * DEFAULT_COUNT, - search: search || "", + const props: GetLabNodesRequest = { + limit: DEFAULT_COUNT, + offset: index * DEFAULT_COUNT, + search: search || '', + }; + + return JSON.stringify(props); }; - return JSON.stringify(props); -}; - const parseKey = (key: string): ApiGetNotesRequest => { try { return JSON.parse(key); } catch (error) { - return { limit: DEFAULT_COUNT, offset: 0, search: "" }; + return { limit: DEFAULT_COUNT, offset: 0, search: '' }; } }; @@ -74,7 +72,7 @@ export const useNotes = (search: string) => { async (id: number, onSuccess?: () => void) => { await apiDeleteNote(id); await mutate( - data?.map(page => page.filter(it => it.id !== id)), + data?.map((page) => page.filter((it) => it.id !== id)), { revalidate: false }, ); onSuccess?.(); @@ -86,7 +84,7 @@ export const useNotes = (search: string) => { async (id: number, text: string, onSuccess?: () => void) => { const result = await apiUpdateNote({ id, text }); await mutate( - data?.map(page => page.map(it => (it.id === id ? result : it))), + data?.map((page) => page.map((it) => (it.id === id ? result : it))), { revalidate: false }, ); onSuccess?.(); @@ -94,7 +92,7 @@ export const useNotes = (search: string) => { [mutate, data], ); - const notes = useMemo(() => uniqBy(n => n.id, flatten(data || [])), [data]); + const notes = useMemo(() => uniqBy((n) => n.id, flatten(data || [])), [data]); const hasMore = (data?.[size - 1]?.length || 0) >= 1; const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); @@ -108,6 +106,6 @@ export const useNotes = (search: string) => { remove, update, }), - [notes, hasMore, loadMore, data, isValidating, create, remove], + [notes, hasMore, loadMore, data, isValidating, create, remove, update], ); }; diff --git a/src/hooks/sidebar/useTagSidebar.ts b/src/hooks/sidebar/useTagSidebar.ts index b9cfdec1..6f75cec7 100644 --- a/src/hooks/sidebar/useTagSidebar.ts +++ b/src/hooks/sidebar/useTagSidebar.ts @@ -1,7 +1,6 @@ import { useCallback } from 'react'; import { SidebarName } from '~/constants/sidebar'; -import { ITag } from '~/types'; import { useSidebar } from '~/utils/providers/SidebarProvider'; export const useTagSidebar = () => { diff --git a/src/hooks/sortable/useSortableActions.ts b/src/hooks/sortable/useSortableActions.ts index 9aa0abb5..f65679f5 100644 --- a/src/hooks/sortable/useSortableActions.ts +++ b/src/hooks/sortable/useSortableActions.ts @@ -1,6 +1,12 @@ import { useCallback, useMemo, useState } from 'react'; -import { DragStartEvent, MouseSensor, TouchSensor, useSensor, useSensors } from '@dnd-kit/core'; +import { + DragStartEvent, + MouseSensor, + TouchSensor, + useSensor, + useSensors, +} from '@dnd-kit/core'; import { DragEndEvent } from '@dnd-kit/core/dist/types'; import { moveArrItem } from '~/utils/fn'; @@ -8,11 +14,11 @@ import { moveArrItem } from '~/utils/fn'; export const useSortableActions = ( items: T[], getID: (item: T) => string | number, - onSortEnd: (items: T[]) => void + onSortEnd: (items: T[]) => void, ) => { const [draggingItem, setDraggingItem] = useState(null); - const ids = useMemo(() => items.map(getID), [items]); + const ids = useMemo(() => items.map(getID), [getID, items]); const onDragEnd = useCallback( ({ active, over }: DragEndEvent) => { @@ -22,12 +28,12 @@ export const useSortableActions = ( return; } - const oldIndex = items.findIndex(it => getID(it) === active.id); - const newIndex = items.findIndex(it => getID(it) === over.id); + const oldIndex = items.findIndex((it) => getID(it) === active.id); + const newIndex = items.findIndex((it) => getID(it) === over.id); onSortEnd(moveArrItem(oldIndex, newIndex, items)); }, - [items] + [getID, items, onSortEnd], ); const onDragStart = useCallback( @@ -36,11 +42,11 @@ export const useSortableActions = ( return; } - const activeItem = items.find(it => getID(it) === active.id); + const activeItem = items.find((it) => getID(it) === active.id); setDraggingItem(activeItem ?? null); }, - [items] + [getID, items], ); const sensors = useSensors( @@ -50,7 +56,7 @@ export const useSortableActions = ( tolerance: 5, }, }), - useSensor(MouseSensor) + useSensor(MouseSensor), ); return { sensors, onDragEnd, onDragStart, draggingItem, ids }; diff --git a/src/hooks/useFormAutosubmit.ts b/src/hooks/useFormAutosubmit.ts index 6b966ad1..0f710d5f 100644 --- a/src/hooks/useFormAutosubmit.ts +++ b/src/hooks/useFormAutosubmit.ts @@ -16,5 +16,6 @@ export const useFormAutoSubmit = ( const timeout = setTimeout(onSubmit, delay); return () => clearTimeout(timeout); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [values]); }; diff --git a/src/layouts/FlowLayout/index.tsx b/src/layouts/FlowLayout/index.tsx index 3b4aa5e6..54de2507 100644 --- a/src/layouts/FlowLayout/index.tsx +++ b/src/layouts/FlowLayout/index.tsx @@ -1,5 +1,3 @@ -import { FC } from 'react'; - import classNames from 'classnames'; import { FlowGrid } from '~/components/flow/FlowGrid'; diff --git a/src/layouts/LabLayout/index.tsx b/src/layouts/LabLayout/index.tsx index cc0f5e53..1a0d18a4 100644 --- a/src/layouts/LabLayout/index.tsx +++ b/src/layouts/LabLayout/index.tsx @@ -1,4 +1,4 @@ -import React, { FC, useMemo } from 'react'; +import React, { FC } from 'react'; import { Group } from '~/components/containers/Group'; import { Sticky } from '~/components/containers/Sticky'; diff --git a/src/layouts/NodeLayout/index.tsx b/src/layouts/NodeLayout/index.tsx index 56abd89c..6d360d54 100644 --- a/src/layouts/NodeLayout/index.tsx +++ b/src/layouts/NodeLayout/index.tsx @@ -31,7 +31,10 @@ const NodeLayout = observer(() => { useNodeCoverImage(node); - const onUnauthorizedLike = useCallback(() => showRegisterDialog({}), []); + const onUnauthorizedLike = useCallback( + () => showRegisterDialog({}), + [showRegisterDialog], + ); return (
diff --git a/src/layouts/RoomLayout/index.tsx b/src/layouts/RoomLayout/index.tsx index ef66c4e2..e805ca44 100644 --- a/src/layouts/RoomLayout/index.tsx +++ b/src/layouts/RoomLayout/index.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react'; +import { Anchor } from '~/components/common/Anchor'; import { Button } from '~/components/input/Button'; import { Role } from '~/constants/auth'; import { Dialog } from '~/constants/modal'; @@ -26,7 +27,7 @@ const RoomLayout: FC = () => {

Пока ещё концепт, над которым я размышляю, ты видишь его, потому - что включил суперсилы в Борисе. + что включил суперсилы в Борисе.

diff --git a/src/pages/node/[id].tsx b/src/pages/node/[id].tsx index 087747f4..cfe8e4ac 100644 --- a/src/pages/node/[id].tsx +++ b/src/pages/node/[id].tsx @@ -91,7 +91,7 @@ export const getStaticProps = async ( revalidate: 7 * 86400, // every week }; } catch (error) { - console.warn(`[NEXT] can't generate node: `, error); + console.warn('[NEXT] can\'t generate node: ', error); return { notFound: true, }; diff --git a/src/types/sidebar/index.ts b/src/types/sidebar/index.ts index 4fa7d584..4d11b90d 100644 --- a/src/types/sidebar/index.ts +++ b/src/types/sidebar/index.ts @@ -1,6 +1,6 @@ -import { FunctionComponent } from "react"; +import { FunctionComponent } from 'react'; -import type { SidebarComponents } from "~/constants/sidebar/components"; +import type { SidebarComponents } from '~/constants/sidebar/components'; export type SidebarComponent = keyof SidebarComponents; diff --git a/src/utils/dom.ts b/src/utils/dom.ts index db41e757..dd0b9d4d 100644 --- a/src/utils/dom.ts +++ b/src/utils/dom.ts @@ -10,7 +10,6 @@ import { COMMENT_BLOCK_TYPES, ICommentBlock, } from '~/constants/comment'; -import { imagePresets } from '~/constants/urls'; import { IFile, ValueOf } from '~/types'; import { CONFIG } from '~/utils/config'; import { diff --git a/src/utils/formatText.ts b/src/utils/formatText.ts index 1f5087da..db5726f6 100644 --- a/src/utils/formatText.ts +++ b/src/utils/formatText.ts @@ -1,6 +1,5 @@ import { marked } from 'marked'; -import { EventMessageType } from '~/constants/events'; import { stripHTMLTags } from '~/utils/stripHTMLTags'; /** @@ -22,7 +21,7 @@ export const formatTextSanitizeTags = (text: string): string => * Returns clickable usernames */ export const formatTextClickableUsernames = (text: string): string => - text.replace(/~([\wа-яА-Я-]+)/giu, `~$1`); + text.replace(/~([\wа-яА-Я-]+)/giu, '~$1'); /** * Makes gray comments diff --git a/src/utils/providers/AuthProvider.tsx b/src/utils/providers/AuthProvider.tsx index 89d569e3..8ec30fbc 100644 --- a/src/utils/providers/AuthProvider.tsx +++ b/src/utils/providers/AuthProvider.tsx @@ -1,7 +1,6 @@ import { createContext, FC, useContext } from 'react'; import { observer } from 'mobx-react-lite'; -import { boolean } from 'yup'; import { EMPTY_USER } from '~/constants/auth'; import { useAuth } from '~/hooks/auth/useAuth'; diff --git a/src/utils/providers/ThemeProvider.tsx b/src/utils/providers/ThemeProvider.tsx index 6869a8aa..66958863 100644 --- a/src/utils/providers/ThemeProvider.tsx +++ b/src/utils/providers/ThemeProvider.tsx @@ -44,10 +44,13 @@ const ThemeProvider: FC = ({ children }) => { useEffect(() => { const stored = localStorage.getItem('vault__theme'); + if (!stored || !keys(themeClass).includes(stored as Theme)) { return; } + setTheme(stored as Theme); + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const value = useMemo(() => ({ theme, setTheme }), [theme, setTheme]); diff --git a/yarn.lock b/yarn.lock index 995443ab..479c67f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1136,10 +1136,10 @@ eslint-plugin-import@^2.25.4: resolve "^1.20.0" tsconfig-paths "^3.12.0" -eslint-plugin-react-hooks@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172" - integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA== +eslint-plugin-react-hooks@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3" + integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.28.0: version "7.28.0" @@ -1161,6 +1161,18 @@ eslint-plugin-react@^7.28.0: semver "^6.3.0" string.prototype.matchall "^4.0.6" +eslint-plugin-unused-imports@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.0.0.tgz#d25175b0072ff16a91892c3aa72a09ca3a9e69e7" + integrity sha512-sduiswLJfZHeeBJ+MQaG+xYzSWdRXoSw61DpU13mzWumCkR0ufD0HmO4kdNokjrkluMHpj/7PJeN35pgbhW3kw== + dependencies: + eslint-rule-composer "^0.3.0" + +eslint-rule-composer@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" + integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== + eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"