Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@
"@types/node-fetch": "^2.6.12",
"babel-jest": "30.0.0",
"depcheck": "^1.4.7",
"eslint": "^9.37.0",
"eslint": "^9.38.0",
"husky": "^9.1.7",
"jest": "29.7.0",
"jest-environment-node": "^29.7.0",
Expand Down
1 change: 1 addition & 0 deletions packages/connect-explorer-theme/src/components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ export function FolderImpl({ item, anchors }: FolderProps): ReactElement {
routeFromChildren,
]),
);
// eslint-disable-next-line react-hooks/immutability
item.children = Object.entries(menu.items || {}).map(([key, menuItem]) => {
const routeMenuItem = routes[key] || {
name: key,
Expand Down
1 change: 1 addition & 0 deletions packages/connect-explorer-theme/src/mdx-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ function HeadingLink({
if (!id) return;
const heading = obRef.current;
if (!heading) return;
// eslint-disable-next-line react-hooks/immutability
slugs.set(heading, [id, (context.index += 1)]);
observer?.observe(heading);

Expand Down
1 change: 1 addition & 0 deletions packages/connect-explorer/src/components/CodeEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const CodeEditor = ({ code, codeChange, schema }: CodeEditorProps) => {

const [codeKey, setCodeKey] = useState(0);
const extensions = useMemo(() => {
// eslint-disable-next-line react-hooks/set-state-in-render
setCodeKey(prev => prev + 1);

const patchedSchema = schema ? { ...schema } : { properties: {} };
Expand Down
8 changes: 4 additions & 4 deletions packages/eslint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
"type-check": "yarn g:tsc --build"
},
"devDependencies": {
"@eslint/js": "^9.37.0",
"eslint": "^9.37.0",
"@eslint/js": "^9.38.0",
"eslint": "^9.38.0",
"eslint-plugin-chai-friendly": "^1.1.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^29.0.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-local-rules": "^3.0.2",
"eslint-plugin-playwright": "^2.2.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^6.1.1",
"eslint-plugin-react-hooks": "^7.0.1",
"globals": "^16.4.0",
"typescript-eslint": "^8.46.0"
"typescript-eslint": "^8.46.2"
}
}
4 changes: 4 additions & 0 deletions packages/eslint/src/chaiFriendlyConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import pluginChaiFriendly from 'eslint-plugin-chai-friendly';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const chaiFriendlyConfig = [
{
plugins: { 'chai-friendly': pluginChaiFriendly },
Expand Down
5 changes: 5 additions & 0 deletions packages/eslint/src/importConfig.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import pluginImport from 'eslint-plugin-import';
import path from 'path';
import { fileURLToPath } from 'url';

/**
* @typedef {import('eslint').Linter.Config} Config
*/

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

Expand All @@ -17,6 +21,7 @@ export const globalNoExtraneousDependenciesDevDependencies = [
'**/*e2e/**', // Todo: This shall be only in packages that has e2e tests
];

/** @type {Config[]} */
export const importConfig = [
pluginImport.flatConfigs.recommended,
{
Expand Down
5 changes: 5 additions & 0 deletions packages/eslint/src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import { jestConfig } from './jestConfig.mjs';
import { localRulesConfig } from './localRulesConfig.mjs';
import { reactConfig } from './reactConfig.mjs';
import { typescriptConfig } from './typescriptConfig.mjs';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

export { globalNoExtraneousDependenciesDevDependencies };

/** @type {Config[]} */
export const eslint = [
{
ignores: [
Expand Down Expand Up @@ -71,6 +75,7 @@ export const eslint = [
},
];

/** @type {Config} */
export const playwrightEslint = {
...playwright.configs['flat/recommended'],
files: ['e2e/**'],
Expand Down
4 changes: 4 additions & 0 deletions packages/eslint/src/javascriptConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import pluginJs from '@eslint/js';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const javascriptConfig = [
pluginJs.configs.recommended,
{
Expand Down
5 changes: 5 additions & 0 deletions packages/eslint/src/javascriptNodejsConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const javascriptNodejsConfig = [
{
// These rules are specific to JavaScript running on Node.js.
Expand Down
4 changes: 4 additions & 0 deletions packages/eslint/src/jestConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import pluginJest from 'eslint-plugin-jest';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const jestConfig = [
pluginJest.configs['flat/recommended'],
{
Expand Down
4 changes: 4 additions & 0 deletions packages/eslint/src/localRulesConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import pluginLocalRules from 'eslint-plugin-local-rules';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const localRulesConfig = [
{
plugins: {
Expand Down
16 changes: 12 additions & 4 deletions packages/eslint/src/reactConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import pluginReact from 'eslint-plugin-react';
import pluginReactHooks from 'eslint-plugin-react-hooks';
/**
* @typedef {import('eslint').Linter.Config} Config
*/

/** @type {Config[]} */
export const reactConfig = [
// React
pluginReact.configs.flat.recommended,
{
languageOptions: {
...pluginReact.configs.flat.recommended.languageOptions,
},
languageOptions: pluginReact.configs.flat.recommended.languageOptions,
settings: { react: { version: 'detect' } },
rules: {
// Additions
Expand All @@ -23,12 +25,18 @@ export const reactConfig = [
},

// React Hooks
...pluginReactHooks.configs.recommended,
pluginReactHooks.configs.flat.recommended,
{
plugins: { 'react-hooks': pluginReactHooks },
rules: {
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error',
'react-hooks/static-components': 'off', // TODO fix & reenable
'react-hooks/set-state-in-effect': 'off', // TODO fix & reenable, though this anti-pattern is unfortunately quite widespread
'react-hooks/refs': 'off', // Too restrictive. Reading ref in render is often desired, though must be carefully considered
'react-hooks/incompatible-library': 'off', // Rule for React Compiler; it's unlikely we'll use it anytime soon
'react-hooks/preserve-manual-memoization': 'off', // Rule for React Compiler; it's unlikely we'll use it anytime soon
'react-hooks/use-memo': 'off', // Too restrictive: enforces inline function in useMemo (forbids using variable)
},
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ const useConnectionGlobalModal = () => {

const allDevices = useSelector(selectAllDevices);

// TODO shall be refactored, now it isn't reactive on Date.now() → can render outdated result. Maybe a setInterval?
// eslint-disable-next-line react-hooks/purity
const lastUpdatedBoundaryTimestamp = Date.now() - NEARBY_DEVICES_LAST_UPDATED_LIMIT;

const devices = allDevices.filter(it => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ export const MetadataLabeling = ({
await dispatch(processMetadataMessageThunk({ payload, deviceStaticSessionId, value }));

setShowSuccess(true);
// Intentional pattern how to use timers with useEffect
// eslint-disable-next-line react-hooks/immutability
timeout = setTimeout(() => {
setShowSuccess(false);
}, 2000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ const factsCount = FACTS.length;
const selectNextHint = (currentIndex: number) => (currentIndex + 1) % factsCount;

export const RotatingFacts = () => {
// Intentionally impure, non-deterministic rendering
// eslint-disable-next-line react-hooks/purity
const firstHintIndex = Math.floor(Math.random() * (factsCount - 1));
const [factIndex, setFactIndex] = useState(firstHintIndex);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ interface TestCallback {
// getContextValues returns actual state of SendFormContext
const Component = ({ callback }: { callback: TestCallback }) => {
const values = useRbfContext();
// eslint-disable-next-line react-hooks/immutability
callback.getContextValues = () => values;

return values.isLoading ? <div>Loading</div> : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ interface TestCallback {
// getContextValues returns actual state of SendFormContext
const Component = ({ callback }: { callback: TestCallback }) => {
const values = useSendFormContext();
// eslint-disable-next-line react-hooks/immutability
callback.getContextValues = () => values;

// NOTE: rendering briefly explanation:
Expand Down
1 change: 1 addition & 0 deletions suite-native/atoms/src/Accordion/AccordionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const AccordionItem = ({

const handlePress = () => {
if (currentIndexOpened.value === index) {
// eslint-disable-next-line react-hooks/immutability
currentIndexOpened.value = null;
} else {
currentIndexOpened.value = index;
Expand Down
1 change: 1 addition & 0 deletions suite-native/atoms/src/Button/TextButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ export const TextButton = ({
);

const interpolatePressColor = () => {
// eslint-disable-next-line react-hooks/immutability
animatedColor.value = interpolateColor(
textPressedColorValue.value,
[0, 1],
Expand Down
1 change: 1 addition & 0 deletions suite-native/atoms/src/Sheet/useAlertAnimation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export const useAlertAnimation = ({ onClose }: { onClose?: () => void }) => {
const openSheetAnimated = useCallback(() => {
'worklet';

// eslint-disable-next-line react-hooks/immutability
translatePanY.value = withTiming(0, {
duration: 300,
easing: Easing.out(Easing.cubic),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const SwipeableWalkthroughScreenHeader = ({
if (currentStepIndex.value === 0) {
onPressBack();
} else {
// eslint-disable-next-line react-hooks/immutability
currentStepIndex.value -= 1;
}
}, [currentStepIndex, onPressBack]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export const SwipeableWalkthroughStep = ({

const handleNextButtonPress = () => {
if (currentStepIndex.value < totalSteps - 1) {
// eslint-disable-next-line react-hooks/immutability
currentStepIndex.value += 1;
}
};
Expand Down
1 change: 1 addition & 0 deletions suite-native/firmware/src/hooks/useFirmwareAnalytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const useFirmwareAnalytics = ({
// Use refs to avoid any re-renders because of analytics and to make useCallback dependencies stable
// so it won't trigger any useEffect which could interfere with other business logic.
const analyticsPayload = useRef<FirmwareUpdatePayload>(prepareAnalyticsPayload());
// eslint-disable-next-line react-hooks/purity
const timeStarted = useRef<number>(Date.now());

useEffect(() => {
Expand Down
1 change: 1 addition & 0 deletions suite-native/icons/src/PizzaIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const usePizzaAnimation = ({
const [displayedPizzaIndex, setDisplayedPizzaIndex] = useState<0 | PIZZA_INDEX>(1);

const handleChangePizza = () => {
// eslint-disable-next-line react-hooks/immutability
animationProgress.value = 0;
setDisplayedPizzaIndex(currentPizzaIndex => ((currentPizzaIndex + 1) % 4) as PIZZA_INDEX);
animationProgress.value = withTiming(percentage / 100, {
Expand Down
2 changes: 2 additions & 0 deletions suite-native/link/src/components/Link.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export const Link = ({
}));

const handlePressIn = (e: GestureResponderEvent) => {
// eslint-disable-next-line react-hooks/immutability
isPressed.value = withTiming(IS_PRESSED_VALUE, { duration: ANIMATION_DURATION });
e.stopPropagation();
};

const handlePressOut = (e: GestureResponderEvent) => {
// eslint-disable-next-line react-hooks/immutability
isPressed.value = withTiming(IS_NOT_PRESSED_VALUE, { duration: ANIMATION_DURATION });
if (href) openLink(href);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export const WalletCreationScreen = () => {
}
}
// repeat the attempt if error was not one of the DEFINITIVE_ERRORS
// This code is OK, but the eslint plugin crashes on recursive calls
// eslint-disable-next-line react-hooks/immutability
handleCreateAndBackupWallet();
}, [dispatch, walletBackupType, navigation, isEntropyCheckEnabled]);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const WalletRecoveryScreen = ({
// Do not retry if user cancelled the flow via the app UI
if (response.payload.code && response.payload.code === 'Method_Interrupted') return;

// This code is OK, but the eslint plugin crashes on recursive calls
// eslint-disable-next-line react-hooks/immutability
handleRecoverWallet();
}, [dispatch, navigation]);

Expand Down
2 changes: 2 additions & 0 deletions suite-native/navigation/src/hooks/useDisableIOSGesture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export const useDisableIOSGesture = () => {
nav?.setOptions({ gestureEnabled: enable });
const parent = nav?.getParent?.();
if (parent) {
// This code is OK, but the eslint plugin crashes on recursive calls
// eslint-disable-next-line react-hooks/immutability
toggleGestures(parent, enable);
}
}, []);
Expand Down
1 change: 1 addition & 0 deletions suite-native/react-native-graph/src/SelectionDot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function SelectionDot({

const setIsActive = useCallback(
(active: boolean) => {
// eslint-disable-next-line react-hooks/immutability
circleRadius.value = withSpring(active ? CIRCLE_RADIUS : 0, {
mass: 1,
stiffness: 1000,
Expand Down
Loading
Loading