diff --git a/.env b/.env new file mode 100644 index 0000000..5f969f5 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +EXPO_PUBLIC_SENTRY_DSN=https://bdb940f3a950ee46ce8ba651dee9b433@o4511094585819136.ingest.de.sentry.io/4511094601810000 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 29ed2b0..1e88ecf 100644 --- a/.gitignore +++ b/.gitignore @@ -48,4 +48,5 @@ CLAUDE.md docs/ feature.md livePlan.md -Promotion.md \ No newline at end of file +Promotion.md +.env.local diff --git a/App.tsx b/App.tsx index 0329d0c..b81b559 100644 --- a/App.tsx +++ b/App.tsx @@ -1,14 +1,34 @@ import { StatusBar } from 'expo-status-bar'; import { StyleSheet, Text, View } from 'react-native'; +import * as Sentry from '@sentry/react-native'; -export default function App() { +Sentry.init({ + dsn: 'https://bdb940f3a950ee46ce8ba651dee9b433@o4511094585819136.ingest.de.sentry.io/4511094601810000', + + // Adds more context data to events (IP address, cookies, user, etc.) + // For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/ + sendDefaultPii: true, + + // Enable Logs + enableLogs: true, + + // Configure Session Replay + replaysSessionSampleRate: 0.1, + replaysOnErrorSampleRate: 1, + integrations: [Sentry.mobileReplayIntegration(), Sentry.feedbackIntegration()], + + // uncomment the line below to enable Spotlight (https://spotlightjs.com) + // spotlight: __DEV__, +}); + +export default Sentry.wrap(function App() { return ( Open up App.tsx to start working on your app! ); -} +}); const styles = StyleSheet.create({ container: { diff --git a/app.json b/app.json index ffec55f..8ac1444 100644 --- a/app.json +++ b/app.json @@ -1,7 +1,7 @@ { "expo": { "name": "JKVideo", - "slug": "jkvideo", + "slug": "jsvideo", "version": "1.0.5", "scheme": "bilibili", "orientation": "default", @@ -24,6 +24,9 @@ }, "predictiveBackGestureEnabled": false, "permissions": [ + "android.permission.RECORD_AUDIO", + "android.permission.MODIFY_AUDIO_SETTINGS", + "android.permission.REQUEST_INSTALL_PACKAGES", "android.permission.RECORD_AUDIO", "android.permission.MODIFY_AUDIO_SETTINGS", "android.permission.REQUEST_INSTALL_PACKAGES" @@ -37,10 +40,27 @@ "plugins": [ "expo-router", "react-native-video", - "expo-screen-orientation" + "expo-screen-orientation", + "expo-updates", + "@sentry/react-native/expo" ], "experiments": { "typedRoutes": true - } + }, + "runtimeVersion": { + "policy": "appVersion" + }, + "updates": { + "url": "https://u.expo.dev/eac4192a-ae80-461c-8fff-6e1a8b777bd1", + "checkAutomatically": "ON_LOAD", + "fallbackToCacheTimeout": 0 + }, + "extra": { + "router": {}, + "eas": { + "projectId": "eac4192a-ae80-461c-8fff-6e1a8b777bd1" + } + }, + "owner": "jinsha" } } diff --git a/app/_layout.tsx b/app/_layout.tsx index d602dc7..bb2fbc3 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,14 +1,24 @@ import { Stack } from 'expo-router'; import { StatusBar } from 'expo-status-bar'; import { SafeAreaProvider } from 'react-native-safe-area-context'; -import { View } from 'react-native'; +import { Text, View } from 'react-native'; import { useEffect } from 'react'; import { useAuthStore } from '../store/authStore'; import { useDownloadStore } from '../store/downloadStore'; import { useSettingsStore } from '../store/settingsStore'; import { MiniPlayer } from '../components/MiniPlayer'; +import * as Updates from 'expo-updates'; +import * as Sentry from '@sentry/react-native'; +import { ErrorBoundary } from '@sentry/react-native'; -export default function RootLayout() { +Sentry.init({ + dsn: process.env.EXPO_PUBLIC_SENTRY_DSN ?? '', + enabled: !__DEV__, + tracesSampleRate: 0.05, + environment: process.env.EXPO_PUBLIC_APP_ENV ?? 'production', +}); + +function RootLayout() { const restore = useAuthStore(s => s.restore); const loadDownloads = useDownloadStore(s => s.loadFromStorage); const restoreSettings = useSettingsStore(s => s.restore); @@ -17,56 +27,73 @@ export default function RootLayout() { restore(); loadDownloads(); restoreSettings(); + + const checkOTA = async () => { + if (!Updates.isEnabled) return; + try { + const update = await Updates.checkForUpdateAsync(); + if (update.isAvailable) { + await Updates.fetchUpdateAsync(); + } + } catch { + // 静默失败,不影响正常使用 + } + }; + checkOTA(); }, []); return ( - - - - - - - - + 发生错误,请重启 App}> + + + + + + + + + ); } + +export default Sentry.wrap(RootLayout); diff --git a/eas.json b/eas.json new file mode 100644 index 0000000..ba470c6 --- /dev/null +++ b/eas.json @@ -0,0 +1,28 @@ +{ + "cli": { + "version": ">= 16.0.0" + }, + "build": { + "development": { + "developmentClient": true, + "distribution": "internal", + "channel": "development" + }, + "preview": { + "distribution": "internal", + "channel": "preview" + }, + "production": { + "channel": "production", + "env": { + "EXPO_PUBLIC_APP_ENV": "production", + "SENTRY_AUTH_TOKEN": "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", + "SENTRY_ORG": "your-org-slug", + "SENTRY_PROJECT": "your-project-slug" + } + } + }, + "submit": { + "production": {} + } +} diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..9d82ec1 --- /dev/null +++ b/metro.config.js @@ -0,0 +1,23 @@ +const path = require('path'); +const { + getSentryExpoConfig +} = require("@sentry/react-native/metro"); + +const config = getSentryExpoConfig(__dirname); + +const originalResolveRequest = config.resolver.resolveRequest; + +config.resolver.resolveRequest = (context, moduleName, platform) => { + if (platform === 'web' && moduleName === 'react-native-pager-view') { + return { + filePath: path.resolve(__dirname, 'shims/react-native-pager-view.web.tsx'), + type: 'sourceFile', + }; + } + if (originalResolveRequest) { + return originalResolveRequest(context, moduleName, platform); + } + return context.resolveRequest(context, moduleName, platform); +}; + +module.exports = config; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 9e597df..dccf46f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,17 @@ { "name": "jkvideo", - "version": "1.0.0", + "version": "1.0.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "jkvideo", - "version": "1.0.0", + "version": "1.0.5", "dependencies": { "@dr.pogodin/react-native-static-server": "^0.26.0", "@expo/vector-icons": "^15.0.2", "@react-native-async-storage/async-storage": "2.2.0", + "@sentry/react-native": "~7.11.0", "axios": "^1.13.6", "expo": "~55.0.5", "expo-av": "^16.0.8", @@ -26,6 +27,7 @@ "expo-screen-orientation": "~55.0.8", "expo-status-bar": "~55.0.4", "expo-system-ui": "~55.0.9", + "expo-updates": "~55.0.15", "pako": "^2.1.0", "react": "19.2.0", "react-dom": "19.2.0", @@ -2924,6 +2926,335 @@ "nanoid": "^3.3.11" } }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.37.0.tgz", + "integrity": "sha512-rqdESYaVio9Ktz55lhUhtBsBUCF3wvvJuWia5YqoHDd+egyIfwWxITTAa0TSEyZl7283A4WNHNl0hyeEMblmfA==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.37.0.tgz", + "integrity": "sha512-P0PVlfrDvfvCYg2KPIS7YUG/4i6ZPf8z1MicXx09C9Cz9W9UhSBh/nii13eBdDtLav2BFMKhvaFMcghXHX03Hw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.37.0.tgz", + "integrity": "sha512-snuk12ZaDerxesSnetNIwKoth/51R0y/h3eXD/bGtXp+hnSkeXN5HanI/RJl297llRjn4zJYRShW9Nx86Ay0Dw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.37.0.tgz", + "integrity": "sha512-PyIYSbjLs+L5essYV0MyIsh4n5xfv2eV7l0nhUoPJv9Bak3kattQY3tholOj0EP3SgKgb+8HSZnmazgF++Hbog==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.8.0.tgz", + "integrity": "sha512-cy/9Eipkv23MsEJ4IuB4dNlVwS9UqOzI3Eu+QPake5BVFgPYCX0uP0Tr3Z43Ime6Rb+BiDnWC51AJK9i9afHYw==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.37.0.tgz", + "integrity": "sha512-kheqJNqGZP5TSBCPv4Vienv1sfZwXKHQDYR+xrdHHYdZqwWuZMJJW/cLO9XjYAe+B9NnJ4UwJOoY4fPvU+HQ1Q==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.37.0", + "@sentry-internal/feedback": "10.37.0", + "@sentry-internal/replay": "10.37.0", + "@sentry-internal/replay-canvas": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/cli": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.58.4.tgz", + "integrity": "sha512-ArDrpuS8JtDYEvwGleVE+FgR+qHaOp77IgdGSacz6SZy6Lv90uX0Nu4UrHCQJz8/xwIcNxSqnN22lq0dH4IqTg==", + "hasInstallScript": true, + "license": "FSL-1.1-MIT", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.58.4", + "@sentry/cli-linux-arm": "2.58.4", + "@sentry/cli-linux-arm64": "2.58.4", + "@sentry/cli-linux-i686": "2.58.4", + "@sentry/cli-linux-x64": "2.58.4", + "@sentry/cli-win32-arm64": "2.58.4", + "@sentry/cli-win32-i686": "2.58.4", + "@sentry/cli-win32-x64": "2.58.4" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.58.4.tgz", + "integrity": "sha512-kbTD+P4X8O+nsNwPxCywtj3q22ecyRHWff98rdcmtRrvwz8CKi/T4Jxn/fnn2i4VEchy08OWBuZAqaA5Kh2hRQ==", + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.58.4.tgz", + "integrity": "sha512-rdQ8beTwnN48hv7iV7e7ZKucPec5NJkRdrrycMJMZlzGBPi56LqnclgsHySJ6Kfq506A2MNuQnKGaf/sBC9REA==", + "cpu": [ + "arm" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.58.4.tgz", + "integrity": "sha512-0g0KwsOozkLtzN8/0+oMZoOuQ0o7W6O+hx+ydVU1bktaMGKEJLMAWxOQNjsh1TcBbNIXVOKM/I8l0ROhaAb8Ig==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.58.4.tgz", + "integrity": "sha512-NseoIQAFtkziHyjZNPTu1Gm1opeQHt7Wm1LbLrGWVIRvUOzlslO9/8i6wETUZ6TjlQxBVRgd3Q0lRBG2A8rFYA==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.58.4.tgz", + "integrity": "sha512-d3Arz+OO/wJYTqCYlSN3Ktm+W8rynQ/IMtSZLK8nu0ryh5mJOh+9XlXY6oDXw4YlsM8qCRrNquR8iEI1Y/IH+Q==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.58.4.tgz", + "integrity": "sha512-bqYrF43+jXdDBh0f8HIJU3tbvlOFtGyRjHB8AoRuMQv9TEDUfENZyCelhdjA+KwDKYl48R1Yasb4EHNzsoO83w==", + "cpu": [ + "arm64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.58.4.tgz", + "integrity": "sha512-3triFD6jyvhVcXOmGyttf+deKZcC1tURdhnmDUIBkiDPJKGT/N5xa4qAtHJlAB/h8L9jgYih9bvJnvvFVM7yug==", + "cpu": [ + "x86", + "ia32" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.58.4", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.58.4.tgz", + "integrity": "sha512-cSzN4PjM1RsCZ4pxMjI0VI7yNCkxiJ5jmWncyiwHXGiXrV1eXYdQ3n1LhUYLZ91CafyprR0OhDcE+RVZ26Qb5w==", + "cpu": [ + "x64" + ], + "license": "FSL-1.1-MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@sentry/cli/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sentry/core": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.37.0.tgz", + "integrity": "sha512-hkRz7S4gkKLgPf+p3XgVjVm7tAfvcEPZxeACCC6jmoeKhGkzN44nXwLiqqshJ25RMcSrhfFvJa/FlBg6zupz7g==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/react": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/react/-/react-10.37.0.tgz", + "integrity": "sha512-XLnXJOHgsCeVAVBbO+9AuGlZWnCxLQHLOmKxpIr8wjE3g7dHibtug6cv8JLx78O4dd7aoCqv2TTyyKY9FLJ2EQ==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "10.37.0", + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.14.0 || 17.x || 18.x || 19.x" + } + }, + "node_modules/@sentry/react-native": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-7.11.0.tgz", + "integrity": "sha512-OiDaLCAGpRN18YG/o7IIwLhU0Xpb0tYKQ5QxkGHiwb+L3VHn+MqGCGfITYNdhqr06HHMvu9Lysm+UJxaNmGaJg==", + "license": "MIT", + "dependencies": { + "@sentry/babel-plugin-component-annotate": "4.8.0", + "@sentry/browser": "10.37.0", + "@sentry/cli": "2.58.4", + "@sentry/core": "10.37.0", + "@sentry/react": "10.37.0", + "@sentry/types": "10.37.0" + }, + "bin": { + "sentry-expo-upload-sourcemaps": "scripts/expo-upload-sourcemaps.js" + }, + "peerDependencies": { + "expo": ">=49.0.0", + "react": ">=17.0.0", + "react-native": ">=0.65.0" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + } + } + }, + "node_modules/@sentry/types": { + "version": "10.37.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-10.37.0.tgz", + "integrity": "sha512-umpnUKRC0AAbJrADg6SlFtqN2yzf7NHciCF9lkHau+ax2PIZ/NDmoG4RQujFVflVaVoD60Ly2t+CcPnYIWMPlw==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.37.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.10", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz", @@ -4517,6 +4848,12 @@ "expo": "*" } }, + "node_modules/expo-eas-client": { + "version": "55.0.2", + "resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-55.0.2.tgz", + "integrity": "sha512-fjOgSXaZFBK2Xmzn/uw0DTF3BsYv97JEa4PYXXqVCEvNJPwJB1cV1eX6Xyq6iKGIhMPH9k62sOc+oUdt094WCw==", + "license": "MIT" + }, "node_modules/expo-file-system": { "version": "55.0.10", "resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-55.0.10.tgz", @@ -4614,12 +4951,12 @@ } }, "node_modules/expo-manifests": { - "version": "55.0.9", - "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-55.0.9.tgz", - "integrity": "sha512-i82j3X4hbxYDe6kxUw4u8WfvbvTj2w+9BD9WKuL0mFRy+MjvdzdyaqAjEViWCKo/alquP/hTApDTQBb3UmWhkg==", + "version": "55.0.11", + "resolved": "https://registry.npmjs.org/expo-manifests/-/expo-manifests-55.0.11.tgz", + "integrity": "sha512-3+pFun4C9F/eFMVpwZgOBrBWq5sfu7rS1uxTrcg9G7jUFatNe5W6hr+M7z7aQPDf0J1afaSudUZPawx1LLf15w==", "license": "MIT", "dependencies": { - "@expo/config": "~55.0.8", + "@expo/config": "~55.0.10", "expo-json-utils": "~55.0.0" }, "peerDependencies": { @@ -4847,6 +5184,12 @@ "react-native": "*" } }, + "node_modules/expo-structured-headers": { + "version": "55.0.0", + "resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-55.0.0.tgz", + "integrity": "sha512-udaNvuWb45/Sryq9FLC/blwgOChhznuqlTrUzVjC0T83pMdcmscKJX23lnNDW6hCec8p81Y3z1DIFwIyk0g/PQ==", + "license": "MIT" + }, "node_modules/expo-symbols": { "version": "55.0.5", "resolved": "https://registry.npmjs.org/expo-symbols/-/expo-symbols-55.0.5.tgz", @@ -4883,6 +5226,36 @@ } } }, + "node_modules/expo-updates": { + "version": "55.0.15", + "resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-55.0.15.tgz", + "integrity": "sha512-UE9Ik56trq//kNeJ/BlC5vOTYdNTvsHwhfWFYMazP1UOQK4lnX59/t0qz8Ut+3aPXZZT7+B6mnbWtic0QqN1wA==", + "license": "MIT", + "dependencies": { + "@expo/code-signing-certificates": "^0.0.6", + "@expo/plist": "^0.5.2", + "@expo/spawn-async": "^1.7.2", + "arg": "^4.1.0", + "chalk": "^4.1.2", + "debug": "^4.3.4", + "expo-eas-client": "~55.0.2", + "expo-manifests": "~55.0.11", + "expo-structured-headers": "~55.0.0", + "expo-updates-interface": "~55.1.3", + "getenv": "^2.0.0", + "glob": "^13.0.0", + "ignore": "^5.3.1", + "resolve-from": "^5.0.0" + }, + "bin": { + "expo-updates": "bin/cli.js" + }, + "peerDependencies": { + "expo": "*", + "react": "*", + "react-native": "*" + } + }, "node_modules/expo-updates-interface": { "version": "55.1.3", "resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-55.1.3.tgz", @@ -4892,6 +5265,12 @@ "expo": "*" } }, + "node_modules/expo-updates/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, "node_modules/expo/node_modules/@expo/cli": { "version": "55.0.15", "resolved": "https://registry.npmjs.org/@expo/cli/-/cli-55.0.15.tgz", diff --git a/package.json b/package.json index edb50e5..c884e7a 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@dr.pogodin/react-native-static-server": "^0.26.0", "@expo/vector-icons": "^15.0.2", "@react-native-async-storage/async-storage": "2.2.0", + "@sentry/react-native": "~7.11.0", "axios": "^1.13.6", "expo": "~55.0.5", "expo-av": "^16.0.8", @@ -28,6 +29,7 @@ "expo-screen-orientation": "~55.0.8", "expo-status-bar": "~55.0.4", "expo-system-ui": "~55.0.9", + "expo-updates": "~55.0.15", "pako": "^2.1.0", "react": "19.2.0", "react-dom": "19.2.0", diff --git a/shims/react-native-pager-view.web.tsx b/shims/react-native-pager-view.web.tsx new file mode 100644 index 0000000..22e990d --- /dev/null +++ b/shims/react-native-pager-view.web.tsx @@ -0,0 +1,31 @@ +/** + * Web shim for react-native-pager-view. + * eas update exports for web; this replaces the native-only module + * with a simple View-based container that renders the first child only. + */ +import React from 'react'; +import { View, type ViewStyle } from 'react-native'; + +interface PagerViewProps { + children: React.ReactNode; + style?: ViewStyle; + initialPage?: number; + scrollEnabled?: boolean; + onPageSelected?: (e: any) => void; + [key: string]: any; +} + +const PagerView = React.forwardRef( + ({ children, style, initialPage = 0 }, ref) => { + const pages = React.Children.toArray(children); + return ( + + {pages[initialPage] ?? pages[0] ?? null} + + ); + }, +); + +PagerView.displayName = 'PagerView'; + +export default PagerView;