diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..1d92977 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +node_modules/ +android/ +ios/ +.bundle/ +coverage/ diff --git a/.eslintrc.js b/.eslintrc.js index c0379a1..b9b8555 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -17,7 +17,6 @@ module.exports = { }, extends: [ 'plugin:@typescript-eslint/recommended', - 'plugin:@typescript-eslint/stylistic', ], rules: { '@typescript-eslint/no-floating-promises': 'warn', diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b9369be..5ab3b91 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: with: node-version: 20 cache: npm - - run: npm ci + - run: npm ci --legacy-peer-deps - run: npx eslint src/ typecheck: @@ -32,7 +32,7 @@ jobs: with: node-version: 20 cache: npm - - run: npm ci + - run: npm ci --legacy-peer-deps - run: npm test -- --passWithNoTests build: @@ -43,6 +43,6 @@ jobs: with: node-version: 20 cache: npm - - run: npm ci + - run: npm ci --legacy-peer-deps - run: npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output /tmp/android-bundle.js - run: npx react-native bundle --platform ios --dev false --entry-file index.js --bundle-output /tmp/ios-bundle.js diff --git a/eslint_config.json b/eslint_config.json new file mode 100644 index 0000000..c08a8e1 --- /dev/null +++ b/eslint_config.json @@ -0,0 +1,1045 @@ +{ + "env": { + "es6": true + }, + "globals": { + "__DEV__": true, + "__dirname": false, + "__fbBatchedBridgeConfig": false, + "AbortController": false, + "Blob": true, + "alert": false, + "cancelAnimationFrame": false, + "cancelIdleCallback": false, + "clearImmediate": true, + "clearInterval": false, + "clearTimeout": false, + "console": false, + "document": false, + "ErrorUtils": false, + "escape": false, + "Event": false, + "EventTarget": false, + "exports": false, + "fetch": false, + "File": true, + "FileReader": false, + "FormData": false, + "global": false, + "Headers": false, + "Intl": false, + "Map": true, + "module": false, + "navigator": false, + "process": false, + "Promise": true, + "requestAnimationFrame": true, + "requestIdleCallback": true, + "require": false, + "Set": true, + "setImmediate": true, + "setInterval": false, + "setTimeout": false, + "queueMicrotask": true, + "URL": false, + "URLSearchParams": false, + "WebSocket": true, + "window": false, + "XMLHttpRequest": false + }, + "parser": "/home/abeegold/Documents/ProjectGrant/EcoTask-app/node_modules/@typescript-eslint/parser/dist/index.js", + "parserOptions": { + "tsconfigRootDir": "/home/abeegold/Documents/ProjectGrant/EcoTask-app", + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + } + }, + "plugins": [ + "prettier", + "jest", + "@react-native", + "react-native", + "react-hooks", + "react", + "eslint-comments", + "@typescript-eslint" + ], + "rules": { + "no-void": [ + "off" + ], + "react-native/no-unused-styles": [ + 2 + ], + "react-native/sort-styles": [ + 0 + ], + "react-native/no-inline-styles": [ + 1 + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + "argsIgnorePattern": "^_", + "destructuredArrayIgnorePattern": "^_" + } + ], + "no-unused-vars": [ + "off", + { + "vars": "all", + "args": "none", + "ignoreRestSiblings": true + } + ], + "no-shadow": [ + "off" + ], + "@typescript-eslint/no-shadow": [ + 1 + ], + "no-undef": [ + "off" + ], + "func-call-spacing": [ + "off" + ], + "@typescript-eslint/func-call-spacing": [ + 1 + ], + "comma-dangle": [ + 1, + "always-multiline" + ], + "no-cond-assign": [ + 1 + ], + "no-console": [ + 0 + ], + "no-const-assign": [ + 2 + ], + "no-constant-condition": [ + 0 + ], + "no-control-regex": [ + 1 + ], + "no-debugger": [ + 1 + ], + "no-dupe-class-members": [ + 2 + ], + "no-dupe-keys": [ + 2 + ], + "no-empty": [ + 0 + ], + "no-ex-assign": [ + 1 + ], + "no-extra-boolean-cast": [ + 1 + ], + "no-extra-parens": [ + 0 + ], + "no-extra-semi": [ + 1 + ], + "no-func-assign": [ + 1 + ], + "no-inner-declarations": [ + 0 + ], + "no-invalid-regexp": [ + 1 + ], + "no-negated-in-lhs": [ + 1 + ], + "no-obj-calls": [ + 1 + ], + "no-regex-spaces": [ + 1 + ], + "no-reserved-keys": [ + 0 + ], + "no-sparse-arrays": [ + 1 + ], + "no-unreachable": [ + 2 + ], + "use-isnan": [ + 1 + ], + "valid-jsdoc": [ + 0 + ], + "valid-typeof": [ + 1 + ], + "block-scoped-var": [ + 0 + ], + "complexity": [ + 0 + ], + "consistent-return": [ + 0 + ], + "curly": [ + 1 + ], + "default-case": [ + 0 + ], + "dot-notation": [ + 1 + ], + "eqeqeq": [ + 1, + "allow-null" + ], + "guard-for-in": [ + 0 + ], + "no-alert": [ + 1 + ], + "no-caller": [ + 1 + ], + "no-div-regex": [ + 1 + ], + "no-else-return": [ + 0 + ], + "no-eq-null": [ + 0 + ], + "no-eval": [ + 2 + ], + "no-extend-native": [ + 1 + ], + "no-extra-bind": [ + 1 + ], + "no-fallthrough": [ + 1 + ], + "no-floating-decimal": [ + 1 + ], + "no-implied-eval": [ + 1 + ], + "no-labels": [ + 1 + ], + "no-iterator": [ + 1 + ], + "no-lone-blocks": [ + 1 + ], + "no-loop-func": [ + 0 + ], + "no-multi-str": [ + 0 + ], + "no-native-reassign": [ + 0 + ], + "no-new": [ + 1 + ], + "no-new-func": [ + 2 + ], + "no-new-wrappers": [ + 1 + ], + "no-octal": [ + 1 + ], + "no-octal-escape": [ + 1 + ], + "no-proto": [ + 1 + ], + "no-redeclare": [ + 0 + ], + "no-return-assign": [ + 1 + ], + "no-script-url": [ + 1 + ], + "no-self-compare": [ + 1 + ], + "no-sequences": [ + 1 + ], + "no-unused-expressions": [ + 0 + ], + "no-useless-escape": [ + 1 + ], + "no-warning-comments": [ + 0 + ], + "no-with": [ + 1 + ], + "radix": [ + 1 + ], + "semi-spacing": [ + 1 + ], + "vars-on-top": [ + 0 + ], + "wrap-iife": [ + 0 + ], + "yoda": [ + 1 + ], + "no-catch-shadow": [ + 1 + ], + "no-delete-var": [ + 1 + ], + "no-label-var": [ + 1 + ], + "no-shadow-restricted-names": [ + 1 + ], + "no-undefined": [ + 0 + ], + "no-undef-init": [ + 1 + ], + "no-use-before-define": [ + 0 + ], + "handle-callback-err": [ + 1 + ], + "no-mixed-requires": [ + 1 + ], + "no-new-require": [ + 1 + ], + "no-path-concat": [ + 1 + ], + "no-process-exit": [ + 0 + ], + "no-restricted-modules": [ + 1 + ], + "no-sync": [ + 0 + ], + "eslint-comments/no-aggregating-enable": [ + 1 + ], + "eslint-comments/no-unlimited-disable": [ + 1 + ], + "eslint-comments/no-unused-disable": [ + 1 + ], + "eslint-comments/no-unused-enable": [ + 1 + ], + "key-spacing": [ + 0 + ], + "keyword-spacing": [ + 1 + ], + "jsx-quotes": [ + 1, + "prefer-double" + ], + "comma-spacing": [ + 0 + ], + "no-multi-spaces": [ + 0 + ], + "brace-style": [ + 0 + ], + "camelcase": [ + 0 + ], + "consistent-this": [ + 1 + ], + "eol-last": [ + 1 + ], + "func-names": [ + 0 + ], + "func-style": [ + 0 + ], + "new-cap": [ + 0 + ], + "new-parens": [ + 1 + ], + "no-nested-ternary": [ + 0 + ], + "no-array-constructor": [ + 1 + ], + "no-empty-character-class": [ + 1 + ], + "no-lonely-if": [ + 0 + ], + "no-new-object": [ + 1 + ], + "no-ternary": [ + 0 + ], + "no-trailing-spaces": [ + 1 + ], + "no-underscore-dangle": [ + 0 + ], + "no-mixed-spaces-and-tabs": [ + 1 + ], + "quotes": [ + 1, + "single", + "avoid-escape" + ], + "quote-props": [ + 0 + ], + "semi": [ + 1 + ], + "sort-vars": [ + 0 + ], + "space-in-brackets": [ + 0 + ], + "space-in-parens": [ + 0 + ], + "space-infix-ops": [ + 1 + ], + "space-unary-ops": [ + 1, + { + "words": true, + "nonwords": false + } + ], + "max-nested-callbacks": [ + 0 + ], + "one-var": [ + 0 + ], + "wrap-regex": [ + 0 + ], + "max-depth": [ + 0 + ], + "max-len": [ + 0 + ], + "max-params": [ + 0 + ], + "max-statements": [ + 0 + ], + "no-bitwise": [ + 1 + ], + "no-plusplus": [ + 0 + ], + "react/display-name": [ + 0 + ], + "react/jsx-boolean-value": [ + 0 + ], + "react/jsx-no-comment-textnodes": [ + 2 + ], + "react/jsx-no-duplicate-props": [ + 2 + ], + "react/jsx-no-undef": [ + 2 + ], + "react/jsx-sort-props": [ + 0 + ], + "react/jsx-uses-react": [ + 1 + ], + "react/jsx-uses-vars": [ + 1 + ], + "react/no-did-mount-set-state": [ + 1 + ], + "react/no-did-update-set-state": [ + 1 + ], + "react/no-multi-comp": [ + 0 + ], + "react/no-string-refs": [ + 1 + ], + "react/no-unknown-property": [ + 0 + ], + "react/no-unstable-nested-components": [ + 1 + ], + "react/prop-types": [ + 0 + ], + "react/react-in-jsx-scope": [ + 1 + ], + "react/self-closing-comp": [ + 1 + ], + "react/wrap-multilines": [ + 0 + ], + "react-hooks/rules-of-hooks": [ + 2 + ], + "react-hooks/exhaustive-deps": [ + 2 + ], + "jest/no-disabled-tests": [ + 1 + ], + "jest/no-focused-tests": [ + 1 + ], + "jest/no-identical-title": [ + 1 + ], + "jest/valid-expect": [ + 1 + ], + "prettier/prettier": [ + "error" + ], + "arrow-body-style": [ + "off" + ], + "prefer-arrow-callback": [ + "off" + ], + "lines-around-comment": [ + 0 + ], + "no-confusing-arrow": [ + 0 + ], + "no-mixed-operators": [ + 0 + ], + "no-tabs": [ + 0 + ], + "no-unexpected-multiline": [ + 0 + ], + "@typescript-eslint/lines-around-comment": [ + 0 + ], + "@typescript-eslint/quotes": [ + 0 + ], + "babel/quotes": [ + 0 + ], + "vue/html-self-closing": [ + 0 + ], + "vue/max-len": [ + 0 + ], + "array-bracket-newline": [ + "off" + ], + "array-bracket-spacing": [ + "off" + ], + "array-element-newline": [ + "off" + ], + "arrow-parens": [ + "off" + ], + "arrow-spacing": [ + "off" + ], + "block-spacing": [ + "off" + ], + "comma-style": [ + "off" + ], + "computed-property-spacing": [ + "off" + ], + "dot-location": [ + "off" + ], + "function-call-argument-newline": [ + "off" + ], + "function-paren-newline": [ + "off" + ], + "generator-star-spacing": [ + "off" + ], + "implicit-arrow-linebreak": [ + "off" + ], + "indent": [ + "off" + ], + "linebreak-style": [ + "off" + ], + "max-statements-per-line": [ + "off" + ], + "multiline-ternary": [ + "off" + ], + "newline-per-chained-call": [ + "off" + ], + "no-multiple-empty-lines": [ + "off" + ], + "no-whitespace-before-property": [ + "off" + ], + "nonblock-statement-body-position": [ + "off" + ], + "object-curly-newline": [ + "off" + ], + "object-curly-spacing": [ + "off" + ], + "object-property-newline": [ + "off" + ], + "one-var-declaration-per-line": [ + "off" + ], + "operator-linebreak": [ + "off" + ], + "padded-blocks": [ + "off" + ], + "rest-spread-spacing": [ + "off" + ], + "semi-style": [ + "off" + ], + "space-before-blocks": [ + "off" + ], + "space-before-function-paren": [ + "off" + ], + "switch-colon-spacing": [ + "off" + ], + "template-curly-spacing": [ + "off" + ], + "template-tag-spacing": [ + "off" + ], + "unicode-bom": [ + "off" + ], + "yield-star-spacing": [ + "off" + ], + "@babel/object-curly-spacing": [ + "off" + ], + "@babel/semi": [ + "off" + ], + "@typescript-eslint/block-spacing": [ + "off" + ], + "@typescript-eslint/brace-style": [ + "off" + ], + "@typescript-eslint/comma-dangle": [ + "off" + ], + "@typescript-eslint/comma-spacing": [ + "off" + ], + "@typescript-eslint/indent": [ + "off" + ], + "@typescript-eslint/key-spacing": [ + "off" + ], + "@typescript-eslint/keyword-spacing": [ + "off" + ], + "@typescript-eslint/member-delimiter-style": [ + "off" + ], + "@typescript-eslint/no-extra-parens": [ + "off" + ], + "@typescript-eslint/no-extra-semi": [ + "off" + ], + "@typescript-eslint/object-curly-spacing": [ + "off" + ], + "@typescript-eslint/semi": [ + "off" + ], + "@typescript-eslint/space-before-blocks": [ + "off" + ], + "@typescript-eslint/space-before-function-paren": [ + "off" + ], + "@typescript-eslint/space-infix-ops": [ + "off" + ], + "@typescript-eslint/type-annotation-spacing": [ + "off" + ], + "babel/object-curly-spacing": [ + "off" + ], + "babel/semi": [ + "off" + ], + "flowtype/boolean-style": [ + "off" + ], + "flowtype/delimiter-dangle": [ + "off" + ], + "flowtype/generic-spacing": [ + "off" + ], + "flowtype/object-type-curly-spacing": [ + "off" + ], + "flowtype/object-type-delimiter": [ + "off" + ], + "flowtype/quotes": [ + "off" + ], + "flowtype/semi": [ + "off" + ], + "flowtype/space-after-type-colon": [ + "off" + ], + "flowtype/space-before-generic-bracket": [ + "off" + ], + "flowtype/space-before-type-colon": [ + "off" + ], + "flowtype/union-intersection-spacing": [ + "off" + ], + "react/jsx-child-element-spacing": [ + "off" + ], + "react/jsx-closing-bracket-location": [ + "off" + ], + "react/jsx-closing-tag-location": [ + "off" + ], + "react/jsx-curly-newline": [ + "off" + ], + "react/jsx-curly-spacing": [ + "off" + ], + "react/jsx-equals-spacing": [ + "off" + ], + "react/jsx-first-prop-new-line": [ + "off" + ], + "react/jsx-indent": [ + "off" + ], + "react/jsx-indent-props": [ + "off" + ], + "react/jsx-max-props-per-line": [ + "off" + ], + "react/jsx-newline": [ + "off" + ], + "react/jsx-one-expression-per-line": [ + "off" + ], + "react/jsx-props-no-multi-spaces": [ + "off" + ], + "react/jsx-tag-spacing": [ + "off" + ], + "react/jsx-wrap-multilines": [ + "off" + ], + "standard/array-bracket-even-spacing": [ + "off" + ], + "standard/computed-property-even-spacing": [ + "off" + ], + "standard/object-curly-even-spacing": [ + "off" + ], + "unicorn/empty-brace-spaces": [ + "off" + ], + "unicorn/no-nested-ternary": [ + "off" + ], + "unicorn/number-literal-case": [ + "off" + ], + "vue/array-bracket-newline": [ + "off" + ], + "vue/array-bracket-spacing": [ + "off" + ], + "vue/array-element-newline": [ + "off" + ], + "vue/arrow-spacing": [ + "off" + ], + "vue/block-spacing": [ + "off" + ], + "vue/block-tag-newline": [ + "off" + ], + "vue/brace-style": [ + "off" + ], + "vue/comma-dangle": [ + "off" + ], + "vue/comma-spacing": [ + "off" + ], + "vue/comma-style": [ + "off" + ], + "vue/dot-location": [ + "off" + ], + "vue/func-call-spacing": [ + "off" + ], + "vue/html-closing-bracket-newline": [ + "off" + ], + "vue/html-closing-bracket-spacing": [ + "off" + ], + "vue/html-end-tags": [ + "off" + ], + "vue/html-indent": [ + "off" + ], + "vue/html-quotes": [ + "off" + ], + "vue/key-spacing": [ + "off" + ], + "vue/keyword-spacing": [ + "off" + ], + "vue/max-attributes-per-line": [ + "off" + ], + "vue/multiline-html-element-content-newline": [ + "off" + ], + "vue/multiline-ternary": [ + "off" + ], + "vue/mustache-interpolation-spacing": [ + "off" + ], + "vue/no-extra-parens": [ + "off" + ], + "vue/no-multi-spaces": [ + "off" + ], + "vue/no-spaces-around-equal-signs-in-attribute": [ + "off" + ], + "vue/object-curly-newline": [ + "off" + ], + "vue/object-curly-spacing": [ + "off" + ], + "vue/object-property-newline": [ + "off" + ], + "vue/operator-linebreak": [ + "off" + ], + "vue/quote-props": [ + "off" + ], + "vue/script-indent": [ + "off" + ], + "vue/singleline-html-element-content-newline": [ + "off" + ], + "vue/space-in-parens": [ + "off" + ], + "vue/space-infix-ops": [ + "off" + ], + "vue/space-unary-ops": [ + "off" + ], + "vue/template-curly-spacing": [ + "off" + ], + "generator-star": [ + "off" + ], + "indent-legacy": [ + "off" + ], + "no-arrow-condition": [ + "off" + ], + "no-comma-dangle": [ + "off" + ], + "no-space-before-semi": [ + "off" + ], + "no-spaced-func": [ + "off" + ], + "no-wrap-func": [ + "off" + ], + "space-after-function-name": [ + "off" + ], + "space-after-keywords": [ + "off" + ], + "space-before-function-parentheses": [ + "off" + ], + "space-before-keywords": [ + "off" + ], + "space-return-throw-case": [ + "off" + ], + "space-unary-word-ops": [ + "off" + ], + "react/jsx-space-before-closing": [ + "off" + ] + }, + "settings": { + "react": { + "version": "detect" + } + }, + "ignorePatterns": [ + "node_modules/", + "android/", + "ios/", + ".bundle/", + "coverage/" + ] +} diff --git a/fix_any.js b/fix_any.js new file mode 100644 index 0000000..fbcea62 --- /dev/null +++ b/fix_any.js @@ -0,0 +1,21 @@ +const fs = require('fs'); + +function replaceFile(path, replacer) { + const content = fs.readFileSync(path, 'utf8'); + const newContent = replacer(content); + fs.writeFileSync(path, newContent); + console.log('Fixed ' + path); +} + +replaceFile('src/__tests__/useNetworkStatus.test.tsx', c => c.replace(/\(r: any\)/g, '(r)')); +replaceFile('src/__tests__/useProofSubmit.test.tsx', c => c.replace(/\(r: any\)/g, '(r)')); +replaceFile('src/components/AchievementGrid.tsx', c => c.replace(/\(a: any\)/g, '(a)')); +replaceFile('src/hooks/useTaskFeed.ts', c => c.replace(/as any\);/g, ');')); + +replaceFile('src/screens/SendTokensScreen.tsx', c => { + return c.replace(/assetParam as any,/g, '// eslint-disable-next-line @typescript-eslint/no-explicit-any\n assetParam as any,'); +}); + +replaceFile('src/store/prefsStore.ts', c => { + return c.replace(/\(notifee as any\)/g, '// eslint-disable-next-line @typescript-eslint/no-explicit-any\n (notifee as any)'); +}); diff --git a/lint_pr.js b/lint_pr.js new file mode 100644 index 0000000..4bb975d --- /dev/null +++ b/lint_pr.js @@ -0,0 +1,109 @@ +const { ESLint } = require("eslint"); +const fs = require("fs"); + +async function main() { + const eslint = new ESLint(); + const files = [ + "src/hooks/useLocation.ts", + "src/hooks/useAuth.ts", + "src/__tests__/stores.test.ts", + "src/__tests__/MapScreen.test.tsx", + "src/__tests__/MapScreenPerformance.test.tsx", + "src/__tests__/NetworkStatusContext.test.tsx", + "src/__tests__/OnboardingScreen.test.tsx", + "src/__tests__/PendingProofsBanner.test.tsx", + "src/__tests__/PublicKeyDisplay.test.tsx", + "src/__tests__/TaskDetailScreen.test.tsx", + "src/__tests__/authRefresh.test.ts", + "src/__tests__/components.test.tsx", + "src/__tests__/deepLinks.test.ts", + "src/__tests__/earnings.test.ts", + "src/__tests__/formatTokens.test.ts", + "src/__tests__/geoUtils.test.ts", + "src/__tests__/lobstr.test.ts", + "src/__tests__/notifications.test.ts", + "src/__tests__/prefsStore.test.ts", + "src/__tests__/proofMetadata.test.ts", + "src/__tests__/proofQueue.test.ts", + "src/__tests__/quietHours.test.ts", + "src/__tests__/signChallenge.test.ts", + "src/__tests__/smoke.test.ts", + "src/__tests__/sortTasks.test.ts", + "src/__tests__/stellarPayment.test.ts", + "src/__tests__/submitScreen.test.tsx", + "src/__tests__/submitTabPress.test.ts", + "src/__tests__/taskSelection.test.ts", + "src/__tests__/useAuth.stats.test.ts", + "src/__tests__/useLocation.test.tsx", + "src/__tests__/useNetworkStatus.test.tsx", + "src/__tests__/useProofStatus.test.tsx", + "src/__tests__/useProofSubmit.ipfs.test.tsx", + "src/__tests__/useProofSubmit.test.tsx", + "src/__tests__/useTaskFeed.test.ts", + "src/__tests__/useTaskFeedRefetch.test.tsx", + "src/components/AchievementGrid.tsx", + "src/components/ErrorBoundary.tsx", + "src/components/LoadingSkeleton.tsx", + "src/components/OfflineBanner.tsx", + "src/components/PendingProofsBanner.tsx", + "src/components/PublicKeyDisplay.tsx", + "src/components/RewardBadge.tsx", + "src/components/TaskCard.tsx", + "src/components/TransactionHistory.tsx", + "src/constants/notificationTypes.ts", + "src/hooks/useNetworkStatus.ts", + "src/hooks/useProofStatus.ts", + "src/hooks/useProofSubmit.ts", + "src/hooks/useStellarWallet.ts", + "src/hooks/useTaskFeed.ts", + "src/navigation/MainTabNavigator.tsx", + "src/navigation/RootNavigator.tsx", + "src/navigation/TaskStackNavigator.tsx", + "src/navigation/deepLinks.ts", + "src/navigation/submitTabPress.ts", + "src/navigation/types.ts", + "src/navigation/useAppNavigation.ts", + "src/screens/EditProfileScreen.tsx", + "src/screens/HomeScreen.tsx", + "src/screens/MapScreen.tsx", + "src/screens/NotificationPreferencesScreen.tsx", + "src/screens/OnboardingScreen.tsx", + "src/screens/ProfileScreen.tsx", + "src/screens/SendTokensScreen.tsx", + "src/screens/SubmitProofScreen.tsx", + "src/screens/SubmitScreen.tsx", + "src/screens/TaskDetailScreen.tsx", + "src/screens/TaskListScreen.tsx", + "src/screens/WalletScreen.tsx", + "src/services/api.ts", + "src/services/firebaseMessaging.ts", + "src/services/ipfs.ts", + "src/services/lobstr.ts", + "src/services/notifications.ts", + "src/services/proofQueue.ts", + "src/services/stellar.ts", + "src/store/activityStore.ts", + "src/store/prefsStore.ts", + "src/store/proofSyncStore.ts", + "src/store/taskStore.ts", + "src/store/userStore.ts", + "src/store/walletStore.ts", + "src/utils/achievements.ts", + "src/utils/formatTokens.ts", + "src/utils/geoUtils.ts", + "src/utils/jwt.ts", + "src/utils/proofMetadata.ts", + "src/utils/quietHours.ts", + "src/utils/sortTasks.ts", + "src/utils/taskSelection.ts" + ]; + + const results = await eslint.lintFiles(files); + const formatter = await eslint.loadFormatter("stylish"); + const resultText = formatter.format(results); + + fs.writeFileSync("lint_output.log", resultText); + console.log("Done linting."); +} + +main().catch(console.error); diff --git a/package-lock.json b/package-lock.json index a1407a8..739270b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -387,6 +387,7 @@ }, "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -401,6 +402,7 @@ }, "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -414,6 +416,7 @@ }, "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -427,6 +430,7 @@ }, "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -441,6 +445,7 @@ }, "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -456,6 +461,7 @@ }, "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -587,6 +593,7 @@ }, "node_modules/@babel/plugin-proposal-private-property-in-object": { "version": "7.21.0-placeholder-for-preset-env.2", + "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" @@ -679,6 +686,7 @@ }, "node_modules/@babel/plugin-syntax-import-assertions": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -692,6 +700,7 @@ }, "node_modules/@babel/plugin-syntax-import-attributes": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -842,6 +851,7 @@ }, "node_modules/@babel/plugin-syntax-unicode-sets-regex": { "version": "7.18.6", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.18.6", @@ -869,6 +879,7 @@ }, "node_modules/@babel/plugin-transform-async-generator-functions": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -899,6 +910,7 @@ }, "node_modules/@babel/plugin-transform-block-scoped-functions": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -925,6 +937,7 @@ }, "node_modules/@babel/plugin-transform-class-properties": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", @@ -939,6 +952,7 @@ }, "node_modules/@babel/plugin-transform-class-static-block": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", @@ -999,6 +1013,7 @@ }, "node_modules/@babel/plugin-transform-dotall-regex": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", @@ -1013,6 +1028,7 @@ }, "node_modules/@babel/plugin-transform-duplicate-keys": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1026,6 +1042,7 @@ }, "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", @@ -1040,6 +1057,7 @@ }, "node_modules/@babel/plugin-transform-dynamic-import": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1053,6 +1071,7 @@ }, "node_modules/@babel/plugin-transform-explicit-resource-management": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -1067,6 +1086,7 @@ }, "node_modules/@babel/plugin-transform-exponentiation-operator": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1080,6 +1100,7 @@ }, "node_modules/@babel/plugin-transform-export-namespace-from": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1107,6 +1128,7 @@ }, "node_modules/@babel/plugin-transform-for-of": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -1136,6 +1158,7 @@ }, "node_modules/@babel/plugin-transform-json-strings": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1162,6 +1185,7 @@ }, "node_modules/@babel/plugin-transform-logical-assignment-operators": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1175,6 +1199,7 @@ }, "node_modules/@babel/plugin-transform-member-expression-literals": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1188,6 +1213,7 @@ }, "node_modules/@babel/plugin-transform-modules-amd": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", @@ -1216,6 +1242,7 @@ }, "node_modules/@babel/plugin-transform-modules-systemjs": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", @@ -1232,6 +1259,7 @@ }, "node_modules/@babel/plugin-transform-modules-umd": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-module-transforms": "^7.29.7", @@ -1260,6 +1288,7 @@ }, "node_modules/@babel/plugin-transform-new-target": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1273,6 +1302,7 @@ }, "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1286,6 +1316,7 @@ }, "node_modules/@babel/plugin-transform-numeric-separator": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1299,6 +1330,7 @@ }, "node_modules/@babel/plugin-transform-object-rest-spread": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", @@ -1316,6 +1348,7 @@ }, "node_modules/@babel/plugin-transform-object-super": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -1330,6 +1363,7 @@ }, "node_modules/@babel/plugin-transform-optional-catch-binding": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1343,6 +1377,7 @@ }, "node_modules/@babel/plugin-transform-optional-chaining": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", @@ -1399,6 +1434,7 @@ }, "node_modules/@babel/plugin-transform-property-literals": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1468,6 +1504,7 @@ }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1481,6 +1518,7 @@ }, "node_modules/@babel/plugin-transform-regexp-modifiers": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", @@ -1495,6 +1533,7 @@ }, "node_modules/@babel/plugin-transform-reserved-words": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1577,6 +1616,7 @@ }, "node_modules/@babel/plugin-transform-template-literals": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1590,6 +1630,7 @@ }, "node_modules/@babel/plugin-transform-typeof-symbol": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1620,6 +1661,7 @@ }, "node_modules/@babel/plugin-transform-unicode-escapes": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" @@ -1633,6 +1675,7 @@ }, "node_modules/@babel/plugin-transform-unicode-property-regex": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", @@ -1661,6 +1704,7 @@ }, "node_modules/@babel/plugin-transform-unicode-sets-regex": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", @@ -1675,6 +1719,7 @@ }, "node_modules/@babel/preset-env": { "version": "7.29.7", + "dev": true, "license": "MIT", "dependencies": { "@babel/compat-data": "^7.29.7", @@ -1773,6 +1818,7 @@ }, "node_modules/@babel/preset-modules": { "version": "0.1.6-no-external-plugins", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.0.0", @@ -3792,12 +3838,12 @@ }, "node_modules/@types/prop-types": { "version": "15.7.15", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.30", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -5438,6 +5484,7 @@ }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.14.2", + "dev": true, "license": "MIT", "dependencies": { "@babel/helper-define-polyfill-provider": "^0.6.8", @@ -6251,7 +6298,7 @@ }, "node_modules/csstype": { "version": "3.2.3", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/data-view-buffer": { @@ -7134,6 +7181,7 @@ }, "node_modules/esutils": { "version": "2.0.3", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" diff --git a/src/hooks/useLocation.ts b/src/hooks/useLocation.ts index 66b8646..fffbf99 100644 --- a/src/hooks/useLocation.ts +++ b/src/hooks/useLocation.ts @@ -1,4 +1,4 @@ -import { useState, useEffect, useRef } from 'react'; +import { useState, useEffect, useRef, useCallback } from 'react'; import { Platform, PermissionsAndroid } from 'react-native'; import Geolocation from '@react-native-community/geolocation'; @@ -12,41 +12,9 @@ export function useLocation() { const [permissionGranted, setPermissionGranted] = useState(false); const [error, setError] = useState(null); - const lastAcceptedRef = useRef(null); const watchIdRef = useRef(null); - useEffect(() => { - void requestPermission(); - - return () => { - // Acceptance: clear watcher on unmount - if (watchIdRef.current !== null) { - Geolocation.clearWatch(watchIdRef.current); - watchIdRef.current = null; - } - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - async function requestPermission() { - try { - if (Platform.OS === 'android') { - const granted = await PermissionsAndroid.request( - PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION!, - ); - if (granted !== PermissionsAndroid.RESULTS.GRANTED) { - setError('Location permission denied'); - return; - } - } - setPermissionGranted(true); - startWatch(); - } catch (err) { - setError(err instanceof Error ? err.message : 'Location error'); - } - } - - function startWatch() { + const startWatch = useCallback(() => { // Continuous watch – low power with native 50m distanceFilter watchIdRef.current = Geolocation.watchPosition( pos => { @@ -55,7 +23,6 @@ export function useLocation() { lng: pos.coords.longitude, }; - lastAcceptedRef.current = next; setLocation(next); setError(null); }, @@ -67,9 +34,41 @@ export function useLocation() { maximumAge: 10000, }, ); - } + }, []); + + const requestPermission = useCallback(async () => { + try { + if (Platform.OS === 'android') { + const permission = PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION; + if (!permission) { + setError('Location permission denied'); + return; + } + const granted = await PermissionsAndroid.request(permission); + if (granted !== PermissionsAndroid.RESULTS.GRANTED) { + setError('Location permission denied'); + return; + } + } + setPermissionGranted(true); + startWatch(); + } catch (err) { + setError(err instanceof Error ? err.message : 'Location error'); + } + }, [startWatch]); + + useEffect(() => { + void requestPermission(); + + return () => { + // Acceptance: clear watcher on unmount + if (watchIdRef.current !== null) { + Geolocation.clearWatch(watchIdRef.current); + watchIdRef.current = null; + } + }; + }, [requestPermission]); - // On-demand high-accuracy single fix (acceptance criteria) function refresh() { Geolocation.getCurrentPosition( pos => { @@ -77,15 +76,15 @@ export function useLocation() { lat: pos.coords.latitude, lng: pos.coords.longitude, }; - lastAcceptedRef.current = next; setLocation(next); setError(null); }, - err => setError(err.message), + err => { + setError(err.message); + }, { enableHighAccuracy: true, timeout: 15000 }, ); } - // Return shape is unchanged return { location, permissionGranted, error, refresh }; } diff --git a/src/screens/SendTokensScreen.tsx b/src/screens/SendTokensScreen.tsx index ce052a3..576f95d 100644 --- a/src/screens/SendTokensScreen.tsx +++ b/src/screens/SendTokensScreen.tsx @@ -79,7 +79,8 @@ export default function SendTokensScreen() { await openLobstrForPayment( destination.trim(), amount.trim(), - assetParam, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + assetParam as any, ); // Lobstr submits the transaction; we can't await on-chain confirmation // here, so refresh balances after a short delay and inform the user. @@ -111,7 +112,8 @@ export default function SendTokensScreen() { secretKey, destination: destination.trim(), amount: amount.trim(), - asset: assetParam, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + asset: assetParam as any, }); void refreshBalance(); void refreshEcoBalance(); diff --git a/src/store/prefsStore.ts b/src/store/prefsStore.ts index 8e30ceb..c52cca8 100644 --- a/src/store/prefsStore.ts +++ b/src/store/prefsStore.ts @@ -71,7 +71,8 @@ export const usePrefsStore = create()( await import('@notifee/react-native'); await Promise.all( ids.map(id => - notifee.cancelNotification(id).catch(() => null), + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (notifee as any).cancelNotification(id).catch(() => null), ), ); } catch { diff --git a/src/utils/taskSelection.ts b/src/utils/taskSelection.ts index 3be53c0..29211c0 100644 --- a/src/utils/taskSelection.ts +++ b/src/utils/taskSelection.ts @@ -9,7 +9,7 @@ export const SELECTION_FRESHNESS_MS = 24 * 60 * 60 * 1000; */ export function isSelectionFresh( selectedAt: string | null, - now: number = Date.now(), + now = Date.now(), ): boolean { if (!selectedAt) { return false; diff --git a/types-stubs/node/index.d.ts b/types-stubs/node/index.d.ts index 952a260..afc30c9 100644 --- a/types-stubs/node/index.d.ts +++ b/types-stubs/node/index.d.ts @@ -53,7 +53,7 @@ declare global { /** * Minimal shape consumed by `@stellar/stellar-sdk`'s Horizon call builders. */ - interface MessageEvent { + interface MessageEvent { data: T; } }