diff --git a/App.tsx b/App.tsx
index fe892d6..dafeda4 100644
--- a/App.tsx
+++ b/App.tsx
@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import { View, TouchableOpacity, StyleSheet } from 'react-native';
-import { NavigationContainer, DefaultTheme, DarkTheme, useNavigation } from '@react-navigation/native';
+import { NavigationContainer, DefaultTheme, DarkTheme } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { MaterialIcons } from '@expo/vector-icons';
@@ -140,7 +140,7 @@ function CreatePlaceholder() {
return ;
}
-function getTabBarIcon(routeName: string, focused: boolean, color: string, size: number) {
+function getTabBarIcon(routeName: string, focused: boolean, color: string, _size: number) {
let iconName: keyof typeof MaterialIcons.glyphMap = 'circle';
switch (routeName) {
@@ -258,7 +258,7 @@ export default function App() {
useEffect(() => {
loadData();
- }, []);
+ }, [loadData]);
const navigationTheme = useMemo(() => {
const isDark = theme.type === 'dark';
diff --git a/package-lock.json b/package-lock.json
index 4981323..90f76d8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"license": "MIT",
"dependencies": {
"@expo/metro-runtime": "~56.0.15",
+ "@expo/vector-icons": "^14.1.0",
"@react-native-async-storage/async-storage": "3.1.1",
"@react-native-community/datetimepicker": "9.1.0",
"@react-navigation/bottom-tabs": "^7.18.2",
@@ -28,11 +29,11 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
- "@eslint/js": "^10.0.1",
+ "@eslint/js": "^9.39.4",
"@types/react": "~19.2.17",
- "eslint": "^10.5.0",
+ "eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
- "eslint-plugin-react-hooks": "^7.1.1",
+ "eslint-plugin-react-hooks": "^5.2.0",
"globals": "^17.6.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.61.1"
@@ -192,6 +193,27 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve": {
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/@babel/helper-globals": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
@@ -1084,128 +1106,118 @@
}
},
"node_modules/@eslint/config-array": {
- "version": "0.23.5",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz",
- "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==",
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/object-schema": "^3.0.5",
+ "@eslint/object-schema": "^2.1.7",
"debug": "^4.3.1",
- "minimatch": "^10.2.4"
+ "minimatch": "^3.1.5"
},
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/config-array/node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
"engines": {
- "node": "18 || 20 || >=22"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/config-array/node_modules/brace-expansion": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
- "license": "MIT",
+ "license": "Apache-2.0",
"dependencies": {
- "balanced-match": "^4.0.2"
+ "@types/json-schema": "^7.0.15"
},
"engines": {
- "node": "18 || 20 || >=22"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@eslint/config-array/node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"dev": true,
- "license": "BlueOak-1.0.0",
+ "license": "MIT",
"dependencies": {
- "brace-expansion": "^5.0.5"
+ "ajv": "^6.14.0",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.1",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "18 || 20 || >=22"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/@eslint/config-helpers": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz",
- "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==",
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^1.2.1"
- },
+ "license": "MIT",
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- }
- },
- "node_modules/@eslint/core": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz",
- "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@types/json-schema": "^7.0.15"
+ "node": ">=18"
},
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@eslint/js": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
- "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"dev": true,
"license": "MIT",
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "eslint": "^10.0.0"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
}
},
"node_modules/@eslint/object-schema": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
- "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==",
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
"dev": true,
"license": "Apache-2.0",
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@eslint/plugin-kit": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz",
- "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==",
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "@eslint/core": "^1.2.1",
+ "@eslint/core": "^0.17.0",
"levn": "^0.4.1"
},
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@expo/cli": {
@@ -1843,6 +1855,17 @@
"integrity": "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw==",
"license": "MIT"
},
+ "node_modules/@expo/vector-icons": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.1.0.tgz",
+ "integrity": "sha512-7T09UE9h8QDTsUeMGymB4i+iqvtEeaO5VvUjryFB4tugDTG/bkzViWA74hm5pfjjDEhYMXWaX112mcvhccmIwQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "expo-font": "*",
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/@expo/ws-tunnel": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@expo/ws-tunnel/-/ws-tunnel-2.0.0.tgz",
@@ -2364,12 +2387,6 @@
"react": ">= 18.2.0"
}
},
- "node_modules/@react-navigation/core/node_modules/react-is": {
- "version": "19.2.7",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz",
- "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
- "license": "MIT"
- },
"node_modules/@react-navigation/elements": {
"version": "2.9.25",
"resolved": "https://registry.npmjs.org/@react-navigation/elements/-/elements-2.9.25.tgz",
@@ -2445,13 +2462,6 @@
"integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
"license": "MIT"
},
- "node_modules/@types/esrecurse": {
- "version": "4.3.1",
- "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
- "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/@types/estree": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz",
@@ -2491,9 +2501,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
- "version": "25.9.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz",
- "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==",
+ "version": "25.9.3",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.3.tgz",
+ "integrity": "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg==",
"license": "MIT",
"dependencies": {
"undici-types": ">=7.24.0 <7.24.7"
@@ -2806,6 +2816,19 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz",
@@ -2847,9 +2870,9 @@
}
},
"node_modules/acorn": {
- "version": "8.16.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
- "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "version": "8.17.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz",
+ "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==",
"license": "MIT",
"bin": {
"acorn": "bin/acorn"
@@ -2868,6 +2891,15 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
+ "node_modules/agent-base": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+ "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/ajv": {
"version": "6.15.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
@@ -3291,9 +3323,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
- "version": "2.10.33",
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.33.tgz",
- "integrity": "sha512-bA6+tcSLpz2tIEdDXZPpPTIuxBcC4+w6SieaYyfigIa4h8GlFxbA17v22Vx3JUtuZQj9SgOsnbK+aTBzyDyEuw==",
+ "version": "2.10.37",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.37.tgz",
+ "integrity": "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig==",
"license": "Apache-2.0",
"bin": {
"baseline-browser-mapping": "dist/cli.cjs"
@@ -3321,9 +3353,9 @@
}
},
"node_modules/bplist-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
- "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.2.tgz",
+ "integrity": "sha512-apC2+fspHGI3mMKj+dGevkGo/tCqVB8jMb6i+OX+E29p0Iposz07fABkRIfVUPNd5A5VbuOz1bZbnmkKLYF+wQ==",
"license": "MIT",
"dependencies": {
"big-integer": "1.6.x"
@@ -3462,6 +3494,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
@@ -3475,9 +3517,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001793",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
- "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
+ "version": "1.0.30001799",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001799.tgz",
+ "integrity": "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==",
"funding": [
{
"type": "opencollective",
@@ -4027,9 +4069,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
- "version": "1.5.364",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.364.tgz",
- "integrity": "sha512-G/dYE3+AYhyHwzTwg8UbnXf7zqMERYh7l2jJ3QujhFsH8agSYwtnGAR2aZ7f0AakIKJXd5En/Hre4igIUrdlYw==",
+ "version": "1.5.375",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.375.tgz",
+ "integrity": "sha512-ZWP5eB4BVPW/ZYo9252hQZHZ5XavtsTgpbhcmMmRwymavC5AsLWQWBPaKMeNd2LW0KGby5HPXvj7+sr4ta5j/Q==",
"license": "ISC"
},
"node_modules/emoji-regex": {
@@ -4125,6 +4167,25 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-abstract-get": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz",
+ "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.2",
+ "is-callable": "^1.2.7",
+ "object-inspect": "^1.13.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -4145,9 +4206,9 @@
}
},
"node_modules/es-iterator-helpers": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz",
- "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.3.tgz",
+ "integrity": "sha512-0PuBxFi+4uPanB97iDxCLWuHeYud2FALrw5HFZGtAF38UpJDbDC8frwp2cnDyae692CQ0dou60UwWfhgsa4U/g==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4215,15 +4276,17 @@
}
},
"node_modules/es-to-primitive": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
- "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.1.tgz",
+ "integrity": "sha512-CxN9N56HYfd2m/acc/NOFrZQsN9kU4eh+2kk6A707Kz1krH8tKmfrs5RnftB8WNX80T0NS7vSQsDOlg23diR2g==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "es-abstract-get": "^1.0.0",
+ "es-errors": "^1.3.0",
"is-callable": "^1.2.7",
- "is-date-object": "^1.0.5",
- "is-symbol": "^1.0.4"
+ "is-date-object": "^1.1.0",
+ "is-symbol": "^1.1.1"
},
"engines": {
"node": ">= 0.4"
@@ -4260,33 +4323,33 @@
}
},
"node_modules/eslint": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.5.0.tgz",
- "integrity": "sha512-1y+7C+vi12bUK1IpZeaV3gsH9fHLBmPvYmPx42pvT/E9yG0IC8g3PUZZgp0+JLJl7ZDK0flc2gc+Aw9dpCvIsQ==",
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
"license": "MIT",
- "workspaces": [
- "packages/*"
- ],
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.2",
- "@eslint/config-array": "^0.23.5",
- "@eslint/config-helpers": "^0.6.0",
- "@eslint/core": "^1.2.1",
- "@eslint/plugin-kit": "^0.7.2",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
"@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2",
"@types/estree": "^1.0.6",
"ajv": "^6.14.0",
+ "chalk": "^4.0.0",
"cross-spawn": "^7.0.6",
"debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^9.1.2",
- "eslint-visitor-keys": "^5.0.1",
- "espree": "^11.2.0",
- "esquery": "^1.7.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
"file-entry-cache": "^8.0.0",
@@ -4296,7 +4359,8 @@
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
- "minimatch": "^10.2.4",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
"natural-compare": "^1.4.0",
"optionator": "^0.9.3"
},
@@ -4304,7 +4368,7 @@
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
@@ -4352,163 +4416,61 @@
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz",
- "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==",
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz",
+ "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==",
"dev": true,
"license": "MIT",
- "dependencies": {
- "@babel/core": "^7.24.4",
- "@babel/parser": "^7.24.4",
- "hermes-parser": "^0.25.1",
- "zod": "^3.25.0 || ^4.0.0",
- "zod-validation-error": "^3.5.0 || ^4.0.0"
- },
"engines": {
- "node": ">=18"
+ "node": ">=10"
},
"peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0"
- }
- },
- "node_modules/eslint-plugin-react-hooks/node_modules/hermes-estree": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
- "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/eslint-plugin-react-hooks/node_modules/hermes-parser": {
- "version": "0.25.1",
- "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
- "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "hermes-estree": "0.25.1"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/resolve": {
- "version": "2.0.0-next.7",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
- "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "is-core-module": "^2.16.2",
- "node-exports-info": "^1.6.0",
- "object-keys": "^1.1.1",
- "path-parse": "^1.0.7",
- "supports-preserve-symlinks-flag": "^1.0.0"
- },
- "bin": {
- "resolve": "bin/resolve"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
"node_modules/eslint-scope": {
- "version": "9.1.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
- "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "@types/esrecurse": "^4.3.1",
- "@types/estree": "^1.0.8",
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
},
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-visitor-keys": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
- "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/eslint/node_modules/brace-expansion": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/eslint/node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/eslint/node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/espree": {
- "version": "11.2.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz",
- "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
"license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.16.0",
+ "acorn": "^8.15.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^5.0.1"
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
@@ -4835,6 +4797,15 @@
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==",
"license": "MIT"
},
+ "node_modules/fbjs/node_modules/promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "license": "MIT",
+ "dependencies": {
+ "asap": "~2.0.3"
+ }
+ },
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -5010,18 +4981,21 @@
}
},
"node_modules/function.prototype.name": {
- "version": "1.1.8",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
- "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz",
+ "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.3",
- "define-properties": "^1.2.1",
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
- "hasown": "^2.0.2",
- "is-callable": "^1.2.7"
+ "has-property-descriptors": "^1.0.2",
+ "hasown": "^2.0.4",
+ "is-callable": "^1.2.7",
+ "is-document.all": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -5151,6 +5125,19 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
"node_modules/glob/node_modules/balanced-match": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -5396,6 +5383,19 @@
"node": ">= 0.8"
}
},
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+ "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^7.1.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
"node_modules/hyphenate-style-name": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
@@ -5432,6 +5432,33 @@
"node": ">=16.x"
}
},
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-fresh/node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -5499,6 +5526,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-arrayish": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
+ "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
+ "license": "MIT"
+ },
"node_modules/is-async-function": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
@@ -5630,6 +5663,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-document.all": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz",
+ "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -5656,6 +5705,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-generator-function": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
@@ -5898,6 +5956,13 @@
"node": ">=8"
}
},
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@@ -6455,6 +6520,13 @@
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
"license": "MIT"
},
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lodash.throttle": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
@@ -6713,28 +6785,6 @@
"node": "^20.19.4 || ^22.13.0 || ^24.3.0 || >= 25.0.0"
}
},
- "node_modules/metro-cache/node_modules/agent-base": {
- "version": "7.1.4",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
- "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/metro-cache/node_modules/https-proxy-agent": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
- "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
- "license": "MIT",
- "dependencies": {
- "agent-base": "^7.1.2",
- "debug": "4"
- },
- "engines": {
- "node": ">= 14"
- }
- },
"node_modules/metro-config": {
"version": "0.84.4",
"resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.84.4.tgz",
@@ -7198,9 +7248,9 @@
"license": "MIT"
},
"node_modules/node-releases": {
- "version": "2.0.46",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.46.tgz",
- "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==",
+ "version": "2.0.47",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.47.tgz",
+ "integrity": "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og==",
"license": "MIT",
"engines": {
"node": ">=18"
@@ -7563,6 +7613,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/parse-png": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/parse-png/-/parse-png-2.1.0.tgz",
@@ -7789,12 +7852,12 @@
}
},
"node_modules/promise": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
- "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
+ "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
"license": "MIT",
"dependencies": {
- "asap": "~2.0.3"
+ "asap": "~2.0.6"
}
},
"node_modules/prompts": {
@@ -7821,6 +7884,12 @@
"react-is": "^16.13.1"
}
},
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
@@ -7932,9 +8001,9 @@
}
},
"node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "version": "19.2.7",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.7.tgz",
+ "integrity": "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A==",
"license": "MIT"
},
"node_modules/react-native": {
@@ -8179,19 +8248,10 @@
"hermes-estree": "0.36.0"
}
},
- "node_modules/react-native/node_modules/promise": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz",
- "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==",
- "license": "MIT",
- "dependencies": {
- "asap": "~2.0.6"
- }
- },
"node_modules/react-native/node_modules/semver": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz",
- "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==",
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz",
+ "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
@@ -8343,13 +8403,16 @@
}
},
"node_modules/resolve": {
- "version": "1.22.12",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
- "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "version": "2.0.0-next.7",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz",
+ "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==",
+ "dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
- "is-core-module": "^2.16.1",
+ "is-core-module": "^2.16.2",
+ "node-exports-info": "^1.6.0",
+ "object-keys": "^1.1.1",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
@@ -8411,13 +8474,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/safe-array-concat/node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -8455,13 +8511,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/safe-push-apply/node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
@@ -8710,15 +8759,15 @@
}
},
"node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz",
+ "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
+ "object-inspect": "^1.13.4",
+ "side-channel-list": "^1.0.1",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
@@ -8802,6 +8851,18 @@
"plist": "^3.0.5"
}
},
+ "node_modules/simple-plist/node_modules/bplist-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.3.1.tgz",
+ "integrity": "sha512-PyJxiNtA5T2PlLIeBot4lbp7rj4OadzjnMZD/G5zuBNt8ei/yCU7+wW0h2bag9vr8c+/WuRWmSxbqAl9hL1rBA==",
+ "license": "MIT",
+ "dependencies": {
+ "big-integer": "1.6.x"
+ },
+ "engines": {
+ "node": ">= 5.10.0"
+ }
+ },
"node_modules/simple-swizzle": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz",
@@ -8811,12 +8872,6 @@
"is-arrayish": "^0.3.1"
}
},
- "node_modules/simple-swizzle/node_modules/is-arrayish": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz",
- "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==",
- "license": "MIT"
- },
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@@ -8957,15 +9012,6 @@
"node": ">=8"
}
},
- "node_modules/string-width/node_modules/is-fullwidth-code-point": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
- "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/string-width/node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -9018,19 +9064,20 @@
}
},
"node_modules/string.prototype.trim": {
- "version": "1.2.10",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
- "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "version": "1.2.11",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz",
+ "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
"define-data-property": "^1.1.4",
"define-properties": "^1.2.1",
- "es-abstract": "^1.23.5",
- "es-object-atoms": "^1.0.0",
- "has-property-descriptors": "^1.0.2"
+ "es-abstract": "^1.24.2",
+ "es-object-atoms": "^1.1.2",
+ "has-property-descriptors": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -9040,16 +9087,16 @@
}
},
"node_modules/string.prototype.trimend": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
- "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz",
+ "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.2",
+ "call-bind": "^1.0.9",
+ "call-bound": "^1.0.4",
"define-properties": "^1.2.1",
- "es-object-atoms": "^1.0.0"
+ "es-object-atoms": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
@@ -9097,6 +9144,19 @@
"node": ">=6"
}
},
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/structured-headers": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/structured-headers/-/structured-headers-0.4.1.tgz",
@@ -9714,13 +9774,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/which-builtin-type/node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true,
- "license": "MIT"
- },
"node_modules/which-collection": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
@@ -9741,9 +9794,9 @@
}
},
"node_modules/which-typed-array": {
- "version": "1.1.21",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz",
- "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==",
+ "version": "1.1.22",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz",
+ "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -9945,19 +9998,6 @@
"url": "https://github.com/sponsors/colinhacks"
}
},
- "node_modules/zod-validation-error": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz",
- "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.0.0"
- },
- "peerDependencies": {
- "zod": "^3.25.0 || ^4.0.0"
- }
- },
"node_modules/zustand": {
"version": "5.0.14",
"resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.14.tgz",
diff --git a/package.json b/package.json
index d628503..1f24838 100644
--- a/package.json
+++ b/package.json
@@ -52,6 +52,7 @@
},
"dependencies": {
"@expo/metro-runtime": "~56.0.15",
+ "@expo/vector-icons": "^14.1.0",
"@react-native-async-storage/async-storage": "3.1.1",
"@react-native-community/datetimepicker": "9.1.0",
"@react-navigation/bottom-tabs": "^7.18.2",
@@ -70,11 +71,11 @@
},
"devDependencies": {
"@babel/core": "^7.20.0",
- "@eslint/js": "^10.0.1",
+ "@eslint/js": "^9.39.4",
"@types/react": "~19.2.17",
- "eslint": "^10.5.0",
+ "eslint": "^9.39.4",
"eslint-plugin-react": "^7.37.5",
- "eslint-plugin-react-hooks": "^7.1.1",
+ "eslint-plugin-react-hooks": "^5.2.0",
"globals": "^17.6.0",
"typescript": "^6.0.3",
"typescript-eslint": "^8.61.1"
diff --git a/screens/AnalyticsScreen.tsx b/screens/AnalyticsScreen.tsx
index 5c82fc3..7ec75f3 100644
--- a/screens/AnalyticsScreen.tsx
+++ b/screens/AnalyticsScreen.tsx
@@ -13,7 +13,7 @@ import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
-import { RootStackParamList, Task } from '../src/shared/types';
+import { RootStackParamList } from '../src/shared/types';
type NavigationProp = NativeStackNavigationProp;
@@ -28,10 +28,9 @@ const getDaysBetween = (start: Date, end: Date): number => {
export default function AnalyticsScreen() {
const navigation = useNavigation();
- const { theme, tasks, projects, categories, goals, habits } = useAppStore();
+ const { theme, tasks, projects, goals, habits } = useAppStore();
const [timeRange, setTimeRange] = useState('week');
- const [selectedMetric, setSelectedMetric] = useState('overview');
const getDateRange = (range: TimeRange): { start: Date; end: Date } => {
const end = new Date();
@@ -129,11 +128,6 @@ export default function AnalyticsScreen() {
return `${hours}小时`;
}, [completedTasks]);
- const getDaysBetweenLocal = (start: Date, end: Date): number => {
- const diffTime = Math.abs(end.getTime() - start.getTime());
- return Math.ceil(diffTime / (1000 * 60 * 60 * 24));
- };
-
const tasksByStatus = useMemo(() => {
const stats: Record = {
'todo': 0,
diff --git a/screens/AutomationScreen.tsx b/screens/AutomationScreen.tsx
index 4f5a428..984bf60 100644
--- a/screens/AutomationScreen.tsx
+++ b/screens/AutomationScreen.tsx
@@ -12,14 +12,13 @@ import {
Modal,
ScrollView,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
import {
RootStackParamList,
AutomationRule,
- AutomationTrigger,
AutomationCondition,
AutomationAction,
AutomationTriggerType,
@@ -86,13 +85,9 @@ export default function AutomationScreen() {
theme,
automationRules,
addAutomationRule,
- updateAutomationRule,
deleteAutomationRule,
toggleAutomationRule,
executeAutomation,
- projects,
- tags,
- categories,
} = useAppStore();
const [showAddModal, setShowAddModal] = useState(false);
@@ -227,12 +222,6 @@ export default function AutomationScreen() {
setNewRule({ ...newRule, actions: [...newRule.actions, newAction] });
};
- const updateAction = (index: number, updates: Partial) => {
- const updated = [...newRule.actions];
- updated[index] = { ...updated[index], ...updates };
- setNewRule({ ...newRule, actions: updated });
- };
-
const removeAction = (index: number) => {
const updated = [...newRule.actions];
updated.splice(index, 1);
@@ -591,7 +580,7 @@ export default function AutomationScreen() {
条件 ({selectedRule.conditions.length})
- {selectedRule.conditions.map((condition, index) => {
+ {selectedRule.conditions.map((condition, _index) => {
const fieldInfo = CONDITION_FIELDS.find((f) => f.field === condition.field);
const operatorInfo = CONDITION_OPERATORS.find((o) => o.value === condition.operator);
return (
@@ -611,7 +600,7 @@ export default function AutomationScreen() {
动作 ({selectedRule.actions.length})
- {selectedRule.actions.map((action, index) => {
+ {selectedRule.actions.map((action, _index) => {
const actionInfo = ACTION_TYPES.find((a) => a.type === action.type);
return (
diff --git a/screens/CalendarScreen.tsx b/screens/CalendarScreen.tsx
index 9ca70b6..1763115 100644
--- a/screens/CalendarScreen.tsx
+++ b/screens/CalendarScreen.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useMemo } from 'react';
+import React, { useState } from 'react';
import {
View,
Text,
@@ -24,12 +24,11 @@ type CalendarView = 'day' | 'week' | 'month';
export default function CalendarScreen() {
const navigation = useNavigation();
- const { theme, tasks, events, projects, categories } = useAppStore();
+ const { theme, tasks } = useAppStore();
const [currentDate, setCurrentDate] = useState(new Date());
const [calendarView, setCalendarView] = useState('month');
const [selectedDate, setSelectedDate] = useState(new Date());
- const [showEventModal, setShowEventModal] = useState(false);
const getDaysInMonth = (date: Date): Date[] => {
const year = date.getFullYear();
@@ -83,18 +82,6 @@ export default function CalendarScreen() {
});
};
- const getEventsForDate = (date: Date) => {
- return events.filter((event) => {
- if (!event.startDate) return false;
- const eventDate = new Date(event.startDate);
- return (
- eventDate.getDate() === date.getDate() &&
- eventDate.getMonth() === date.getMonth() &&
- eventDate.getFullYear() === date.getFullYear()
- );
- });
- };
-
const monthNames = [
'一月', '二月', '三月', '四月', '五月', '六月',
'七月', '八月', '九月', '十月', '十一月', '十二月'
@@ -129,7 +116,6 @@ export default function CalendarScreen() {
};
const selectedDateTasks = getTasksForDate(selectedDate);
- const selectedDateEvents = getEventsForDate(selectedDate);
const isToday = (date: Date): boolean => {
const today = new Date();
@@ -163,19 +149,6 @@ export default function CalendarScreen() {
return colors[priority] || theme.colors.primary;
};
- const getStatusColor = (status: string): string => {
- const colors: Record = {
- 'todo': '#6b7280',
- 'in-progress': '#3b82f6',
- 'waiting': '#8b5cf6',
- 'delegated': '#f59e0b',
- 'completed': '#10b981',
- 'cancelled': '#ef4444',
- 'on-hold': '#6b7280',
- };
- return colors[status] || theme.colors.primary;
- };
-
const renderHeader = () => (
navigation.goBack()} style={styles.backButton}>
@@ -342,7 +315,6 @@ export default function CalendarScreen() {
{weekDays.map((date, index) => {
const dayTasks = getTasksForDate(date);
- const dayEvents = getEventsForDate(date);
return (
diff --git a/screens/CategoriesScreen.tsx b/screens/CategoriesScreen.tsx
index bb1407b..bcbb4dc 100644
--- a/screens/CategoriesScreen.tsx
+++ b/screens/CategoriesScreen.tsx
@@ -11,7 +11,7 @@ import {
Alert,
Modal,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
diff --git a/screens/HomeScreen.tsx b/screens/HomeScreen.tsx
index 304c5d7..4ede2aa 100644
--- a/screens/HomeScreen.tsx
+++ b/screens/HomeScreen.tsx
@@ -43,7 +43,6 @@ export default function HomeScreen() {
tasks,
categories,
activeView,
- setActiveView,
selectedCategory,
setSelectedCategory,
loadData,
@@ -131,10 +130,10 @@ export default function HomeScreen() {
bulk.exit();
};
- const openReorder = () => {
+ const openReorder = useCallback(() => {
setReorderList([...sortedTasks]);
setShowReorder(true);
- };
+ }, [sortedTasks]);
const handleReorder = (from: number, to: number) => {
setReorderList((prev) => {
@@ -226,7 +225,7 @@ export default function HomeScreen() {
onSwipeRight={(task) => toggleTaskComplete(task.id)}
/>
);
- }, [navigation, toggleTaskComplete, deleteTask, bulk, updateTask, theme]);
+ }, [navigation, toggleTaskComplete, deleteTask, bulk, theme]);
const bulkActions: MultiSelectAction[] = [
{
diff --git a/screens/NotesScreen.tsx b/screens/NotesScreen.tsx
index 50704e3..ed903c7 100644
--- a/screens/NotesScreen.tsx
+++ b/screens/NotesScreen.tsx
@@ -3,21 +3,19 @@ import {
View,
Text,
StyleSheet,
- FlatList,
TouchableOpacity,
TextInput,
SafeAreaView,
- Platform,
Alert,
Modal,
ScrollView,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
import { RootStackParamList, Note } from '../src/shared/types';
-import { Button } from '../src/shared/components/common';
+
import { toast } from '../src/shared/components/common/Toast';
type NavigationProp = NativeStackNavigationProp;
diff --git a/screens/ProjectsScreen.tsx b/screens/ProjectsScreen.tsx
index d4a64ba..33237ca 100644
--- a/screens/ProjectsScreen.tsx
+++ b/screens/ProjectsScreen.tsx
@@ -3,7 +3,6 @@ import {
View,
Text,
StyleSheet,
- FlatList,
TouchableOpacity,
TextInput,
SafeAreaView,
@@ -13,7 +12,7 @@ import {
ScrollView,
Dimensions,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
@@ -47,7 +46,6 @@ export default function ProjectsScreen() {
updateProject,
deleteProject,
tasks,
- setActiveView,
} = useAppStore();
const [showAddModal, setShowAddModal] = useState(false);
@@ -179,7 +177,7 @@ export default function ProjectsScreen() {
}
};
- const handleViewProject = (projectId: string) => {
+ const handleViewProject = (_projectId: string) => {
navigation.navigate('Home');
};
diff --git a/screens/SearchScreen.tsx b/screens/SearchScreen.tsx
index a4823ce..dc2a996 100644
--- a/screens/SearchScreen.tsx
+++ b/screens/SearchScreen.tsx
@@ -7,16 +7,14 @@ import {
TouchableOpacity,
TextInput,
SafeAreaView,
- Platform,
- Alert,
ScrollView,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
-import { RootStackParamList, Task, Priority, TaskStatus, FilterCondition } from '../src/shared/types';
-import { TaskCard, Button } from '../src/shared/components/common';
+import { RootStackParamList, Task, Priority, TaskStatus } from '../src/shared/types';
+import { TaskCard } from '../src/shared/components/common';
type NavigationProp = NativeStackNavigationProp;
@@ -94,15 +92,17 @@ export default function SearchScreen() {
case 'title':
comparison = a.title.localeCompare(b.title);
break;
- case 'dueDate':
+ case 'dueDate': {
const aDate = a.dueDate ? new Date(a.dueDate).getTime() : Infinity;
const bDate = b.dueDate ? new Date(b.dueDate).getTime() : Infinity;
comparison = aDate - bDate;
break;
- case 'priority':
+ }
+ case 'priority': {
const priorityOrder = { critical: 0, urgent: 1, high: 2, medium: 3, low: 4 };
comparison = priorityOrder[a.priority] - priorityOrder[b.priority];
break;
+ }
case 'createdAt':
comparison = new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
break;
@@ -158,18 +158,20 @@ export default function SearchScreen() {
case 'isOverdue':
fieldValue = task.dueDate && new Date(task.dueDate) < new Date() && !task.completed;
break;
- case 'dueToday':
+ case 'dueToday': {
const today = new Date();
fieldValue = task.dueDate &&
new Date(task.dueDate).toDateString() === today.toDateString();
break;
- case 'dueThisWeek':
- const today2 = new Date();
- const nextWeek = new Date(today2.getTime() + 7 * 24 * 60 * 60 * 1000);
+ }
+ case 'dueThisWeek': {
+ const today = new Date();
+ const nextWeek = new Date(today.getTime() + 7 * 24 * 60 * 60 * 1000);
fieldValue = task.dueDate &&
- new Date(task.dueDate) >= today2 &&
+ new Date(task.dueDate) >= today &&
new Date(task.dueDate) <= nextWeek;
break;
+ }
default:
return true;
}
@@ -249,7 +251,7 @@ export default function SearchScreen() {
let valueDisplay = '';
switch (filter.field) {
- case 'status':
+ case 'status': {
const statusLabels: Record = {
'todo': '待办',
'in-progress': '进行中',
@@ -261,7 +263,8 @@ export default function SearchScreen() {
};
valueDisplay = statusLabels[filter.value] || filter.value;
break;
- case 'priority':
+ }
+ case 'priority': {
const priorityLabels: Record = {
'low': '低',
'medium': '中',
@@ -271,14 +274,17 @@ export default function SearchScreen() {
};
valueDisplay = priorityLabels[filter.value] || filter.value;
break;
- case 'project':
+ }
+ case 'project': {
const project = projects.find((p) => p.id === filter.value);
valueDisplay = project?.name || filter.value;
break;
- case 'category':
+ }
+ case 'category': {
const category = categories.find((c) => c.id === filter.value);
valueDisplay = category?.name || filter.value;
break;
+ }
default:
valueDisplay = String(filter.value);
}
diff --git a/screens/SettingsScreen.tsx b/screens/SettingsScreen.tsx
index 4e0c386..e60920e 100644
--- a/screens/SettingsScreen.tsx
+++ b/screens/SettingsScreen.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from 'react';
+import React from 'react';
import {
View,
Text,
@@ -7,7 +7,6 @@ import {
TouchableOpacity,
Switch,
SafeAreaView,
- Platform,
Alert,
Linking,
} from 'react-native';
@@ -15,7 +14,7 @@ import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
-import { RootStackParamList, Theme, ThemePreset, NotificationPreferences, DisplaySettings, PrivacySettings } from '../src/shared/types';
+import { RootStackParamList, Theme } from '../src/shared/types';
import { toast } from '../src/shared/components/common/Toast';
type NavigationProp = NativeStackNavigationProp;
@@ -38,7 +37,6 @@ export default function SettingsScreen() {
updateNotificationSettings,
updateDisplaySettings,
updatePrivacySettings,
- updateUserPreferences,
} = useAppStore();
const notif = userPreferences?.notifications;
@@ -58,7 +56,7 @@ export default function SettingsScreen() {
const dataStr = await exportData();
const data = JSON.parse(dataStr);
Alert.alert('导出成功', `数据已导出,共 ${data.tasks?.length || 0} 个任务、${data.projects?.length || 0} 个项目`);
- } catch (error) {
+ } catch {
Alert.alert('导出失败', '导出数据时发生错误,请重试。');
}
},
@@ -85,7 +83,7 @@ export default function SettingsScreen() {
});
await importData(sampleData);
toast.success('数据已成功导入');
- } catch (error) {
+ } catch {
toast.error('导入数据失败,请检查文件格式是否正确');
}
},
diff --git a/screens/TagsScreen.tsx b/screens/TagsScreen.tsx
index a29fa75..ecdd79b 100644
--- a/screens/TagsScreen.tsx
+++ b/screens/TagsScreen.tsx
@@ -12,7 +12,7 @@ import {
Modal,
ScrollView,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
diff --git a/screens/TaskDetailScreen.tsx b/screens/TaskDetailScreen.tsx
index 3b98d89..74f803d 100644
--- a/screens/TaskDetailScreen.tsx
+++ b/screens/TaskDetailScreen.tsx
@@ -18,7 +18,7 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import DateTimePicker from '@react-native-community/datetimepicker';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
-import { RootStackParamList, Priority, TaskStatus, Task, RecurrenceRule, Comment, Attachment, ChecklistItem } from '../src/shared/types';
+import { RootStackParamList, Priority, TaskStatus, Task } from '../src/shared/types';
import { Button } from '../src/shared/components/common';
import { toast } from '../src/shared/components/common/Toast';
import { Pomodoro } from '../src/shared/components/common/Pomodoro';
@@ -53,13 +53,11 @@ export default function TaskDetailScreen() {
updateTask,
deleteTask,
toggleTaskComplete,
- addTagToTask,
removeTagFromTask,
addSubtask,
updateSubtask,
deleteSubtask,
addComment,
- addAttachment,
addChecklistItem,
toggleChecklistItem,
deleteChecklistItem,
@@ -73,20 +71,19 @@ export default function TaskDetailScreen() {
const [editedTask, setEditedTask] = useState(null);
const [showDatePicker, setShowDatePicker] = useState(false);
const [showTimePicker, setShowTimePicker] = useState(false);
- const [showPriorityPicker, setShowPriorityPicker] = useState(false);
- const [showStatusPicker, setShowStatusPicker] = useState(false);
- const [showProjectPicker, setShowProjectPicker] = useState(false);
- const [showCategoryPicker, setShowCategoryPicker] = useState(false);
- const [showTagPicker, setShowTagPicker] = useState(false);
const [newComment, setNewComment] = useState('');
const [newSubtaskTitle, setNewSubtaskTitle] = useState('');
const [newChecklistItem, setNewChecklistItem] = useState('');
const [showSubtasks, setShowSubtasks] = useState(true);
const [showPomodoro, setShowPomodoro] = useState(false);
- const [showNLInput, setShowNLInput] = useState(false);
const [showChecklist, setShowChecklist] = useState(true);
const [showComments, setShowComments] = useState(true);
const [showAttachments, setShowAttachments] = useState(true);
+ const [, setShowProjectPicker] = useState(false);
+ const [, setShowCategoryPicker] = useState(false);
+ const [, setShowTagPicker] = useState(false);
+ const [, setShowStatusPicker] = useState(false);
+ const [, setShowPriorityPicker] = useState(false);
useEffect(() => {
if (task) {
@@ -221,13 +218,6 @@ export default function TaskDetailScreen() {
deleteChecklistItem(task.id, itemId);
};
- const handleAddTag = (tagId: string) => {
- if (!task.tags.includes(tagId)) {
- addTagToTask(task.id, tagId);
- }
- setShowTagPicker(false);
- };
-
const handleRemoveTag = (tagId: string) => {
removeTagFromTask(task.id, tagId);
};
diff --git a/screens/TemplatesScreen.tsx b/screens/TemplatesScreen.tsx
index c93bf49..32d8262 100644
--- a/screens/TemplatesScreen.tsx
+++ b/screens/TemplatesScreen.tsx
@@ -7,12 +7,11 @@ import {
TouchableOpacity,
TextInput,
SafeAreaView,
- Platform,
Alert,
Modal,
ScrollView,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
@@ -32,11 +31,9 @@ const TEMPLATE_TYPES = [
export default function TemplatesScreen() {
const navigation = useNavigation();
- const { theme, templates, addTemplate, updateTemplate, deleteTemplate, applyTemplate } = useAppStore();
+ const { theme, templates, addTemplate, deleteTemplate, applyTemplate } = useAppStore();
const [showAddModal, setShowAddModal] = useState(false);
- const [showEditModal, setShowEditModal] = useState(false);
- const [selectedTemplate, setSelectedTemplate] = useState(null);
const [newTemplate, setNewTemplate] = useState>({
name: '',
description: '',
@@ -46,6 +43,8 @@ export default function TemplatesScreen() {
});
const [searchQuery, setSearchQuery] = useState('');
const [selectedType, setSelectedType] = useState(null);
+ const [, setSelectedTemplate] = useState(null);
+ const [, setShowEditModal] = useState(false);
const filteredTemplates = templates.filter((template) => {
if (selectedType && template.type !== selectedType) return false;
diff --git a/screens/ViewsScreen.tsx b/screens/ViewsScreen.tsx
index 6a224c0..ad8e706 100644
--- a/screens/ViewsScreen.tsx
+++ b/screens/ViewsScreen.tsx
@@ -3,7 +3,6 @@ import {
View,
Text,
StyleSheet,
- FlatList,
TouchableOpacity,
TextInput,
SafeAreaView,
@@ -12,7 +11,7 @@ import {
Modal,
ScrollView,
} from 'react-native';
-import { useNavigation, useFocusEffect } from '@react-navigation/native';
+import { useNavigation } from '@react-navigation/native';
import { NativeStackNavigationProp } from '@react-navigation/native-stack';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../src/shared/store';
diff --git a/src/shared/components/common/DatePicker.tsx b/src/shared/components/common/DatePicker.tsx
index c288796..7cbf8d6 100644
--- a/src/shared/components/common/DatePicker.tsx
+++ b/src/shared/components/common/DatePicker.tsx
@@ -6,8 +6,6 @@ import {
Modal,
TouchableOpacity,
TouchableWithoutFeedback,
- TextInput,
- ScrollView,
} from 'react-native';
import DateTimePicker from '@react-native-community/datetimepicker';
import { useAppStore } from '../../store';
diff --git a/src/shared/components/common/DraggableList.tsx b/src/shared/components/common/DraggableList.tsx
index cbb5a30..cc2c29f 100644
--- a/src/shared/components/common/DraggableList.tsx
+++ b/src/shared/components/common/DraggableList.tsx
@@ -4,7 +4,6 @@ import {
StyleSheet,
Animated,
PanResponder,
- Platform,
LayoutChangeEvent,
ViewStyle,
TouchableOpacity,
@@ -43,7 +42,7 @@ export function DraggableList({
keyExtractor,
renderItem,
onReorder,
- itemHeight = 64,
+ itemHeight: _itemHeight = 64,
showHandle = true,
handleComponent,
dragActivationMs = 250,
diff --git a/src/shared/components/common/FocusMode.tsx b/src/shared/components/common/FocusMode.tsx
index 85c4c84..67cb98b 100644
--- a/src/shared/components/common/FocusMode.tsx
+++ b/src/shared/components/common/FocusMode.tsx
@@ -29,11 +29,9 @@ const LABELS: Record = { focus: '专注', shortBreak: '短休息'
const { width } = Dimensions.get('window');
const CIRCLE_SIZE = Math.min(width * 0.7, 320);
const STROKE = 8;
-const RADIUS = (CIRCLE_SIZE - STROKE) / 2;
-const CIRCUMFERENCE = 2 * Math.PI * RADIUS;
export function FocusMode({ visible, onClose, taskTitle, onComplete }: FocusModeProps) {
- const { theme, addSession } = useAppStore();
+ const { addSession } = useAppStore();
const [phase, setPhase] = useState('focus');
const [remaining, setRemaining] = useState(DURATIONS.focus);
const [running, setRunning] = useState(false);
@@ -139,7 +137,6 @@ export function FocusMode({ visible, onClose, taskTitle, onComplete }: FocusMode
const mm = String(Math.floor(remaining / 60)).padStart(2, '0');
const ss = String(remaining % 60).padStart(2, '0');
- const progress = (DURATIONS[phase] - remaining) / DURATIONS[phase];
const phaseColor = phase === 'focus' ? '#10b981' : phase === 'shortBreak' ? '#3b82f6' : '#8b5cf6';
const breatheScale = breathe.interpolate({
@@ -218,7 +215,7 @@ export function FocusMode({ visible, onClose, taskTitle, onComplete }: FocusMode
>
{
if (intervalRef.current) clearInterval(intervalRef.current);
};
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, [running]);
useEffect(() => {
@@ -114,13 +114,6 @@ export function Pomodoro({ visible, onClose, taskTitle, onComplete }: PomodoroPr
const timeStr = `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
const modeColor = mode === 'focus' ? theme.colors.primary : mode === 'shortBreak' ? theme.colors.success : theme.colors.info;
- const radius = 110;
- const circumference = 2 * Math.PI * radius;
- const strokeDashoffset = progressAnim.interpolate({
- inputRange: [0, 1],
- outputRange: [circumference, 0],
- });
-
return (
diff --git a/src/shared/components/common/SideDrawer.tsx b/src/shared/components/common/SideDrawer.tsx
index 054b4e0..ec1d360 100644
--- a/src/shared/components/common/SideDrawer.tsx
+++ b/src/shared/components/common/SideDrawer.tsx
@@ -376,7 +376,11 @@ const styles = StyleSheet.create({
flex: 1,
},
backdrop: {
- ...StyleSheet.absoluteFillObject,
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
},
drawer: {
position: 'absolute',
diff --git a/src/shared/components/common/SwipeableTaskCard.tsx b/src/shared/components/common/SwipeableTaskCard.tsx
index ecec57c..967ff13 100644
--- a/src/shared/components/common/SwipeableTaskCard.tsx
+++ b/src/shared/components/common/SwipeableTaskCard.tsx
@@ -165,7 +165,11 @@ const styles = StyleSheet.create({
overflow: 'hidden',
},
actionBackground: {
- ...StyleSheet.absoluteFillObject,
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'stretch',
diff --git a/src/shared/components/common/TagInput.tsx b/src/shared/components/common/TagInput.tsx
index 6a37497..c16373f 100644
--- a/src/shared/components/common/TagInput.tsx
+++ b/src/shared/components/common/TagInput.tsx
@@ -21,7 +21,7 @@ export const TagInput: React.FC = ({
value,
onChange,
label,
- placeholder = '添加标签...',
+ placeholder: _placeholder = '添加标签...',
}) => {
const { theme, tags } = useAppStore();
const [showModal, setShowModal] = useState(false);
@@ -47,13 +47,6 @@ export const TagInput: React.FC = ({
if (!searchQuery.trim()) return;
const newTagId = `tag-${Date.now()}`;
- const newTag = {
- id: newTagId,
- name: searchQuery.trim(),
- color: '#3b82f6',
- createdAt: new Date(),
- updatedAt: new Date(),
- };
onChange([...value, newTagId]);
setSearchQuery('');
diff --git a/src/shared/components/common/TaskDependencies.tsx b/src/shared/components/common/TaskDependencies.tsx
index 729d936..8f64a39 100644
--- a/src/shared/components/common/TaskDependencies.tsx
+++ b/src/shared/components/common/TaskDependencies.tsx
@@ -12,12 +12,11 @@ export interface TaskDependenciesProps {
export function TaskDependencies({ task, onPressTask }: TaskDependenciesProps) {
const { theme, tasks } = useAppStore();
- const { blockedBy, blocking, dependsOn } = useMemo(() => {
+ const { blockedBy, blocking } = useMemo(() => {
const all = new Map(tasks.map((t) => [t.id, t]));
const blockedBy = (task.blockedBy || []).map((id) => all.get(id)).filter(Boolean) as Task[];
const blocking = (task.dependencies || []).map((id) => all.get(id)).filter(Boolean) as Task[];
- const dependsOn = blockedBy;
- return { blockedBy, blocking, dependsOn };
+ return { blockedBy, blocking };
}, [task, tasks]);
if (blockedBy.length === 0 && blocking.length === 0) {
@@ -120,7 +119,7 @@ interface DependencyGraphProps {
export function DependencyGraph({ taskIds, onPressTask }: DependencyGraphProps) {
const { theme, tasks } = useAppStore();
- const idSet = new Set(taskIds);
+ const idSet = useMemo(() => new Set(taskIds), [taskIds]);
const subset = tasks.filter((t) => idSet.has(t.id));
const edges = useMemo(() => {
const e: { from: string; to: string }[] = [];
diff --git a/src/shared/components/common/TaskSuggestions.tsx b/src/shared/components/common/TaskSuggestions.tsx
index b01a47b..b5ae3e3 100644
--- a/src/shared/components/common/TaskSuggestions.tsx
+++ b/src/shared/components/common/TaskSuggestions.tsx
@@ -1,12 +1,10 @@
-import React, { useMemo, useCallback } from 'react';
+import React, { useMemo } from 'react';
import {
View,
Text,
StyleSheet,
TouchableOpacity,
ScrollView,
- Platform,
- Animated,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../../store';
diff --git a/src/shared/components/common/Toast.tsx b/src/shared/components/common/Toast.tsx
index f471f2e..24f5fd3 100644
--- a/src/shared/components/common/Toast.tsx
+++ b/src/shared/components/common/Toast.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef, useState, useCallback } from 'react';
+import React, { useEffect, useRef, useState } from 'react';
import {
View,
Text,
diff --git a/src/shared/components/common/VoiceInput.tsx b/src/shared/components/common/VoiceInput.tsx
index 7d89080..a08107e 100644
--- a/src/shared/components/common/VoiceInput.tsx
+++ b/src/shared/components/common/VoiceInput.tsx
@@ -73,7 +73,9 @@ export function VoiceInput({ onResult, size = 48, color, hint = '点击开始语
if (recognitionRef.current) {
try {
recognitionRef.current.stop();
- } catch {}
+ } catch {
+ // ignore stop errors
+ }
recognitionRef.current = null;
}
setListening(false);
diff --git a/src/shared/components/common/WhiteNoisePlayer.tsx b/src/shared/components/common/WhiteNoisePlayer.tsx
index 55a9fc4..63bcd36 100644
--- a/src/shared/components/common/WhiteNoisePlayer.tsx
+++ b/src/shared/components/common/WhiteNoisePlayer.tsx
@@ -10,7 +10,6 @@ import {
Vibration,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
-import { useAppStore } from '../../store';
import { toast } from './Toast';
export interface NoiseTrack {
@@ -119,7 +118,6 @@ export const WhiteNoisePlayer = forwardRef void;
compact?: boolean;
}>(({ autoStart = false, onStateChange, compact = false }, ref) => {
- const { theme } = useAppStore();
const [currentTrackId, setCurrentTrackId] = useState('white');
const [playing, setPlaying] = useState(false);
const [volume, setVolume] = useState(0.4);
@@ -136,6 +134,7 @@ export const WhiteNoisePlayer = forwardRef stopAudio();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
@@ -168,7 +167,9 @@ export const WhiteNoisePlayer = forwardRef t.id === currentTrackId) ?? NOISE_TRACKS[0];
const buffer = createNoiseBuffer(ctx, track.generator);
@@ -184,7 +185,9 @@ export const WhiteNoisePlayer = forwardRef {
if (audioRef.current?.source) {
- try { audioRef.current.source.stop(); } catch {}
+ try { audioRef.current.source.stop(); } catch {
+ // ignore stop errors
+ }
audioRef.current.source = null;
}
setPlaying(false);
@@ -202,7 +205,9 @@ export const WhiteNoisePlayer = forwardRef {
setCurrentTrackId(id);
if (audioRef.current?.source) {
- try { audioRef.current.source.stop(); } catch {}
+ try { audioRef.current.source.stop(); } catch {
+ // ignore stop errors
+ }
}
startAudio();
}, 50);
diff --git a/src/shared/components/views/GanttView.tsx b/src/shared/components/views/GanttView.tsx
index 21c6681..e22ca94 100644
--- a/src/shared/components/views/GanttView.tsx
+++ b/src/shared/components/views/GanttView.tsx
@@ -5,16 +5,12 @@ import {
StyleSheet,
ScrollView,
TouchableOpacity,
- Dimensions,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../../store';
import { Task } from '../../types';
-const { width } = Dimensions.get('window');
-
const DAY_WIDTH = 40;
-const HOUR_WIDTH = 20;
const ROW_HEIGHT = 50;
interface GanttViewProps {
@@ -33,7 +29,7 @@ export const GanttView: React.FC = ({
const { theme } = useAppStore();
const [viewMode, setViewMode] = useState<'day' | 'week' | 'month'>('week');
- const { startDate, endDate, days, tasksWithDates } = useMemo(() => {
+ const { days, tasksWithDates } = useMemo(() => {
const tasksWithDueDates = tasks.filter((task) => task.dueDate && !task.isDeleted);
if (tasksWithDueDates.length === 0) {
@@ -47,8 +43,6 @@ export const GanttView: React.FC = ({
}
return {
- startDate: start,
- endDate: end,
days,
tasksWithDates: [],
};
@@ -82,8 +76,6 @@ export const GanttView: React.FC = ({
});
return {
- startDate: minDate,
- endDate: maxDate,
days: allDays,
tasksWithDates: tasksData,
};
diff --git a/src/shared/components/views/KanbanView.tsx b/src/shared/components/views/KanbanView.tsx
index 8c3d375..bf3107c 100644
--- a/src/shared/components/views/KanbanView.tsx
+++ b/src/shared/components/views/KanbanView.tsx
@@ -1,4 +1,4 @@
-import React, { useState, useMemo } from 'react';
+import React, { useMemo } from 'react';
import {
View,
Text,
@@ -35,7 +35,7 @@ interface KanbanViewProps {
}
export const KanbanView: React.FC = ({ tasks, onTaskPress }) => {
- const { theme, updateTask } = useAppStore();
+ const { theme } = useAppStore();
const tasksByStatus = useMemo(() => {
const grouped: Record = {
@@ -57,10 +57,6 @@ export const KanbanView: React.FC = ({ tasks, onTaskPress }) =>
return grouped;
}, [tasks]);
- const handleTaskDrop = (taskId: string, newStatus: TaskStatus) => {
- updateTask(taskId, { status: newStatus });
- };
-
const renderTaskCard = (task: Task) => {
const isOverdue = task.dueDate && new Date(task.dueDate) < new Date() && !task.completed;
diff --git a/src/shared/components/views/TableView.tsx b/src/shared/components/views/TableView.tsx
index 0fc1617..2f3e3b4 100644
--- a/src/shared/components/views/TableView.tsx
+++ b/src/shared/components/views/TableView.tsx
@@ -5,14 +5,11 @@ import {
StyleSheet,
ScrollView,
TouchableOpacity,
- Dimensions,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../../store';
import { Task, Priority, TaskStatus } from '../../types';
-const { width } = Dimensions.get('window');
-
interface Column {
key: string;
title: string;
@@ -41,7 +38,6 @@ export const TableView: React.FC = ({ tasks, onTaskPress }) => {
const { theme, projects, categories, tags, toggleTaskComplete } = useAppStore();
const [sortBy, setSortBy] = useState('dueDate');
const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('asc');
- const [selectedTasks, setSelectedTasks] = useState>(new Set());
const sortedTasks = useMemo(() => {
const result = [...tasks].filter((t) => !t.isDeleted);
@@ -57,15 +53,17 @@ export const TableView: React.FC = ({ tasks, onTaskPress }) => {
case 'status':
comparison = a.status.localeCompare(b.status);
break;
- case 'priority':
+ case 'priority': {
const priorityOrder = { critical: 0, urgent: 1, high: 2, medium: 3, low: 4 };
comparison = priorityOrder[a.priority] - priorityOrder[b.priority];
break;
- case 'dueDate':
+ }
+ case 'dueDate': {
const aDate = a.dueDate ? new Date(a.dueDate).getTime() : Infinity;
const bDate = b.dueDate ? new Date(b.dueDate).getTime() : Infinity;
comparison = aDate - bDate;
break;
+ }
default:
comparison = 0;
}
@@ -86,24 +84,6 @@ export const TableView: React.FC = ({ tasks, onTaskPress }) => {
}
};
- const handleSelectTask = (taskId: string) => {
- const newSelected = new Set(selectedTasks);
- if (newSelected.has(taskId)) {
- newSelected.delete(taskId);
- } else {
- newSelected.add(taskId);
- }
- setSelectedTasks(newSelected);
- };
-
- const handleSelectAll = () => {
- if (selectedTasks.size === sortedTasks.length) {
- setSelectedTasks(new Set());
- } else {
- setSelectedTasks(new Set(sortedTasks.map((t) => t.id)));
- }
- };
-
const getStatusLabel = (status: TaskStatus): string => {
const labels: Record = {
'todo': '待办',
@@ -185,7 +165,6 @@ export const TableView: React.FC = ({ tasks, onTaskPress }) => {
);
const renderRow = (task: Task) => {
- const isSelected = selectedTasks.has(task.id);
const project = projects.find((p) => p.id === task.projectId);
const category = categories.find((c) => c.id === task.categoryId);
const taskTags = tags.filter((t) => task.tags.includes(t.id));
@@ -200,7 +179,6 @@ export const TableView: React.FC = ({ tasks, onTaskPress }) => {
style={[
styles.tableRow,
{ backgroundColor: theme.colors.surface },
- isSelected && { backgroundColor: theme.colors.primary + '10' },
]}
>
diff --git a/src/shared/components/views/TimeBlockView.tsx b/src/shared/components/views/TimeBlockView.tsx
index e99eede..7e8ca4b 100644
--- a/src/shared/components/views/TimeBlockView.tsx
+++ b/src/shared/components/views/TimeBlockView.tsx
@@ -5,13 +5,11 @@ import {
StyleSheet,
ScrollView,
TouchableOpacity,
- Dimensions,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../../store';
import { Task } from '../../types';
-const { width } = Dimensions.get('window');
const HOUR_HEIGHT = 60;
const TIME_COLUMN_WIDTH = 60;
diff --git a/src/shared/components/views/TimelineView.tsx b/src/shared/components/views/TimelineView.tsx
index b990cee..e95bd61 100644
--- a/src/shared/components/views/TimelineView.tsx
+++ b/src/shared/components/views/TimelineView.tsx
@@ -5,14 +5,11 @@ import {
StyleSheet,
ScrollView,
TouchableOpacity,
- Dimensions,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppStore } from '../../store';
import { Task } from '../../types';
-const { width } = Dimensions.get('window');
-
interface TimelineViewProps {
tasks: Task[];
onTaskPress?: (taskId: string) => void;
diff --git a/src/shared/hooks/useUndo.ts b/src/shared/hooks/useUndo.ts
index f0cfa71..d6b3930 100644
--- a/src/shared/hooks/useUndo.ts
+++ b/src/shared/hooks/useUndo.ts
@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react';
import { useAppStore } from '../store';
-import { Task, Project, Note, Goal, Habit, View, Category, Tag, Template, AutomationRule } from '../types';
+import { Task, Project, Note, Goal, Habit } from '../types';
import { toast } from '../components/common/Toast';
type UndoableAction = {
diff --git a/src/shared/store/index.ts b/src/shared/store/index.ts
index 0e1c3fd..f85934e 100644
--- a/src/shared/store/index.ts
+++ b/src/shared/store/index.ts
@@ -1,5 +1,4 @@
import { create } from 'zustand';
-import { persist, createJSONStorage } from 'zustand/middleware';
import AsyncStorage from '@react-native-async-storage/async-storage';
import {
Task,
@@ -1958,13 +1957,13 @@ export const useAppStore = create((set, get) => ({
}
},
- executeAutomation: async (ruleId, context) => {
+ executeAutomation: async (ruleId, _context) => {
const rule = get().automationRules.find((r) => r.id === ruleId);
if (!rule || !rule.isEnabled) return;
try {
// Execute actions based on rule
- rule.actions.forEach((action) => {
+ rule.actions.forEach((_action) => {
// Action execution logic would go here.
// The shape of `action` is intentionally left to product requirements;
// intentionally NOT logging to avoid noisy devtools in production builds.
diff --git a/src/shared/utils/naturalLanguageParser.ts b/src/shared/utils/naturalLanguageParser.ts
index a14363f..503f990 100644
--- a/src/shared/utils/naturalLanguageParser.ts
+++ b/src/shared/utils/naturalLanguageParser.ts
@@ -16,11 +16,6 @@ const ZH_NUM_MAP: Record = {
'一': 1, '二': 2, '两': 2, '三': 3, '四': 4, '五': 5, '六': 6, '七': 7, '八': 8, '九': 9, '十': 10,
};
-const HOUR_PATTERNS = [
- /(\d{1,2})[点时]/g,
- /([一二两三四五六七八九十])[点时]/g,
-];
-
const RELATIVE_DAYS: Record Date> = {
'今天': () => { const d = new Date(); d.setHours(0, 0, 0, 0); return d; },
'明天': () => { const d = new Date(); d.setDate(d.getDate() + 1); d.setHours(0, 0, 0, 0); return d; },
@@ -76,22 +71,6 @@ function nextWeekday(target: number, thisWeek = false): Date {
return d;
}
-function getTimeModifier(hourKeyword: string, currentHour: number): number {
- if (/明早|明晨|明上午/.test(hourKeyword)) {
- const d = new Date();
- d.setDate(d.getDate() + 1);
- d.setHours(9, 0, 0, 0);
- return d.getTime();
- }
- if (/明晚|明晚间/.test(hourKeyword)) {
- const d = new Date();
- d.setDate(d.getDate() + 1);
- d.setHours(19, 0, 0, 0);
- return d.getTime();
- }
- return currentHour;
-}
-
export function parseNaturalLanguage(input: string): ParsedTask {
let title = input.trim();
const result: ParsedTask = { title: '' };
@@ -153,26 +132,22 @@ export function parseNaturalLanguage(input: string): ParsedTask {
}
// 6. Date - relative day
- let dateMatched = false;
for (const [keyword, getDate] of Object.entries(RELATIVE_DAYS)) {
if (title.includes(keyword)) {
const baseDate = getDate();
result.dueDate = baseDate;
title = title.replace(keyword, '').trim();
- dateMatched = true;
break;
}
}
// 7. Time - keyword based (上午/下午/晚上)
- let timeMatched = false;
for (const { pattern, hour } of TIME_KEYWORDS) {
if (pattern.test(title)) {
const baseDate = result.dueDate || new Date();
baseDate.setHours(hour, 0, 0, 0);
result.dueDate = baseDate;
title = title.replace(pattern, '').trim();
- timeMatched = true;
break;
}
}
@@ -188,7 +163,6 @@ export function parseNaturalLanguage(input: string): ParsedTask {
baseDate.setHours(hour, minute, 0, 0);
result.dueDate = baseDate;
title = title.replace(m[0], '').trim();
- timeMatched = true;
}
// 9. Chinese time
@@ -200,7 +174,6 @@ export function parseNaturalLanguage(input: string): ParsedTask {
baseDate.setHours(hour, 0, 0, 0);
result.dueDate = baseDate;
title = title.replace(m[0], '').trim();
- timeMatched = true;
}
// 10. Specific dates (12/25, 2026-06-15, 6月15日)
diff --git a/tsconfig.json b/tsconfig.json
index 51eb194..8fa332d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -26,7 +26,9 @@
"exclude": [
"node_modules",
"dist",
- ".expo"
+ ".expo",
+ "desktop",
+ "backend"
],
"extends": "expo/tsconfig.base"
}