diff --git a/.eslintignore b/.eslintignore index edc3a77e7b9..ca60c6693b2 100644 --- a/.eslintignore +++ b/.eslintignore @@ -4,4 +4,3 @@ coverage e2e/docker android ios -.eslintrc.js \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js index dba025b0233..fcbada21558 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,53 +5,33 @@ module.exports = { extensions: ['.ts', '.tsx', '.js', '.ios.js', '.android.js', '.native.js', '.ios.tsx', '.android.tsx'] }, typescript: { - alwaysTryTypes: true, project: './tsconfig.json' } }, 'import/parsers': { '@typescript-eslint/parser': ['.ts', '.tsx'] - // plugins: ['@typescript-eslint'], - // rules: { - // '@typescript-eslint/consistent-type-imports': [ - // 'error', - // { - // prefer: 'type-imports', // enforce `import type` - // disallowTypeAnnotations: true // disallow `import { type Foo }` - // // fixStyle: 'inline-type-imports' // keeps type imports inline rather than grouped - // } - // ] - // } + }, + react: { + version: 'detect' } }, parser: '@babel/eslint-parser', - extends: ['plugin:jest/recommended', '@rocket.chat/eslint-config', 'prettier', 'plugin:react-hooks/recommended'], + extends: [ + '@rocket.chat/eslint-config', + 'plugin:react/recommended', + 'plugin:react-hooks/recommended', + 'plugin:prettier/recommended', + 'prettier' + ], parserOptions: { sourceType: 'module', - ecmaVersion: 2017, - ecmaFeatures: { - experimentalObjectRestSpread: true, - jsx: true, - legacyDecorators: true - } + ecmaVersion: 2024 }, - plugins: ['react', 'jsx-a11y', 'import', 'react-native', '@babel', 'react-hooks', 'jest'], + plugins: ['import', 'react-native', '@babel'], env: { - browser: true, - commonjs: true, - es6: true, - node: true, - jquery: true, - mocha: true, - jest: true, - 'jest/globals': true + es6: true }, rules: { - 'react-hooks/set-state-in-effect': 1, - 'react-hooks/immutability': 1, - 'react-hooks/refs': 1, - 'import/named': 'error', - 'import/no-unresolved': 'error', 'import/extensions': [ 'error', 'ignorePackages', @@ -62,122 +42,34 @@ module.exports = { tsx: 'warning' } ], - 'react/jsx-filename-extension': [ - 1, - { - extensions: ['.js', '.jsx', '.ts', '.tsx'] - } - ], - 'react/require-default-props': [0], - 'ordered-imports': [0], - 'react/no-did-mount-set-state': 0, - 'react/no-multi-comp': [0], - 'react/jsx-indent-props': [2, 'tab'], - 'jsx-quotes': [2, 'prefer-single'], - 'jsx-a11y/href-no-hash': 0, - 'jsx-a11y/aria-role': 0, - 'import/prefer-default-export': 0, - 'import/no-cycle': 2, + 'import/named': 'error', + 'import/no-cycle': 'error', + 'import/no-unresolved': 'error', 'import/order': [ 'error', { 'newlines-between': 'ignore' } ], - camelcase: 0, - 'no-underscore-dangle': 0, - 'no-return-assign': 0, - 'no-param-reassign': 0, - 'no-tabs': 0, - 'no-multi-spaces': 2, - 'no-eval': 2, - 'no-extend-native': 2, - 'no-multi-str': 2, - 'no-use-before-define': 2, - 'no-const-assign': 2, - 'no-cond-assign': 2, - 'no-constant-condition': 2, - 'no-control-regex': 2, - 'no-debugger': 2, - 'no-delete-var': 2, - 'no-dupe-keys': 2, - 'no-dupe-args': 2, - 'no-dupe-class-members': 2, - 'no-duplicate-case': 2, - 'no-else-return': [0, { allowElseIf: true }], - 'no-empty': 2, - 'no-empty-character-class': 2, - 'no-ex-assign': 2, - 'no-extra-boolean-cast': 2, - 'no-extra-semi': 2, - 'no-fallthrough': 2, - 'no-func-assign': 2, - 'no-inner-declarations': [2, 'functions'], - 'no-invalid-regexp': 2, - 'no-irregular-whitespace': 2, - 'no-mixed-spaces-and-tabs': 1, - 'no-sparse-arrays': 2, - 'no-negated-in-lhs': 2, - 'no-obj-calls': 2, - 'no-octal': 2, - 'no-redeclare': 2, - 'no-regex-spaces': 2, - 'no-undef': 2, - 'no-unreachable': 2, - 'no-unused-expressions': 0, + 'react/display-name': 'off', + 'react/jsx-fragments': ['error', 'syntax'], + 'react/jsx-key': 'off', + 'react/no-direct-mutation-state': 'off', + 'react/prop-types': 'off', + 'react/react-in-jsx-scope': 'off', + 'react-hooks/set-state-in-effect': 'warn', + 'react-hooks/immutability': 'warn', + 'react-hooks/refs': 'warn', + 'react-native/no-color-literals': 'off', + 'react-native/no-inline-styles': 'off', + 'react-native/no-raw-text': 'off', + 'react-native/no-single-element-style-arrays': 'error', + 'react-native/no-unused-styles': 'error', + 'react-native/split-platform-components': 'off', 'no-unused-vars': 'off', - 'max-len': 0, - 'react/jsx-uses-vars': 2, - 'no-void': 2, - 'no-var': 2, - 'one-var': [2, 'never'], - 'no-lonely-if': 2, - 'no-trailing-spaces': 2, - complexity: [1, 31], - 'space-in-parens': [2, 'never'], - 'space-before-blocks': [2, 'always'], - indent: 'off', - 'eol-last': [2, 'always'], - 'comma-dangle': [2, 'never'], - 'keyword-spacing': 2, - 'block-spacing': 2, - 'brace-style': [2, '1tbs', { allowSingleLine: true }], - 'computed-property-spacing': 2, - 'comma-spacing': 2, - 'comma-style': 2, - 'guard-for-in': 2, - 'wrap-iife': 2, - 'block-scoped-var': 2, - curly: [2, 'all'], - eqeqeq: [2, 'allow-null'], - 'new-cap': 'off', - 'use-isnan': 2, - 'valid-typeof': 2, - 'linebreak-style': 0, - 'prefer-template': 2, - quotes: [1, 'single'], - semi: [2, 'always'], - 'prefer-const': 2, - 'object-shorthand': 2, - 'consistent-return': 0, - 'global-require': 'off', - 'react-native/no-unused-styles': 2, - 'react/jsx-one-expression-per-line': 0, - 'require-await': 2, - 'func-names': 0, - 'react/static-property-placement': [0], - 'arrow-parens': ['warn', 'as-needed', { requireForBlockBody: true }], - 'react/jsx-curly-newline': [0], - 'react/state-in-constructor': [0], - 'no-async-promise-executor': [0], - 'max-classes-per-file': [0], - 'no-multiple-empty-lines': [0], - 'no-sequences': 'off', - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn' - }, - globals: { - __DEV__: true + 'no-void': 'error', + 'new-cap': 'error', + 'require-await': 'error' }, overrides: [ { @@ -186,50 +78,13 @@ module.exports = { 'plugin:@typescript-eslint/recommended', 'plugin:@typescript-eslint/eslint-recommended', '@rocket.chat/eslint-config', + 'plugin:prettier/recommended', 'prettier' ], parser: '@typescript-eslint/parser', - parserOptions: { - sourceType: 'module', - ecmaVersion: 2018, - warnOnUnsupportedTypeScriptVersion: false, - ecmaFeatures: { - experimentalObjectRestSpread: true, - legacyDecorators: true - } - }, - plugins: ['react', '@typescript-eslint'], rules: { - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-empty-function': [0], - '@typescript-eslint/ban-types': [0], - 'func-call-spacing': 'off', - 'jsx-quotes': ['error', 'prefer-single'], - indent: 'off', - 'comma-dangle': [2, 'never'], - 'no-return-assign': 0, - 'no-dupe-class-members': 'off', - 'no-extra-parens': 'off', - 'no-spaced-func': 'off', - 'no-unused-vars': 'off', - 'no-useless-constructor': 'off', - 'no-use-before-define': 'off', - 'react/jsx-uses-react': 'error', - 'react/jsx-uses-vars': 'error', - 'react/jsx-no-undef': 'error', - 'react/jsx-fragments': ['error', 'syntax'], '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/indent': 'off', - '@typescript-eslint/no-extra-parens': 'off', - '@typescript-eslint/no-dupe-class-members': 'error', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': [ - 'error', - { - argsIgnorePattern: '^_', - ignoreRestSiblings: true - } - ], + '@typescript-eslint/ban-types': 'off', '@typescript-eslint/consistent-type-imports': [ 'error', { @@ -238,14 +93,31 @@ module.exports = { fixStyle: 'inline-type-imports' } ], + '@typescript-eslint/indent': 'off', + '@typescript-eslint/no-dupe-class-members': 'error', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-extra-parens': 'off', + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'all', + argsIgnorePattern: '^_' + } + ], + '@typescript-eslint/no-var-requires': 'off', + 'no-return-assign': 'off', + 'no-dupe-class-members': 'off', + 'no-extra-parens': 'off', + 'no-spaced-func': 'off', + 'no-unused-vars': 'off', + 'no-useless-constructor': 'off', + 'no-use-before-define': 'off', 'new-cap': 'off', - 'lines-between-class-members': 'off', - 'react-hooks/rules-of-hooks': 'error', - 'react-hooks/exhaustive-deps': 'warn', - 'jest/no-conditional-expect': 'off' + 'lines-between-class-members': 'off' }, globals: { - JSX: true + JSX: 'readonly' }, settings: { 'import/resolver': { @@ -256,10 +128,13 @@ module.exports = { } }, { - files: ['e2e/**'], - rules: { - 'no-await-in-loop': 0, - 'jest/expect-expect': 'off' + files: ['jest.setup.js', '__mocks__/**/*.js', '**/*.test.{js,ts,tsx}'], + extends: ['plugin:jest/recommended'] + }, + { + files: ['index.js', 'app/**/*.{js,ts,tsx}'], + env: { + 'react-native/react-native': true } } ] diff --git a/__mocks__/react-native-mmkv.js b/__mocks__/react-native-mmkv.js index 3288748482c..44b12dcf0c9 100644 --- a/__mocks__/react-native-mmkv.js +++ b/__mocks__/react-native-mmkv.js @@ -84,7 +84,7 @@ export class MMKV { } notifyListeners(key) { - this.listeners.forEach((listener) => { + this.listeners.forEach(listener => { try { listener(key); } catch (error) { @@ -102,7 +102,7 @@ export function useMMKVString(key, mmkvInstance) { const [value, setValue] = useState(() => mmkvInstance.getString(key)); useEffect(() => { - const listener = mmkvInstance.addOnValueChangedListener((changedKey) => { + const listener = mmkvInstance.addOnValueChangedListener(changedKey => { if (changedKey === key || changedKey === undefined) { setValue(mmkvInstance.getString(key)); } @@ -110,7 +110,7 @@ export function useMMKVString(key, mmkvInstance) { return () => listener.remove(); }, [key, mmkvInstance]); - const setStoredValue = (newValue) => { + const setStoredValue = newValue => { if (newValue === undefined) { mmkvInstance.delete(key); } else { @@ -126,7 +126,7 @@ export function useMMKVNumber(key, mmkvInstance) { const [value, setValue] = useState(() => mmkvInstance.getNumber(key)); useEffect(() => { - const listener = mmkvInstance.addOnValueChangedListener((changedKey) => { + const listener = mmkvInstance.addOnValueChangedListener(changedKey => { if (changedKey === key || changedKey === undefined) { setValue(mmkvInstance.getNumber(key)); } @@ -134,7 +134,7 @@ export function useMMKVNumber(key, mmkvInstance) { return () => listener.remove(); }, [key, mmkvInstance]); - const setStoredValue = (newValue) => { + const setStoredValue = newValue => { if (newValue === undefined) { mmkvInstance.delete(key); } else { @@ -150,7 +150,7 @@ export function useMMKVBoolean(key, mmkvInstance) { const [value, setValue] = useState(() => mmkvInstance.getBoolean(key)); useEffect(() => { - const listener = mmkvInstance.addOnValueChangedListener((changedKey) => { + const listener = mmkvInstance.addOnValueChangedListener(changedKey => { if (changedKey === key || changedKey === undefined) { setValue(mmkvInstance.getBoolean(key)); } @@ -158,7 +158,7 @@ export function useMMKVBoolean(key, mmkvInstance) { return () => listener.remove(); }, [key, mmkvInstance]); - const setStoredValue = (newValue) => { + const setStoredValue = newValue => { if (newValue === undefined) { mmkvInstance.delete(key); } else { @@ -177,7 +177,7 @@ export function useMMKVObject(key, mmkvInstance) { }); useEffect(() => { - const listener = mmkvInstance.addOnValueChangedListener((changedKey) => { + const listener = mmkvInstance.addOnValueChangedListener(changedKey => { if (changedKey === key || changedKey === undefined) { const stored = mmkvInstance.getString(key); setValue(stored ? JSON.parse(stored) : undefined); @@ -186,7 +186,7 @@ export function useMMKVObject(key, mmkvInstance) { return () => listener.remove(); }, [key, mmkvInstance]); - const setStoredValue = (newValue) => { + const setStoredValue = newValue => { if (newValue === undefined) { mmkvInstance.delete(key); } else { diff --git a/app/containers/ActionSheet/ActionSheet.tsx b/app/containers/ActionSheet/ActionSheet.tsx index 65f65d551dc..b05824f8590 100644 --- a/app/containers/ActionSheet/ActionSheet.tsx +++ b/app/containers/ActionSheet/ActionSheet.tsx @@ -168,13 +168,9 @@ const ActionSheet = React.memo( // We need this to allow horizontal swipe gesture inside the bottom sheet like in reaction picker enableContentPanningGesture={data?.enableContentPanningGesture ?? true} {...androidTablet}> - + + {data?.children} + )} diff --git a/app/containers/AudioPlayer/Seek.tsx b/app/containers/AudioPlayer/Seek.tsx index eecd5d444e0..6b70602df0f 100644 --- a/app/containers/AudioPlayer/Seek.tsx +++ b/app/containers/AudioPlayer/Seek.tsx @@ -65,7 +65,7 @@ const Seek = ({ currentTime, duration, loaded = false, onChangeTime }: ISeek) => }; const onGestureEvent = useAnimatedGestureHandler({ - onStart: (event, ctx) => { + onStart: (_event, ctx) => { isPanning.value = true; ctx.offsetX = translateX.value; }, diff --git a/app/containers/Avatar/Avatar.stories.tsx b/app/containers/Avatar/Avatar.stories.tsx index 0a2503e3c7d..0af49c24552 100644 --- a/app/containers/Avatar/Avatar.stories.tsx +++ b/app/containers/Avatar/Avatar.stories.tsx @@ -64,7 +64,7 @@ export const CustomBorderRadius = () => ( - + ); diff --git a/app/containers/Avatar/AvatarContainer.tsx b/app/containers/Avatar/AvatarContainer.tsx index d9e610eda7b..4e54161efec 100644 --- a/app/containers/Avatar/AvatarContainer.tsx +++ b/app/containers/Avatar/AvatarContainer.tsx @@ -58,7 +58,6 @@ const AvatarContainer = ({ size={size} borderRadius={borderRadius} type={type} - children={children} userId={id} token={token} onPress={onPress} @@ -72,8 +71,9 @@ const AvatarContainer = ({ serverVersion={serverVersion} cdnPrefix={cdnPrefix} accessibilityLabel={accessibilityLabel} - accessible={accessible} - /> + accessible={accessible}> + {children} + ); }; diff --git a/app/containers/Avatar/AvatarWithEdit.tsx b/app/containers/Avatar/AvatarWithEdit.tsx index 49c96bd5f47..41767a01f9b 100644 --- a/app/containers/Avatar/AvatarWithEdit.tsx +++ b/app/containers/Avatar/AvatarWithEdit.tsx @@ -61,12 +61,12 @@ const AvatarWithEdit = ({ size={120} borderRadius={borderRadius} type={type} - children={children} onPress={onPress} getCustomEmoji={getCustomEmoji} isStatic={isStatic} - rid={rid} - /> + rid={rid}> + {children} + {handleEdit && serverVersion && compareServerVersion(serverVersion, 'greaterThanOrEqualTo', '3.6.0') ? (