diff --git a/.eslintrc.js b/.eslintrc.js index e822b399..46b6af84 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,6 @@ module.exports = { extends: ['plugin:react/recommended', 'plugin:@next/next/recommended'], rules: { - 'prettier/prettier': 'error', 'react-hooks/rules-of-hooks': 'error', // Checks rules of Hooks 'react-hooks/exhaustive-deps': 'warn', // Checks effect dependencies 'react/prop-types': 0, @@ -10,21 +9,13 @@ module.exports = { '@next/next/no-img-element': 0, 'unused-imports/no-unused-imports': 'warn', // 'no-unused-vars': 'warn', - quotes: [2, 'single', { avoidEscape: true }], + 'quotes': [2, 'single', { 'avoidEscape': true }], 'import/order': [ 'error', { alphabetize: { order: 'asc' }, 'newlines-between': 'always', - groups: [ - 'builtin', - 'external', - 'internal', - 'parent', - 'sibling', - 'index', - 'unknown', - ], + groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'unknown'], pathGroups: [ { pattern: 'react', @@ -43,17 +34,18 @@ module.exports = { paths: [ { name: 'ramda', - message: "import from '~/utils/ramda' instead", + message: + 'import from \'~/utils/ramda\' instead', }, ], }, - ], + ] }, parserOptions: { ecmaVersion: 7, sourceType: 'module', }, - plugins: ['import', 'react-hooks', 'unused-imports', 'prettier'], + plugins: ['import', 'react-hooks', 'unused-imports'], parser: '@typescript-eslint/parser', settings: { react: { diff --git a/package.json b/package.json index 133af634..10e5589c 100644 --- a/package.json +++ b/package.json @@ -92,14 +92,13 @@ "@typescript-eslint/parser": "^5.10.1", "eslint": "^7.32.0", "eslint-plugin-import": "^2.25.4", - "eslint-plugin-prettier": "^5.2.3", "eslint-plugin-react": "^7.28.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", - "prettier": "^3.0.0" + "prettier": "^2.7.1" }, "lint-staged": { "./**/*.{js,jsx,ts,tsx}": [ diff --git a/src/components/common/Avatar/index.tsx b/src/components/common/Avatar/index.tsx index 946c63f9..dc35d469 100644 --- a/src/components/common/Avatar/index.tsx +++ b/src/components/common/Avatar/index.tsx @@ -14,7 +14,7 @@ interface Props extends DivProps { username?: string; size?: number; hasUpdates?: boolean; - preset?: (typeof imagePresets)[keyof typeof imagePresets]; + preset?: typeof imagePresets[keyof typeof imagePresets]; } const Avatar = forwardRef( diff --git a/src/components/common/NodeHorizontalCard/index.tsx b/src/components/common/NodeHorizontalCard/index.tsx index d132ee90..3c0847be 100644 --- a/src/components/common/NodeHorizontalCard/index.tsx +++ b/src/components/common/NodeHorizontalCard/index.tsx @@ -8,8 +8,6 @@ import { URLS } from '~/constants/urls'; import { INode } from '~/types'; import { getPrettyDate } from '~/utils/dom'; -import { getNewCommentAnchor } from '../../../constants/dom/links'; - import styles from './styles.module.scss'; interface Props { @@ -18,30 +16,32 @@ interface Props { onClick?: MouseEventHandler; } -const NodeHorizontalCard: FC = ({ node, hasNew, onClick }) => ( - -
= ({ node, hasNew, onClick }) => { + return ( + - -
- -
-
{node.title || '...'}
- -
- {getPrettyDate(node.created_at)} +
+
-
- -); + +
+
{node.title || '...'}
+ +
+ {getPrettyDate(node.created_at)} +
+
+ + ); +}; export { NodeHorizontalCard }; diff --git a/src/components/notifications/NotificationComment/index.tsx b/src/components/notifications/NotificationComment/index.tsx index 90acf0ae..194a60bb 100644 --- a/src/components/notifications/NotificationComment/index.tsx +++ b/src/components/notifications/NotificationComment/index.tsx @@ -9,8 +9,6 @@ import { Square } from '~/components/common/Square'; import { NotificationItem } from '~/types/notifications'; import { formatText, getURLFromString } from '~/utils/dom'; -import { getCommentAnchor } from '../../../constants/dom/links'; - import styles from './styles.module.scss'; interface NotificationCommentProps { @@ -19,10 +17,7 @@ interface NotificationCommentProps { } const NotificationComment: FC = ({ item, isNew }) => ( - +
- [COMMENT_ANCHOR_PREFIX, id].join('-'); - -export const getNewCommentAnchor = (url: string) => - [url, NEW_COMMENT_ANCHOR_NAME].join('#'); - -export const getCommentAnchor = (url: string, commentId: number) => - [url, getCommentId(commentId)].join('#'); - -export const isCommentAnchor = (hash: string | undefined) => - hash?.startsWith(COMMENT_ANCHOR_PREFIX) || - hash?.startsWith(NEW_COMMENT_ANCHOR_NAME); diff --git a/src/constants/sidebar/index.ts b/src/constants/sidebar/index.ts index abd3390a..587b493e 100644 --- a/src/constants/sidebar/index.ts +++ b/src/constants/sidebar/index.ts @@ -1,3 +1,4 @@ + export enum SidebarName { Settings = 'settings', Tag = 'tag', diff --git a/src/constants/themes/index.ts b/src/constants/themes/index.ts index ab72f641..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: 'Веспера', diff --git a/src/constants/urls.ts b/src/constants/urls.ts index 9bed6e30..50da82fe 100644 --- a/src/constants/urls.ts +++ b/src/constants/urls.ts @@ -37,7 +37,7 @@ export const imagePresets = { flow_horizontal: 'flow_horizontal', } as const; -export type ImagePreset = (typeof imagePresets)[keyof typeof imagePresets]; +export type ImagePreset = typeof imagePresets[keyof typeof imagePresets]; export const imageSrcSets: Partial> = { [imagePresets[1600]]: 1600, @@ -49,7 +49,7 @@ export const imageSrcSets: Partial> = { export const flowDisplayToPreset: Record< FlowDisplayVariant, - (typeof imagePresets)[keyof typeof imagePresets] + typeof imagePresets[keyof typeof imagePresets] > = { single: 'flow_square', quadro: 'flow_square', diff --git a/src/containers/boris/BorisSuperpowers/ssr.tsx b/src/containers/boris/BorisSuperpowers/ssr.tsx index 5779c5c2..c8104207 100644 --- a/src/containers/boris/BorisSuperpowers/ssr.tsx +++ b/src/containers/boris/BorisSuperpowers/ssr.tsx @@ -3,12 +3,10 @@ import dynamic from 'next/dynamic'; import type { BorisSuperpowersProps } from './index'; export const BorisSuperPowersSSR = dynamic( - () => - import('~/containers/boris/BorisSuperpowers/index').then( - (it) => it.BorisSuperpowers, - ), + () => import('~/containers/boris/BorisSuperpowers/index') + .then(it => it.BorisSuperpowers), { ssr: false, loading: () =>
, - }, + } ); diff --git a/src/containers/dialogs/EditorCreateDialog/index.tsx b/src/containers/dialogs/EditorCreateDialog/index.tsx index 5abd35aa..50b16dd4 100644 --- a/src/containers/dialogs/EditorCreateDialog/index.tsx +++ b/src/containers/dialogs/EditorCreateDialog/index.tsx @@ -8,7 +8,7 @@ import { DialogComponentProps } from '~/types/modal'; import { values } from '~/utils/ramda'; export interface EditorCreateDialogProps extends DialogComponentProps { - type: (typeof NODE_TYPES)[keyof typeof NODE_TYPES]; + type: typeof NODE_TYPES[keyof typeof NODE_TYPES]; isInLab: boolean; } diff --git a/src/containers/dialogs/EditorDialog/constants/index.ts b/src/containers/dialogs/EditorDialog/constants/index.ts index ce392b50..dd9d0bc0 100644 --- a/src/containers/dialogs/EditorDialog/constants/index.ts +++ b/src/containers/dialogs/EditorDialog/constants/index.ts @@ -11,7 +11,7 @@ import { TextEditor } from '../components/TextEditor'; import { VideoEditor } from '../components/VideoEditor'; export const NODE_EDITORS: Record< - (typeof NODE_TYPES)[keyof typeof NODE_TYPES], + typeof NODE_TYPES[keyof typeof NODE_TYPES], FC > = { [NODE_TYPES.IMAGE]: ImageEditor, @@ -22,7 +22,7 @@ export const NODE_EDITORS: Record< }; export const NODE_EDITOR_DATA: Record< - (typeof NODE_TYPES)[keyof typeof NODE_TYPES], + typeof NODE_TYPES[keyof typeof NODE_TYPES], Partial > = { [NODE_TYPES.TEXT]: { diff --git a/src/containers/main/Header/ssr.tsx b/src/containers/main/Header/ssr.tsx index 1c698535..5b6e4b6a 100644 --- a/src/containers/main/Header/ssr.tsx +++ b/src/containers/main/Header/ssr.tsx @@ -4,12 +4,9 @@ import type { HeaderProps } from '~/containers/main/Header/index'; import styles from './styles.module.scss'; -export const HeaderSSR = dynamic( - () => import('./index').then((it) => it.Header), - { - ssr: false, - loading: () =>
, - }, -); +export const HeaderSSR = dynamic(() => import('./index').then(it => it.Header), { + ssr: false, + loading: () =>
, +}); export const HeaderSSRPlaceholder = () =>
; diff --git a/src/containers/main/SubmitBarRouter/components/SubmitBar/ssr.ts b/src/containers/main/SubmitBarRouter/components/SubmitBar/ssr.ts index 7304ab41..50a28f1e 100644 --- a/src/containers/main/SubmitBarRouter/components/SubmitBar/ssr.ts +++ b/src/containers/main/SubmitBarRouter/components/SubmitBar/ssr.ts @@ -3,6 +3,5 @@ import dynamic from 'next/dynamic'; import type { SubmitBarProps } from './index'; export const SubmitBarSSR = dynamic( - () => import('./index').then((it) => it.SubmitBar), - { ssr: false }, -); + () => import('./index').then(it => it.SubmitBar), + { ssr: false }); diff --git a/src/containers/node/NodeComments/components/Comment/index.tsx b/src/containers/node/NodeComments/components/Comment/index.tsx index 1e3f2b60..121d8051 100644 --- a/src/containers/node/NodeComments/components/Comment/index.tsx +++ b/src/containers/node/NodeComments/components/Comment/index.tsx @@ -8,7 +8,6 @@ import { CommentWrapper } from '~/containers/comments/CommentWrapper'; import { IComment, ICommentGroup, IFile } from '~/types'; import { CommendDeleted } from '../../../../../components/node/CommendDeleted'; -import { getCommentId } from '../../../../../constants/dom/links'; import { CommentContent } from './components/CommentContent'; import { CommentDistance } from './components/CommentDistance'; @@ -84,22 +83,18 @@ const Comment: FC = memo( ); return ( - <> - - - onLike(comment.id, !comment.liked)} - onDelete={(val: boolean) => onDelete(comment.id, val)} - onShowImageModal={onShowImageModal} - key={comment.id} - /> - + onLike(comment.id, !comment.liked)} + onDelete={(val: boolean) => onDelete(comment.id, val)} + onShowImageModal={onShowImageModal} + key={comment.id} + /> ); })}
diff --git a/src/containers/node/NodeComments/components/Comment/styles.module.scss b/src/containers/node/NodeComments/components/Comment/styles.module.scss index 92cd93b4..01c1e131 100644 --- a/src/containers/node/NodeComments/components/Comment/styles.module.scss +++ b/src/containers/node/NodeComments/components/Comment/styles.module.scss @@ -15,9 +15,3 @@ .highlighted { box-shadow: $color_primary 0 0 0px 2px; } - -.anchor { - display: block; - position: relative; - top: -($header_height * 2); -} diff --git a/src/containers/node/NodeComments/index.tsx b/src/containers/node/NodeComments/index.tsx index 71c3a547..acba75b0 100644 --- a/src/containers/node/NodeComments/index.tsx +++ b/src/containers/node/NodeComments/index.tsx @@ -1,13 +1,9 @@ -import { FC, useEffect, useMemo } from 'react'; +import { FC, useMemo } from 'react'; import { observer } from 'mobx-react-lite'; import { LoadMoreButton } from '~/components/input/LoadMoreButton'; import { ANNOUNCE_USER_ID, BORIS_NODE_ID } from '~/constants/boris/constants'; -import { - isCommentAnchor, - NEW_COMMENT_ANCHOR_NAME, -} from '~/constants/dom/links'; import { Comment } from '~/containers/node/NodeComments/components/Comment'; import { useGrouppedComments } from '~/hooks/node/useGrouppedComments'; import { ICommentGroup } from '~/types'; @@ -22,11 +18,6 @@ interface Props { order: 'ASC' | 'DESC'; } -const isFirstGroupWithNewComment = ( - group: ICommentGroup, - prevGroup: ICommentGroup | undefined, -) => group.hasNew && (!prevGroup || !prevGroup.hasNew); - const NodeComments: FC = observer(({ order }) => { const user = useUserContext(); const { node } = useNodeContext(); @@ -44,7 +35,7 @@ const NodeComments: FC = observer(({ order }) => { onSaveComment, } = useCommentContext(); - const groupped = useGrouppedComments( + const groupped: ICommentGroup[] = useGrouppedComments( comments, order, lastSeenCurrent ?? undefined, @@ -68,49 +59,26 @@ const NodeComments: FC = observer(({ order }) => { return null; } - useEffect(() => { - const anchor = location.hash?.replace('#', ''); - - if (!isLoading && isCommentAnchor(anchor)) { - setTimeout( - () => - document - .getElementById(anchor) - ?.scrollIntoView({ behavior: 'smooth' }), - 300, - ); - } - }, [isLoading]); - return (
{order === 'DESC' && more} - {groupped.map((group, index) => ( - <> - {isFirstGroupWithNewComment(group, groupped[index - 1]) && ( - - )} - - - + {groupped.map((group) => ( + ))} {order === 'ASC' && more} diff --git a/src/containers/node/NodeComments/styles.module.scss b/src/containers/node/NodeComments/styles.module.scss index 1d006bd7..3cd52e5a 100644 --- a/src/containers/node/NodeComments/styles.module.scss +++ b/src/containers/node/NodeComments/styles.module.scss @@ -13,9 +13,3 @@ .more { margin-bottom: $gap; } - -.newCommentAnchor { - position: relative; - top: -($header_height * 2); - display: block; -} \ No newline at end of file diff --git a/src/containers/sidebars/ProfileSidebar/index.tsx b/src/containers/sidebars/ProfileSidebar/index.tsx index 26bb13e5..ff623d89 100644 --- a/src/containers/sidebars/ProfileSidebar/index.tsx +++ b/src/containers/sidebars/ProfileSidebar/index.tsx @@ -14,7 +14,7 @@ import type { SidebarComponentProps } from '~/types/sidebar'; import { isNil } from '~/utils/ramda'; const tabs = ['profile', 'notifications', 'bookmarks'] as const; -type TabName = (typeof tabs)[number]; +type TabName = typeof tabs[number]; interface SettingsSidebarProps extends SidebarComponentProps { diff --git a/src/hooks/auth/useLastSeenBoris.ts b/src/hooks/auth/useLastSeenBoris.ts index 3cc5a5bb..c8e08bbe 100644 --- a/src/hooks/auth/useLastSeenBoris.ts +++ b/src/hooks/auth/useLastSeenBoris.ts @@ -10,7 +10,7 @@ export const useLastSeenBoris = () => { async (date: string) => { await update({ last_seen_boris: date }, false); }, - [update], + [update] ); return { setLastSeen, lastSeen }; diff --git a/src/hooks/auth/useLoginLogoutRestore.ts b/src/hooks/auth/useLoginLogoutRestore.ts index 76e74458..4e438f16 100644 --- a/src/hooks/auth/useLoginLogoutRestore.ts +++ b/src/hooks/auth/useLoginLogoutRestore.ts @@ -20,7 +20,7 @@ export const useLoginLogoutRestore = () => { showToastInfo(getRandomPhrase('WELCOME')); return result.user; }, - [auth], + [auth] ); return { logout, login }; diff --git a/src/hooks/auth/useRestoreCode.ts b/src/hooks/auth/useRestoreCode.ts index 74e3fa68..8e957b58 100644 --- a/src/hooks/auth/useRestoreCode.ts +++ b/src/hooks/auth/useRestoreCode.ts @@ -5,9 +5,8 @@ import { API } from '~/constants/api'; import { getErrorMessage } from '~/utils/errors/getErrorMessage'; export const useRestoreCode = (code: string) => { - const { data, isValidating, error } = useSWR( - API.USER.REQUEST_CODE(code), - () => apiCheckRestoreCode({ code }), + const { data, isValidating, error } = useSWR(API.USER.REQUEST_CODE(code), () => + apiCheckRestoreCode({ code }) ); const codeUser = data?.user; diff --git a/src/hooks/auth/useRestorePasswordForm.ts b/src/hooks/auth/useRestorePasswordForm.ts index 0405993d..0373dfd0 100644 --- a/src/hooks/auth/useRestorePasswordForm.ts +++ b/src/hooks/auth/useRestorePasswordForm.ts @@ -18,7 +18,7 @@ const validationSchema = object({ .test( 'sameAsPassword', 'Должен совпадать с паролем', - (val, ctx) => val === ctx.parent.newPassword, + (val, ctx) => val === ctx.parent.newPassword ), }); @@ -26,21 +26,15 @@ export type RestorePasswordData = Asserts; export const useRestorePasswordForm = ( code: string, - fetcher: (props: { - code: string; - password: string; - }) => Promise<{ token: string; user: IUser }>, - onSuccess: () => void, + fetcher: (props: { code: string; password: string }) => Promise<{ token: string; user: IUser }>, + onSuccess: () => void ) => { const auth = useAuthStore(); const onSubmit = useCallback['onSubmit']>( async (values, { setErrors }) => { try { - const { token, user } = await fetcher({ - password: values.newPassword, - code, - }); + const { token, user } = await fetcher({ password: values.newPassword, code }); auth.setUser(user); auth.setToken(token); onSuccess(); @@ -53,7 +47,7 @@ export const useRestorePasswordForm = ( } } }, - [onSuccess, fetcher, code, auth], + [onSuccess, fetcher, code, auth] ); return useFormik({ diff --git a/src/hooks/auth/useRestoreRequestForm.ts b/src/hooks/auth/useRestoreRequestForm.ts index 7386a9ac..6dc63a37 100644 --- a/src/hooks/auth/useRestoreRequestForm.ts +++ b/src/hooks/auth/useRestoreRequestForm.ts @@ -15,7 +15,7 @@ type RestoreRequestData = Asserts; export const useRestoreRequestForm = ( fetcher: (field: string) => Promise, - onSuccess: () => void, + onSuccess: () => void ) => { const onSubmit = useCallback['onSubmit']>( async (values, { setErrors }) => { @@ -31,7 +31,7 @@ export const useRestoreRequestForm = ( } } }, - [fetcher, onSuccess], + [fetcher, onSuccess] ); return useFormik({ diff --git a/src/hooks/auth/useSessionCookie.ts b/src/hooks/auth/useSessionCookie.ts index eeeab746..0d7ce68d 100644 --- a/src/hooks/auth/useSessionCookie.ts +++ b/src/hooks/auth/useSessionCookie.ts @@ -13,6 +13,6 @@ export const useSessionCookie = () => { autorun(() => { setCookie('session', auth.token, 30); }), - [auth], + [auth] ); }; diff --git a/src/hooks/auth/useSocialRegisterForm.ts b/src/hooks/auth/useSocialRegisterForm.ts index 7ea8c26b..3acad2d0 100644 --- a/src/hooks/auth/useSocialRegisterForm.ts +++ b/src/hooks/auth/useSocialRegisterForm.ts @@ -9,7 +9,9 @@ import { showErrorToast } from '~/utils/errors/showToast'; const validationSchema = object({ username: string().required(ERRORS.REQUIRED), - password: string().required(ERRORS.REQUIRED).min(6, ERRORS.PASSWORD_IS_SHORT), + password: string() + .required(ERRORS.REQUIRED) + .min(6, ERRORS.PASSWORD_IS_SHORT), }); type SocialRegisterData = Asserts; @@ -21,7 +23,7 @@ export const useSocialRegisterForm = ( username: string; password: string; }) => Promise<{ token: string }>, - onSuccess: (token: string) => void, + onSuccess: (token: string) => void ) => { const onSubmit = useCallback['onSubmit']>( async (values, { setErrors }) => { @@ -41,7 +43,7 @@ export const useSocialRegisterForm = ( } } }, - [token, onSuccess, fetcher], + [token, onSuccess, fetcher] ); return useFormik({ diff --git a/src/hooks/auth/useUserActiveStatus.ts b/src/hooks/auth/useUserActiveStatus.ts index ea364e88..ba90caa9 100644 --- a/src/hooks/auth/useUserActiveStatus.ts +++ b/src/hooks/auth/useUserActiveStatus.ts @@ -7,10 +7,7 @@ const today = new Date(); export const useUserActiveStatus = (lastSeen?: string) => { try { const lastSeenDate = lastSeen ? parseISO(lastSeen) : undefined; - return ( - lastSeenDate && - differenceInDays(today, lastSeenDate) < INACTIVE_ACCOUNT_DAYS - ); + return lastSeenDate && differenceInDays(today, lastSeenDate) < INACTIVE_ACCOUNT_DAYS; } catch (e) { return false; } diff --git a/src/hooks/boris/useBorisStats.ts b/src/hooks/boris/useBorisStats.ts index 7713fe0b..47d8a7b9 100644 --- a/src/hooks/boris/useBorisStats.ts +++ b/src/hooks/boris/useBorisStats.ts @@ -6,15 +6,13 @@ import { initialBackendStats } from '~/constants/boris/constants'; import { BorisUsageStats } from '~/types/boris'; export const useBorisStats = () => { - const { - data: backend = initialBackendStats, - isValidating: isValidatingBackend, - } = useSWR(API.BORIS.GET_BACKEND_STATS, () => getBorisBackendStats()); - - const { data: issues = [] } = useSWR(API.BORIS.GITHUB_ISSUES, () => - getGithubIssues(), + const { data: backend = initialBackendStats, isValidating: isValidatingBackend } = useSWR( + API.BORIS.GET_BACKEND_STATS, + () => getBorisBackendStats() ); + const { data: issues = [] } = useSWR(API.BORIS.GITHUB_ISSUES, () => getGithubIssues()); + const stats: BorisUsageStats = { backend, issues, diff --git a/src/hooks/color/useColorFromString.ts b/src/hooks/color/useColorFromString.ts index dba30155..10668fb8 100644 --- a/src/hooks/color/useColorFromString.ts +++ b/src/hooks/color/useColorFromString.ts @@ -3,16 +3,9 @@ import { useMemo } from 'react'; import { normalizeBrightColor } from '~/utils/color'; import { stringToColour } from '~/utils/dom'; -export const useColorFromString = ( - val?: string, - saturation = 3, - lightness = 3, -) => { +export const useColorFromString = (val?: string, saturation = 3, lightness = 3) => { return useMemo( - () => - (val && - normalizeBrightColor(stringToColour(val), saturation, lightness)) || - '', - [lightness, saturation, val], + () => (val && normalizeBrightColor(stringToColour(val), saturation, lightness)) || '', + [lightness, saturation, val] ); }; diff --git a/src/hooks/color/useColorGradientFromString.ts b/src/hooks/color/useColorGradientFromString.ts index 10e17cdc..b94864f1 100644 --- a/src/hooks/color/useColorGradientFromString.ts +++ b/src/hooks/color/useColorGradientFromString.ts @@ -6,7 +6,7 @@ export const useColorGradientFromString = ( val?: string, saturation = 3, lightness = 3, - angle = 155, + angle = 155 ) => useMemo(() => { if (!val) { diff --git a/src/hooks/data/usePersistedState.ts b/src/hooks/data/usePersistedState.ts index f0403824..80a48418 100644 --- a/src/hooks/data/usePersistedState.ts +++ b/src/hooks/data/usePersistedState.ts @@ -1,9 +1,6 @@ import { useEffect, useMemo, useState } from 'react'; -export const usePersistedState = ( - key: string, - initial: string, -): [string, (val: string) => any] => { +export const usePersistedState = (key: string, initial: string): [string, (val: string) => any] => { const stored = useMemo(() => { try { return localStorage.getItem(`vault_${key}`) || initial; diff --git a/src/hooks/dom/useFocusEvent.ts b/src/hooks/dom/useFocusEvent.ts index 3af9ab24..baaf273a 100644 --- a/src/hooks/dom/useFocusEvent.ts +++ b/src/hooks/dom/useFocusEvent.ts @@ -4,18 +4,15 @@ export const useFocusEvent = (initialState = false, delay = 0) => { const [focused, setFocused] = useState(initialState); const onFocus = useCallback( - (event) => { + event => { event.preventDefault(); event.stopPropagation(); setFocused(true); }, - [setFocused], - ); - const onBlur = useCallback( - () => setTimeout(() => setFocused(false), delay), - [delay], + [setFocused] ); + const onBlur = useCallback(() => setTimeout(() => setFocused(false), delay), [delay]); return { focused, onBlur, onFocus }; }; diff --git a/src/hooks/dom/useFormatWrapper.ts b/src/hooks/dom/useFormatWrapper.ts index 96b832a9..89c25b23 100644 --- a/src/hooks/dom/useFormatWrapper.ts +++ b/src/hooks/dom/useFormatWrapper.ts @@ -7,13 +7,12 @@ export const useFormatWrapper = (onChange: (val: string) => void) => { target: HTMLTextAreaElement, prefix = '', - suffix = '', - ) => - (event) => { - event.preventDefault(); - wrapTextInsideInput(target, prefix, suffix, onChange); - }, - [onChange], + suffix = '' + ) => event => { + event.preventDefault(); + wrapTextInsideInput(target, prefix, suffix, onChange); + }, + [onChange] ); }; @@ -22,7 +21,7 @@ export const wrapTextInsideInput = ( target: HTMLTextAreaElement, prefix: string, suffix: string, - onChange: (val: string) => void, + onChange: (val: string) => void ) => { if (!target) return; @@ -35,7 +34,7 @@ export const wrapTextInsideInput = ( onChange( target.value.substring(0, start) + replacement + - target.value.substring(end, target.value.length), + target.value.substring(end, target.value.length) ); target.focus(); diff --git a/src/hooks/dom/useInfiniteLoader.ts b/src/hooks/dom/useInfiniteLoader.ts index 32236c63..e6eb2608 100644 --- a/src/hooks/dom/useInfiniteLoader.ts +++ b/src/hooks/dom/useInfiniteLoader.ts @@ -2,8 +2,7 @@ import { useCallback, useEffect } from 'react'; export const useInfiniteLoader = (loader: () => void, isLoading?: boolean) => { const onLoadMore = useCallback(() => { - const pos = - window.scrollY + window.innerHeight - document.body.scrollHeight; + const pos = window.scrollY + window.innerHeight - document.body.scrollHeight; if (isLoading || pos < -600) return; diff --git a/src/hooks/dom/useInputPasteUpload.ts b/src/hooks/dom/useInputPasteUpload.ts index b45ed986..50ab42ba 100644 --- a/src/hooks/dom/useInputPasteUpload.ts +++ b/src/hooks/dom/useInputPasteUpload.ts @@ -5,13 +5,13 @@ import { getImageFromPaste } from '~/utils/uploader'; // useInputPasteUpload attaches event listener to input, that calls onUpload if user pasted any image export const useInputPasteUpload = (onUpload: (files: File[]) => void) => { return useCallback( - async (event) => { + async event => { const image = await getImageFromPaste(event); if (!image) return; onUpload([image]); }, - [onUpload], + [onUpload] ); }; diff --git a/src/hooks/dom/usePopperModifiers.ts b/src/hooks/dom/usePopperModifiers.ts index 4cccfa7e..f057ccb0 100644 --- a/src/hooks/dom/usePopperModifiers.ts +++ b/src/hooks/dom/usePopperModifiers.ts @@ -17,11 +17,7 @@ const sameWidth = { }, }; -export const usePopperModifiers = ( - offsetX = 0, - offsetY = 10, - justify?: boolean, -): Modifier[] => +export const usePopperModifiers = (offsetX = 0, offsetY = 10, justify?: boolean): Modifier[] => useMemo( () => [ @@ -39,5 +35,5 @@ export const usePopperModifiers = ( }, ...(justify ? [sameWidth] : []), ] as Modifier[], - [offsetX, offsetY, justify], + [offsetX, offsetY, justify] ); diff --git a/src/hooks/dom/useScrollHeight.ts b/src/hooks/dom/useScrollHeight.ts index b2eaae11..48bf7f4d 100644 --- a/src/hooks/dom/useScrollHeight.ts +++ b/src/hooks/dom/useScrollHeight.ts @@ -11,7 +11,7 @@ const getHeight = () => { body.offsetHeight, html.clientHeight, html.scrollHeight, - html.offsetHeight, + html.offsetHeight ); }; export const useScrollHeight = () => getHeight(); diff --git a/src/hooks/dom/useScrollToTop.ts b/src/hooks/dom/useScrollToTop.ts index 6127f83c..f1c5c846 100644 --- a/src/hooks/dom/useScrollToTop.ts +++ b/src/hooks/dom/useScrollToTop.ts @@ -18,6 +18,6 @@ export const useScrollToTop = (deps?: any[]) => { }); }, // eslint-disable-next-line react-hooks/exhaustive-deps - deps && Array.isArray(deps) ? deps : [], + deps && Array.isArray(deps) ? deps : [] ); }; diff --git a/src/hooks/dom/useScrollTop.ts b/src/hooks/dom/useScrollTop.ts index d8e33579..d8e7e066 100644 --- a/src/hooks/dom/useScrollTop.ts +++ b/src/hooks/dom/useScrollTop.ts @@ -1,9 +1,7 @@ import { useEffect, useState } from 'react'; export const useScrollTop = () => { - const [top, setTop] = useState( - typeof window !== 'undefined' ? window.scrollY : 0, - ); + const [top, setTop] = useState(typeof window !== 'undefined' ? window.scrollY : 0); useEffect(() => { setTop(window.scrollY); diff --git a/src/hooks/flow/useFlowCellControls.ts b/src/hooks/flow/useFlowCellControls.ts index 3e749a4f..6440ece4 100644 --- a/src/hooks/flow/useFlowCellControls.ts +++ b/src/hooks/flow/useFlowCellControls.ts @@ -6,12 +6,11 @@ export const useFlowCellControls = ( id: INode['id'], description: string | undefined, flow: FlowDisplay, - onChangeCellView: (id: INode['id'], flow: FlowDisplay) => void, + onChangeCellView: (id: INode['id'], flow: FlowDisplay) => void ) => { const onChange = useCallback( - (value: Partial) => - onChangeCellView(id, { ...flow, ...value }), - [flow, id, onChangeCellView], + (value: Partial) => onChangeCellView(id, { ...flow, ...value }), + [flow, id, onChangeCellView] ); const hasDescription = !!description && description.length > 32; diff --git a/src/hooks/flow/useFlowSetCellView.ts b/src/hooks/flow/useFlowSetCellView.ts index 8c688137..8f391dac 100644 --- a/src/hooks/flow/useFlowSetCellView.ts +++ b/src/hooks/flow/useFlowSetCellView.ts @@ -17,6 +17,6 @@ export const useFlowSetCellView = () => { showErrorToast(error); } }, - [updateNode], + [updateNode] ); }; diff --git a/src/hooks/lab/useGetLabStats.ts b/src/hooks/lab/useGetLabStats.ts index 97853d49..9a484a80 100644 --- a/src/hooks/lab/useGetLabStats.ts +++ b/src/hooks/lab/useGetLabStats.ts @@ -21,19 +21,15 @@ export const useGetLabStats = () => { heroes: lab.heroes, tags: lab.tags, }, - onSuccess: (data) => { + onSuccess: data => { lab.setHeroes(data.heroes); lab.setTags(data.tags); }, refreshInterval, - }, + } ); - const { - data: updatesData, - isValidating: isValidatingUpdates, - mutate: mutateUpdates, - } = useSWR( + const { data: updatesData, isValidating: isValidatingUpdates, mutate: mutateUpdates } = useSWR( isUser ? API.LAB.UPDATES : null, async () => { const result = await getLabUpdates(); @@ -41,27 +37,26 @@ export const useGetLabStats = () => { }, { fallbackData: lab.updates, - onSuccess: (data) => { + onSuccess: data => { lab.setUpdates(data); }, refreshInterval, - }, + } ); const heroes = useMemo(() => stats?.heroes || [], [stats]); const tags = useMemo(() => stats?.tags || [], [stats]); const updates = useMemo(() => updatesData || [], [updatesData]); - const isLoading = - (!stats || !updates) && (isValidatingStats || isValidatingUpdates); + const isLoading = (!stats || !updates) && (isValidatingStats || isValidatingUpdates); const seenNode = useCallback( async (nodeId: number) => { await mutateUpdates( - updates.filter((it) => it.id !== nodeId), - false, + updates.filter(it => it.id !== nodeId), + false ); }, - [mutateUpdates, updates], + [mutateUpdates, updates] ); return { heroes, tags, updates, isLoading, seenNode }; diff --git a/src/hooks/messages/useMessages.ts b/src/hooks/messages/useMessages.ts index 6349202d..e7614fea 100644 --- a/src/hooks/messages/useMessages.ts +++ b/src/hooks/messages/useMessages.ts @@ -11,7 +11,7 @@ const getKey = (username: string): string | null => { }; export const useMessages = (username: string) => { const { data, isValidating } = useSWR(getKey(username), async () => - apiGetUserMessages({ username }), + apiGetUserMessages({ username }) ); const messages: IMessage[] = useMemo(() => data?.messages || [], [data]); diff --git a/src/hooks/modal/useModal.ts b/src/hooks/modal/useModal.ts index 66266935..de5ce0d2 100644 --- a/src/hooks/modal/useModal.ts +++ b/src/hooks/modal/useModal.ts @@ -5,9 +5,7 @@ import { useModalStore } from '~/store/modal/useModalStore'; import { DialogComponentProps } from '~/types/modal'; export type DialogContentProps = { - [K in keyof typeof DIALOG_CONTENT]: (typeof DIALOG_CONTENT)[K] extends ( - props: infer U, - ) => any + [K in keyof typeof DIALOG_CONTENT]: typeof DIALOG_CONTENT[K] extends (props: infer U) => any ? U extends DialogComponentProps ? keyof Omit extends never ? {} @@ -23,7 +21,7 @@ export const useModal = () => { (dialog: T, props: DialogContentProps[T]) => { setCurrent(dialog, props); }, - [setCurrent], + [setCurrent] ); return { showModal, hideModal: hide, current, isOpened: !!current }; diff --git a/src/hooks/modal/useShowModal.ts b/src/hooks/modal/useShowModal.ts index 3ef0204a..57452600 100644 --- a/src/hooks/modal/useShowModal.ts +++ b/src/hooks/modal/useShowModal.ts @@ -10,6 +10,6 @@ export const useShowModal = (dialog: T) => { (props: DialogContentProps[T]) => { modal.showModal(dialog, props); }, - [dialog, modal], + [dialog, modal] ); }; diff --git a/src/hooks/navigation/useImageModal.ts b/src/hooks/navigation/useImageModal.ts index 68accfa9..ce3af6bd 100644 --- a/src/hooks/navigation/useImageModal.ts +++ b/src/hooks/navigation/useImageModal.ts @@ -11,6 +11,6 @@ export const useImageModal = () => { (images: IFile[], index: number) => { showModal({ items: images, index }); }, - [showModal], + [showModal] ); }; diff --git a/src/hooks/navigation/useNavigation.ts b/src/hooks/navigation/useNavigation.ts index b6f26c47..199801d8 100644 --- a/src/hooks/navigation/useNavigation.ts +++ b/src/hooks/navigation/useNavigation.ts @@ -17,7 +17,7 @@ export const useNavigation = () => { craHistory.push(url); } }, - [craHistory, nextRouter], + [craHistory, nextRouter] ); return { push }; diff --git a/src/hooks/node/useCreateNode.ts b/src/hooks/node/useCreateNode.ts index 6dfd10de..75b2a87a 100644 --- a/src/hooks/node/useCreateNode.ts +++ b/src/hooks/node/useCreateNode.ts @@ -16,13 +16,9 @@ export const useCreateNode = () => { if (node.is_promoted) { flow.setNodes([result.node, ...flow.nodes]); } else { - await lab.unshift({ - node: result.node, - comment_count: 0, - last_seen: node.created_at, - }); + await lab.unshift({ node: result.node, comment_count: 0, last_seen: node.created_at }); } }, - [flow, lab], + [flow, lab] ); }; diff --git a/src/hooks/node/useGrouppedComments.ts b/src/hooks/node/useGrouppedComments.ts index 22dfb3df..dde9182e 100644 --- a/src/hooks/node/useGrouppedComments.ts +++ b/src/hooks/node/useGrouppedComments.ts @@ -6,13 +6,13 @@ import { groupCommentsByUser } from '~/utils/fn'; export const useGrouppedComments = ( comments: IComment[], order: 'ASC' | 'DESC', - lastSeen?: string, + lastSeen?: string ) => useMemo( () => (order === 'DESC' ? [...comments].reverse() : comments).reduce( groupCommentsByUser(lastSeen), - [], + [] ), - [comments, lastSeen, order], + [comments, lastSeen, order] ); diff --git a/src/hooks/node/useNodeActions.ts b/src/hooks/node/useNodeActions.ts index 06bb88ae..58377560 100644 --- a/src/hooks/node/useNodeActions.ts +++ b/src/hooks/node/useNodeActions.ts @@ -6,10 +6,7 @@ import { useModal } from '~/hooks/modal/useModal'; import { INode } from '~/types'; import { showErrorToast } from '~/utils/errors/showToast'; -export const useNodeActions = ( - node: INode, - update: (node: Partial) => Promise, -) => { +export const useNodeActions = (node: INode, update: (node: Partial) => Promise) => { const { showModal } = useModal(); const onLike = useCallback(async () => { @@ -38,20 +35,17 @@ export const useNodeActions = ( const onLock = useCallback(async () => { try { - const result = await apiLockNode({ - id: node.id, - is_locked: !node.deleted_at, - }); + const result = await apiLockNode({ id: node.id, is_locked: !node.deleted_at }); await update({ deleted_at: result.deleted_at }); } catch (error) { showErrorToast(error); } }, [node.deleted_at, node.id, update]); - const onEdit = useCallback( - () => showModal(Dialog.EditNode, { nodeId: node.id! }), - [node, showModal], - ); + const onEdit = useCallback(() => showModal(Dialog.EditNode, { nodeId: node.id! }), [ + node, + showModal, + ]); return { onLike, onStar, onLock, onEdit }; }; diff --git a/src/hooks/node/useNodeAudios.ts b/src/hooks/node/useNodeAudios.ts index 3149a171..1ad28cf1 100644 --- a/src/hooks/node/useNodeAudios.ts +++ b/src/hooks/node/useNodeAudios.ts @@ -4,8 +4,7 @@ import { UploadType } from '~/constants/uploads'; import { INode } from '~/types'; export const useNodeAudios = (node: INode) => { - return useMemo( - () => node.files.filter((file) => file && file.type === UploadType.Audio), - [node.files], - ); + return useMemo(() => node.files.filter(file => file && file.type === UploadType.Audio), [ + node.files, + ]); }; diff --git a/src/hooks/node/useNodeFormFormik.ts b/src/hooks/node/useNodeFormFormik.ts index cc723a4f..089f5ae2 100644 --- a/src/hooks/node/useNodeFormFormik.ts +++ b/src/hooks/node/useNodeFormFormik.ts @@ -1,11 +1,6 @@ import { useCallback, useRef } from 'react'; -import { - FormikConfig, - FormikHelpers, - useFormik, - useFormikContext, -} from 'formik'; +import { FormikConfig, FormikHelpers, useFormik, useFormikContext } from 'formik'; import { object } from 'yup'; import { INode } from '~/types'; @@ -15,31 +10,31 @@ import { showErrorToast } from '~/utils/errors/showToast'; const validationSchema = object().shape({}); -const afterSubmit = - ({ resetForm, setSubmitting, setErrors }: FormikHelpers) => - (error?: unknown) => { - setSubmitting(false); +const afterSubmit = ({ resetForm, setSubmitting, setErrors }: FormikHelpers) => ( + error?: unknown +) => { + setSubmitting(false); - if (error) { - showErrorToast(error); - return; - } + if (error) { + showErrorToast(error); + return; + } - if (getValidationErrors(error)) { - setErrors(getValidationErrors(error)!); - return; - } + if (getValidationErrors(error)) { + setErrors(getValidationErrors(error)!); + return; + } - if (resetForm) { - resetForm(); - } - }; + if (resetForm) { + resetForm(); + } +}; export const useNodeFormFormik = ( values: INode, uploader: Uploader, stopEditing: () => void, - sendSaveRequest: (node: INode) => Promise, + sendSaveRequest: (node: INode) => Promise ) => { const { current: initialValues } = useRef(values); @@ -58,7 +53,7 @@ export const useNodeFormFormik = ( afterSubmit(helpers)(error); } }, - [sendSaveRequest, uploader.files], + [sendSaveRequest, uploader.files] ); return useFormik({ diff --git a/src/hooks/node/useNodeImages.ts b/src/hooks/node/useNodeImages.ts index 08cc1947..e162be05 100644 --- a/src/hooks/node/useNodeImages.ts +++ b/src/hooks/node/useNodeImages.ts @@ -4,8 +4,7 @@ import { UploadType } from '~/constants/uploads'; import { INode } from '~/types'; export const useNodeImages = (node: INode) => { - return useMemo( - () => node.files.filter((file) => file && file.type === UploadType.Image), - [node.files], - ); + return useMemo(() => node.files.filter(file => file && file.type === UploadType.Image), [ + node.files, + ]); }; diff --git a/src/hooks/node/useUpdateNode.ts b/src/hooks/node/useUpdateNode.ts index cc1ad033..1a6ff356 100644 --- a/src/hooks/node/useUpdateNode.ts +++ b/src/hooks/node/useUpdateNode.ts @@ -27,6 +27,6 @@ export const useUpdateNode = (id: number) => { await lab.updateNode(result.node.id!, result.node); } }, - [update, flow, lab], + [update, flow, lab] ); }; diff --git a/src/hooks/profile/useGetProfile.ts b/src/hooks/profile/useGetProfile.ts index 3e8c9308..8d3eacbc 100644 --- a/src/hooks/profile/useGetProfile.ts +++ b/src/hooks/profile/useGetProfile.ts @@ -20,7 +20,7 @@ export const useGetProfile = (username?: string) => { }, { refreshInterval: 60000, - }, + } ); const profile = data || EMPTY_USER; @@ -29,7 +29,7 @@ export const useGetProfile = (username?: string) => { async (user: Partial) => { await mutate({ ...profile, ...user }); }, - [mutate, profile], + [mutate, profile] ); return { profile, isLoading: !data && isValidating, update }; diff --git a/src/hooks/search/useSearch.ts b/src/hooks/search/useSearch.ts index a38dd2f0..4fa3b874 100644 --- a/src/hooks/search/useSearch.ts +++ b/src/hooks/search/useSearch.ts @@ -9,19 +9,21 @@ import { flatten } from '~/utils/ramda'; const RESULTS_COUNT = 20; -const getKey: (text: string) => SWRInfiniteKeyLoader = - (text) => (pageIndex, previousPageData: INode[]) => { - if ((pageIndex > 0 && !previousPageData?.length) || !text) return null; +const getKey: (text: string) => SWRInfiniteKeyLoader = text => ( + pageIndex, + previousPageData: INode[] +) => { + if ((pageIndex > 0 && !previousPageData?.length) || !text) return null; - const props: GetSearchResultsRequest = { - text, - skip: pageIndex * RESULTS_COUNT, - take: RESULTS_COUNT, - }; - - return JSON.stringify(props); + const props: GetSearchResultsRequest = { + text, + skip: pageIndex * RESULTS_COUNT, + take: RESULTS_COUNT, }; + return JSON.stringify(props); +}; + export const useSearch = () => { const [searchText, setSearchText] = useState(''); const [debouncedSearchText, setDebouncedSearchText] = useState(''); @@ -38,7 +40,7 @@ export const useSearch = () => { const result = await getSearchResults(props); return result.nodes; - }, + } ); const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); diff --git a/src/hooks/tag/useTagAutocomplete.ts b/src/hooks/tag/useTagAutocomplete.ts index 493690c8..8cbfb495 100644 --- a/src/hooks/tag/useTagAutocomplete.ts +++ b/src/hooks/tag/useTagAutocomplete.ts @@ -26,5 +26,5 @@ export const useTagAutocomplete = ( }, ); - return useMemo(() => (search ? (data ?? []) : []), [data, search]); + return useMemo(() => (search ? data ?? [] : []), [data, search]); }; diff --git a/src/hooks/tag/useTagNodes.ts b/src/hooks/tag/useTagNodes.ts index 53d02b12..7df94f90 100644 --- a/src/hooks/tag/useTagNodes.ts +++ b/src/hooks/tag/useTagNodes.ts @@ -9,11 +9,13 @@ import { flatten, isNil } from '~/utils/ramda'; const PAGE_SIZE = 10; -const getKey: (tag: string) => SWRInfiniteKeyLoader = - (tag) => (pageIndex, previousPageData: INode[]) => { - if (pageIndex > 0 && !previousPageData?.length) return null; - return `${API.TAG.NODES}?tag=${tag}&page=${pageIndex}`; - }; +const getKey: (tag: string) => SWRInfiniteKeyLoader = tag => ( + pageIndex, + previousPageData: INode[] +) => { + if (pageIndex > 0 && !previousPageData?.length) return null; + return `${API.TAG.NODES}?tag=${tag}&page=${pageIndex}`; +}; const extractKey = (key: string) => { const re = new RegExp(`${API.TAG.NODES}\\?tag=[^&]+&page=(\\d+)`); @@ -37,7 +39,7 @@ export const useTagNodes = (tag: string) => { }); return result.nodes; - }, + } ); const nodes = useMemo(() => flatten(data || []), [data]); @@ -45,12 +47,5 @@ export const useTagNodes = (tag: string) => { const loadMore = useCallback(() => setSize(size + 1), [setSize, size]); - return { - nodes, - hasMore, - loadMore, - isLoading: !data && isValidating, - mutate, - data, - }; + return { nodes, hasMore, loadMore, isLoading: !data && isValidating, mutate, data }; }; diff --git a/src/hooks/updates/useUpdates.ts b/src/hooks/updates/useUpdates.ts index 9f1d4be0..91614788 100644 --- a/src/hooks/updates/useUpdates.ts +++ b/src/hooks/updates/useUpdates.ts @@ -9,7 +9,7 @@ export const useUpdates = () => { const { data } = useSWR( isUser ? API.USER.GET_UPDATES : null, () => apiAuthGetUpdates({ exclude_dialogs: 0, last: '' }), - { refreshInterval: 5 * 60 * 1000 }, + { refreshInterval: 5 * 60 * 1000 } ); const borisCommentedAt = data?.boris?.commented_at || ''; diff --git a/src/reportWebVitals.js b/src/reportWebVitals.js index 532f29b0..5253d3ad 100644 --- a/src/reportWebVitals.js +++ b/src/reportWebVitals.js @@ -1,4 +1,4 @@ -const reportWebVitals = (onPerfEntry) => { +const reportWebVitals = onPerfEntry => { if (onPerfEntry && onPerfEntry instanceof Function) { import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { getCLS(onPerfEntry); diff --git a/src/store/flow/FlowStore.ts b/src/store/flow/FlowStore.ts index f7f689a9..dab1c742 100644 --- a/src/store/flow/FlowStore.ts +++ b/src/store/flow/FlowStore.ts @@ -24,13 +24,11 @@ export class FlowStore { /** removes node from updated after user seen it */ seenNode = (nodeId: number) => { - this.setUpdated(this.updated.filter((node) => node.id !== nodeId)); + this.setUpdated(this.updated.filter(node => node.id !== nodeId)); }; /** replaces node with value */ updateNode = (id: number, node: Partial) => { - this.setNodes( - this.nodes.map((it) => (it.id === id ? { ...it, ...node } : it)), - ); + this.setNodes(this.nodes.map(it => (it.id === id ? { ...it, ...node } : it))); }; } diff --git a/src/store/metadata/MetadataStore.tsx b/src/store/metadata/MetadataStore.tsx index 61105cd7..68a0b596 100644 --- a/src/store/metadata/MetadataStore.tsx +++ b/src/store/metadata/MetadataStore.tsx @@ -12,9 +12,7 @@ export class MetadataStore { pending: string[] = []; constructor( - protected apiMetadataLoader: ( - ids: string[], - ) => Promise>, + protected apiMetadataLoader: (ids: string[]) => Promise> ) { makeAutoObservable(this); } @@ -61,7 +59,7 @@ export class MetadataStore { try { const result = await this.apiMetadataLoader(items); - const fetchedIDs = values(result).map((it) => it.address); + const fetchedIDs = values(result).map(it => it.address); runInAction(() => { this.pushMetadataItems(result); @@ -74,11 +72,7 @@ export class MetadataStore { /** adds items to queue */ enqueue = (id: string) => { - if ( - this.queue.includes(id) || - keys(this.metadata).includes(id) || - this.pending.includes(id) - ) { + if (this.queue.includes(id) || keys(this.metadata).includes(id) || this.pending.includes(id)) { return; } diff --git a/src/types/index.ts b/src/types/index.ts index 54ef359a..04703abb 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -153,13 +153,13 @@ export const NOTIFICATION_TYPES = { }; export type IMessageNotification = { - type: (typeof NOTIFICATION_TYPES)['message']; + type: typeof NOTIFICATION_TYPES['message']; content: Partial; created_at: string; }; export type ICommentNotification = { - type: (typeof NOTIFICATION_TYPES)['comment']; + type: typeof NOTIFICATION_TYPES['comment']; content: Partial; created_at: string; }; diff --git a/src/types/notifications/index.ts b/src/types/notifications/index.ts index c23b3f90..5a34538f 100644 --- a/src/types/notifications/index.ts +++ b/src/types/notifications/index.ts @@ -2,7 +2,6 @@ import { ShallowUser } from '../auth'; export interface NotificationItem { id: number; - itemId: number; url: string; type: NotificationType; title: string; diff --git a/src/types/sidebar/index.ts b/src/types/sidebar/index.ts index 2e029c64..4d11b90d 100644 --- a/src/types/sidebar/index.ts +++ b/src/types/sidebar/index.ts @@ -5,14 +5,15 @@ import type { SidebarComponents } from '~/constants/sidebar/components'; export type SidebarComponent = keyof SidebarComponents; // TODO: use it to store props for sidebar -export type SidebarProps = - SidebarComponents[T] extends FunctionComponent - ? U extends object - ? U extends SidebarComponentProps - ? Omit> - : U +export type SidebarProps< + T extends SidebarComponent +> = SidebarComponents[T] extends FunctionComponent + ? U extends object + ? U extends SidebarComponentProps + ? Omit> : U - : {}; + : U + : {}; export interface SidebarComponentProps { onRequestClose: () => void; openSidebar: (name: T, props: SidebarProps) => void; diff --git a/src/utils/color.ts b/src/utils/color.ts index b6e67589..f37a7518 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -1,19 +1,9 @@ -import { - adjustHue, - darken, - desaturate, - parseToHsla, - transparentize, -} from 'color2k'; +import { adjustHue, darken, desaturate, parseToHsla, transparentize } from 'color2k'; import { DEFAULT_DOMINANT_COLOR } from '~/constants/node'; import { stringToColour } from '~/utils/dom'; -export const normalizeBrightColor = ( - color?: string, - saturationExp = 3, - lightnessExp = 3, -) => { +export const normalizeBrightColor = (color?: string, saturationExp = 3, lightnessExp = 3) => { if (!color) { return ''; } @@ -22,23 +12,12 @@ export const normalizeBrightColor = ( const saturation = hsla[1]; const lightness = hsla[2]; - const desaturated = - saturationExp > 1 ? desaturate(color, saturation ** saturationExp) : color; - return lightnessExp > 1 - ? darken(desaturated, lightness ** lightnessExp) - : desaturated; + const desaturated = saturationExp > 1 ? desaturate(color, saturation ** saturationExp) : color; + return lightnessExp > 1 ? darken(desaturated, lightness ** lightnessExp) : desaturated; }; -export const generateColorTriplet = ( - val: string, - saturation: number, - lightness: number, -) => { - const color = normalizeBrightColor( - stringToColour(val), - saturation, - lightness, - ); +export const generateColorTriplet = (val: string, saturation: number, lightness: number) => { + const color = normalizeBrightColor(stringToColour(val), saturation, lightness); return [ color, @@ -52,13 +31,9 @@ export const generateGradientFromColor = ( saturation = 3, lightness = 3, angle = 155, - opacity = 1, + opacity = 1 ) => { - const [first, second, third] = generateColorTriplet( - val, - saturation, - lightness, - ).map((it) => { + const [first, second, third] = generateColorTriplet(val, saturation, lightness).map(it => { if (opacity > 1 || opacity < 0) { return it; } diff --git a/src/utils/config/index.ts b/src/utils/config/index.ts index 82386766..2e836055 100644 --- a/src/utils/config/index.ts +++ b/src/utils/config/index.ts @@ -6,6 +6,5 @@ export const CONFIG = { // image storage endpoint (sames as backend, but with /static usualy) remoteCurrent: process.env.NEXT_PUBLIC_REMOTE_CURRENT || '', // transitional prop, marks migration to nextjs - isNextEnvironment: - !!process.env.NEXT_PUBLIC_REMOTE_CURRENT || typeof window === 'undefined', + isNextEnvironment: !!process.env.NEXT_PUBLIC_REMOTE_CURRENT || typeof window === 'undefined', }; diff --git a/src/utils/fn.ts b/src/utils/fn.ts index 482ea41c..53b461be 100644 --- a/src/utils/fn.ts +++ b/src/utils/fn.ts @@ -3,19 +3,11 @@ import { differenceInDays, isAfter, isValid, parseISO } from 'date-fns'; import { IComment, ICommentGroup } from '~/types'; import { curry, insert, nth, path, remove } from '~/utils/ramda'; -export const moveArrItem = curry((at, to, list) => - insert(to, nth(at, list), remove(at, 1, list)), -); +export const moveArrItem = curry((at, to, list) => insert(to, nth(at, list), remove(at, 1, list))); export const objFromArray = (array: any[], key: string) => - array.reduce( - (obj, el) => (key && el[key] ? { ...obj, [el[key]]: el } : obj), - {}, - ); + array.reduce((obj, el) => (key && el[key] ? { ...obj, [el[key]]: el } : obj), {}); -const compareCommentDates = ( - commentDateValue?: string, - lastSeenDateValue?: string, -) => { +const compareCommentDates = (commentDateValue?: string, lastSeenDateValue?: string) => { if (!commentDateValue || !lastSeenDateValue) { return false; } @@ -45,49 +37,45 @@ const getCommentDistance = (firstDate?: string, secondDate?: string) => { } }; -export const groupCommentsByUser = - (lastSeen?: string) => - (grouppedComments: ICommentGroup[], comment: IComment): ICommentGroup[] => { - const last: ICommentGroup | undefined = path( - [grouppedComments.length - 1], - grouppedComments, - ); +export const groupCommentsByUser = (lastSeen?: string) => ( + grouppedComments: ICommentGroup[], + comment: IComment +): ICommentGroup[] => { + const last: ICommentGroup | undefined = path([grouppedComments.length - 1], grouppedComments); - if (!comment.user) { - return grouppedComments; - } + if (!comment.user) { + return grouppedComments; + } - return [ - ...(!last || path(['user', 'id'], last) !== path(['user', 'id'], comment) - ? [ - // add new group - ...grouppedComments, - { - user: comment.user, - comments: [comment], - distancesInDays: [0], - ids: [comment.id], - hasNew: compareCommentDates(comment.created_at, lastSeen), - }, - ] - : [ - // append to last group - ...grouppedComments.slice(0, grouppedComments.length - 1), - { - ...last, - distancesInDays: [ - ...last.distancesInDays, - getCommentDistance( - comment?.created_at, - last.comments[last.comments.length - 1]?.created_at, - ), - ], - comments: [...last.comments, comment], - ids: [...last.ids, comment.id], - hasNew: - last.hasNew || - compareCommentDates(comment.created_at, lastSeen), - }, - ]), - ]; - }; + return [ + ...(!last || path(['user', 'id'], last) !== path(['user', 'id'], comment) + ? [ + // add new group + ...grouppedComments, + { + user: comment.user, + comments: [comment], + distancesInDays: [0], + ids: [comment.id], + hasNew: compareCommentDates(comment.created_at, lastSeen), + }, + ] + : [ + // append to last group + ...grouppedComments.slice(0, grouppedComments.length - 1), + { + ...last, + distancesInDays: [ + ...last.distancesInDays, + getCommentDistance( + comment?.created_at, + last.comments[last.comments.length - 1]?.created_at + ), + ], + comments: [...last.comments, comment], + ids: [...last.ids, comment.id], + hasNew: last.hasNew || compareCommentDates(comment.created_at, lastSeen), + }, + ]), + ]; +}; diff --git a/src/utils/providers/ProfileProvider.tsx b/src/utils/providers/ProfileProvider.tsx index 8e33d872..4a7f0b8a 100644 --- a/src/utils/providers/ProfileProvider.tsx +++ b/src/utils/providers/ProfileProvider.tsx @@ -18,16 +18,11 @@ const ProfileContext = createContext({ isLoading: false, }); -export const ProfileProvider: FC = ({ - children, - username, -}) => { +export const ProfileProvider: FC = ({ children, username }) => { const { profile, isLoading } = useGetProfile(username); return ( - - {children} - + {children} ); }; diff --git a/src/utils/splitText.ts b/src/utils/splitText.ts index 3a841c15..f7d1bb0a 100644 --- a/src/utils/splitText.ts +++ b/src/utils/splitText.ts @@ -2,12 +2,10 @@ import { flatten, isEmpty } from '~/utils/ramda'; export const splitTextByYoutube = (strings: string[]): string[] => flatten( - strings.map((str) => - str.split( - /(https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch)?(?:\?v=)?[\w\-&=]+)/, - ), - ), + strings.map(str => + str.split(/(https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be)\/(?:watch)?(?:\?v=)?[\w\-&=]+)/) + ) ); export const splitTextOmitEmpty = (strings: string[]): string[] => - strings.map((el) => el.trim()).filter((el) => !isEmpty(el)); + strings.map(el => el.trim()).filter(el => !isEmpty(el)); diff --git a/src/utils/ssr/getPageTitle.ts b/src/utils/ssr/getPageTitle.ts index e0a80215..d564ea98 100644 --- a/src/utils/ssr/getPageTitle.ts +++ b/src/utils/ssr/getPageTitle.ts @@ -1,4 +1,4 @@ /** just combines title elements to form title of the page */ export const getPageTitle = (...props: string[]): string => { - return ['Убежище', ...props].filter((it) => it.trim()).join(' • '); + return ['Убежище', ...props].filter(it => it.trim()).join(' • '); }; diff --git a/src/utils/tag.ts b/src/utils/tag.ts index b897ab24..4bbf4d3f 100644 --- a/src/utils/tag.ts +++ b/src/utils/tag.ts @@ -3,13 +3,11 @@ import { ITag } from '~/types'; export const separateTags = (tags: Partial[]): Partial[][] => (tags || []).reduce( (obj, tag) => - tag?.title?.substr(0, 1) === '/' - ? [[...obj[0], tag], obj[1]] - : [obj[0], [...obj[1], tag]], - [[], []] as Partial[][], + tag?.title?.substr(0, 1) === '/' ? [[...obj[0], tag], obj[1]] : [obj[0], [...obj[1], tag]], + [[], []] as Partial[][] ); export const separateTagOptions = (options: string[]): string[][] => - separateTags(options.map((title): Partial => ({ title }))).map((item) => - item.filter((tag) => tag.title).map(({ title }) => title!), + separateTags(options.map((title): Partial => ({ title }))).map(item => + item.filter(tag => tag.title).map(({ title }) => title!) ); diff --git a/src/utils/trans.ts b/src/utils/trans.ts index cc8cab41..54445e43 100644 --- a/src/utils/trans.ts +++ b/src/utils/trans.ts @@ -1,6 +1,5 @@ import { ERROR_LITERAL, ERRORS } from '~/constants/errors'; import { ValueOf } from '~/types'; -export const t = ( - string: ValueOf, -): ValueOf => ERROR_LITERAL[string] || string; +export const t = (string: ValueOf): ValueOf => + ERROR_LITERAL[string] || string; diff --git a/src/utils/uploader.ts b/src/utils/uploader.ts index 4e651c2e..1abfcdc6 100644 --- a/src/utils/uploader.ts +++ b/src/utils/uploader.ts @@ -2,10 +2,10 @@ import { FILE_MIMES, UploadType } from '~/constants/uploads'; import { isMimeOfImage } from '~/utils/validators'; /** if file is image, returns data-uri of thumbnail */ -export const uploadGetThumb = async (file) => { +export const uploadGetThumb = async file => { if (!file.type || !isMimeOfImage(file.type)) return ''; - return new Promise((resolve) => { + return new Promise(resolve => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result?.toString() || ''); reader.readAsDataURL(file); @@ -15,17 +15,14 @@ export const uploadGetThumb = async (file) => { /** returns UploadType by file */ export const getFileType = (file: File): UploadType | undefined => ((file.type && - Object.keys(FILE_MIMES).find((mime) => - FILE_MIMES[mime].includes(file.type), - )) as UploadType) || undefined; + Object.keys(FILE_MIMES).find(mime => FILE_MIMES[mime].includes(file.type))) as UploadType) || + undefined; /** getImageFromPaste returns any images from paste event */ -export const getImageFromPaste = ( - event: ClipboardEvent, -): Promise => { +export const getImageFromPaste = (event: ClipboardEvent): Promise => { const items = event.clipboardData?.items; - return new Promise((resolve) => { + return new Promise(resolve => { for (let index in items) { const item = items[index]; @@ -34,7 +31,7 @@ export const getImageFromPaste = ( const reader = new FileReader(); const type = item.type; - reader.onload = function (e) { + reader.onload = function(e) { if (!e.target?.result) { return; } @@ -43,7 +40,7 @@ export const getImageFromPaste = ( new File([e.target?.result], 'paste.png', { type, lastModified: new Date().getTime(), - }), + }) ); }; diff --git a/src/utils/validators.ts b/src/utils/validators.ts index a0a9426d..dcbb6144 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -1,4 +1,3 @@ import { IMAGE_MIME_TYPES } from '~/constants/uploads'; -export const isMimeOfImage = (mime): boolean => - !!mime && IMAGE_MIME_TYPES.indexOf(mime) >= 0; +export const isMimeOfImage = (mime): boolean => !!mime && IMAGE_MIME_TYPES.indexOf(mime) >= 0; diff --git a/yarn.lock b/yarn.lock index 7a7ea181..5ccef8ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,11 +221,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@pkgr/core@^0.1.0": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.1.1.tgz#1ec17e2edbec25c8306d424ecfbf13c7de1aaa31" - integrity sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA== - "@polka/url@^1.0.0-next.20": version "1.0.0-next.21" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" @@ -1211,14 +1206,6 @@ eslint-plugin-import@^2.25.4: resolve "^1.20.0" tsconfig-paths "^3.12.0" -eslint-plugin-prettier@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz#c4af01691a6fa9905207f0fbba0d7bea0902cce5" - integrity sha512-qJ+y0FfCp/mQYQ/vWQ3s7eUlFEL4PyKfAJxsnYTJ4YT73nsJBWqmEpFryxV9OeUiqmsTsYJ5Y+KDNaeP31wrRw== - dependencies: - prettier-linter-helpers "^1.0.0" - synckit "^0.9.1" - 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" @@ -1407,11 +1394,6 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@^1.1.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" - integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== - fast-fifo@^1.1.0, fast-fifo@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" @@ -2470,17 +2452,10 @@ prelude-ls@^1.2.1: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^3.0.0: - version "3.4.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.4.2.tgz#a5ce1fb522a588bf2b78ca44c6e6fe5aa5a2b13f" - integrity sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ== +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== pretty-format@^26.6.2: version "26.6.2" @@ -3112,14 +3087,6 @@ swr@^1.0.1: resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.0.tgz#8649f6e9131ce94bbcf7ffd65c21334da3d1ec20" integrity sha512-C3IXeKOREn0jQ1ewXRENE7ED7jjGbFTakwB64eLACkCqkF/A0N2ckvpCTftcaSYi5yV36PzoehgVCOVRmtECcA== -synckit@^0.9.1: - version "0.9.2" - resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.9.2.tgz#a3a935eca7922d48b9e7d6c61822ee6c3ae4ec62" - integrity sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw== - dependencies: - "@pkgr/core" "^0.1.0" - tslib "^2.6.2" - table@^6.0.9: version "6.8.0" resolved "https://registry.yarnpkg.com/table/-/table-6.8.0.tgz#87e28f14fa4321c3377ba286f07b79b281a3b3ca" @@ -3254,11 +3221,6 @@ tslib@^2.0.3, tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== -tslib@^2.6.2: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tsutils@^3.21.0: version "3.21.0" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"