mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
added OTA support
This commit is contained in:
parent
5ddf26af34
commit
e4bc0d3896
11 changed files with 1279 additions and 259 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -49,3 +49,5 @@ local-scrapers-repo
|
|||
worki.json
|
||||
VERSION_UPDATE_README.md
|
||||
hackintosh-emulator-fix.sh
|
||||
/ota-builds
|
||||
src/screens/xavio.md
|
||||
|
|
|
|||
13
App.tsx
13
App.tsx
|
|
@ -29,6 +29,7 @@ import { TrailerProvider } from './src/contexts/TrailerContext';
|
|||
import SplashScreen from './src/components/SplashScreen';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import * as Sentry from '@sentry/react-native';
|
||||
import UpdateService from './src/services/updateService';
|
||||
|
||||
Sentry.init({
|
||||
dsn: 'https://1a58bf436454d346e5852b7bfd3c95e8@o4509536317276160.ingest.de.sentry.io/4509536317734992',
|
||||
|
|
@ -60,20 +61,24 @@ const ThemedApp = () => {
|
|||
const [isAppReady, setIsAppReady] = useState(false);
|
||||
const [hasCompletedOnboarding, setHasCompletedOnboarding] = useState<boolean | null>(null);
|
||||
|
||||
// Check onboarding status
|
||||
// Check onboarding status and initialize update service
|
||||
useEffect(() => {
|
||||
const checkOnboardingStatus = async () => {
|
||||
const initializeApp = async () => {
|
||||
try {
|
||||
// Check onboarding status
|
||||
const onboardingCompleted = await AsyncStorage.getItem('hasCompletedOnboarding');
|
||||
setHasCompletedOnboarding(onboardingCompleted === 'true');
|
||||
|
||||
// Initialize update service
|
||||
await UpdateService.initialize();
|
||||
} catch (error) {
|
||||
console.error('Error checking onboarding status:', error);
|
||||
console.error('Error initializing app:', error);
|
||||
// Default to showing onboarding if we can't check
|
||||
setHasCompletedOnboarding(false);
|
||||
}
|
||||
};
|
||||
|
||||
checkOnboardingStatus();
|
||||
initializeApp();
|
||||
}, []);
|
||||
|
||||
// Create custom themes based on current theme
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@
|
|||
</intent>
|
||||
</queries>
|
||||
<application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="true" android:theme="@style/AppTheme" android:supportsRtl="true">
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="false"/>
|
||||
<meta-data android:name="expo.modules.updates.ENABLED" android:value="true"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_RUNTIME_VERSION" android:value="@string/expo_runtime_version"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_CHECK_ON_LAUNCH" android:value="ALWAYS"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATES_LAUNCH_WAIT_MS" android:value="0"/>
|
||||
<meta-data android:name="expo.modules.updates.EXPO_UPDATE_URL" android:value="https://grim-reyna-tapframe-69970143.koyeb.app/api/manifest"/>
|
||||
<activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|locale|layoutDirection" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true" android:screenOrientation="unspecified">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@
|
|||
<string name="expo_splash_screen_resize_mode" translatable="false">contain</string>
|
||||
<string name="expo_splash_screen_status_bar_translucent" translatable="false">false</string>
|
||||
<string name="expo_system_ui_user_interface_style" translatable="false">dark</string>
|
||||
<string name="expo_runtime_version">0.6.0-beta.8</string>
|
||||
</resources>
|
||||
17
app.json
17
app.json
|
|
@ -72,7 +72,20 @@
|
|||
"organization": "tapframe"
|
||||
}
|
||||
],
|
||||
"expo-localization"
|
||||
]
|
||||
"expo-localization",
|
||||
[
|
||||
"expo-updates",
|
||||
{
|
||||
"username": "nayifleo"
|
||||
}
|
||||
]
|
||||
],
|
||||
"updates": {
|
||||
"enabled": true,
|
||||
"checkAutomatically": "ON_LOAD",
|
||||
"fallbackToCacheTimeout": 0,
|
||||
"url": "https://grim-reyna-tapframe-69970143.koyeb.app/api/manifest"
|
||||
},
|
||||
"runtimeVersion": "0.6.0-beta.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
61
build-and-publish-app-release.sh
Normal file
61
build-and-publish-app-release.sh
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Check if the correct number of arguments are provided
|
||||
if [ "$#" -ne 2 ]; then
|
||||
echo "Usage: $0 <runtimeVersion> <xavia-ota-url>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the current commit hash and message
|
||||
commitHash=$(git rev-parse HEAD)
|
||||
commitMessage=$(git log -1 --pretty=%B)
|
||||
|
||||
# Assign arguments to variables
|
||||
runtimeVersion=$1
|
||||
serverHost=$2
|
||||
|
||||
# Generate a timestamp for the output folder
|
||||
timestamp=$(date -u +%Y%m%d%H%M%S)
|
||||
outputFolder="ota-builds/$timestamp"
|
||||
|
||||
# Ask the user to confirm the hash, commit message, runtime version, and output folder
|
||||
echo "Output Folder: $outputFolder"
|
||||
echo "Runtime Version: $runtimeVersion"
|
||||
echo "Commit Hash: $commitHash"
|
||||
echo "Commit Message: $commitMessage"
|
||||
|
||||
read -p "Do you want to proceed with these values? (y/n): " confirm
|
||||
|
||||
if [ "$confirm" != "y" ]; then
|
||||
echo "Operation cancelled by the user."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf $outputFolder
|
||||
mkdir -p $outputFolder
|
||||
|
||||
# Run expo export with the specified output folder
|
||||
npx expo export --output-dir $outputFolder
|
||||
|
||||
# Extract expo config property from app.json and save to expoconfig.json
|
||||
jq '.expo' app.json > $outputFolder/expoconfig.json
|
||||
|
||||
|
||||
# Zip the output folder
|
||||
cd $outputFolder
|
||||
zip -q -r ${timestamp}.zip .
|
||||
|
||||
|
||||
# Upload the zip file to the server
|
||||
curl -X POST $serverHost/api/upload -F "file=@${timestamp}.zip" -F "runtimeVersion=$runtimeVersion" -F "commitHash=$commitHash" -F "commitMessage=$commitMessage"
|
||||
|
||||
echo ""
|
||||
|
||||
echo "Uploaded to $serverHost/api/upload"
|
||||
cd ..
|
||||
|
||||
# Remove the output folder and zip file
|
||||
rm -rf $outputFolder
|
||||
|
||||
echo "Removed $outputFolder"
|
||||
echo "Done"
|
||||
535
package-lock.json
generated
535
package-lock.json
generated
|
|
@ -1,27 +1,28 @@
|
|||
{
|
||||
"name": "nuvio",
|
||||
"version": "1.0.0",
|
||||
"version": "0.6.0-beta.6",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "nuvio",
|
||||
"version": "1.0.0",
|
||||
"version": "0.6.0-beta.6",
|
||||
"dependencies": {
|
||||
"@backpackapp-io/react-native-toast": "^0.14.0",
|
||||
"@expo/metro-runtime": "~4.0.1",
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
"@expo/vector-icons": "~14.0.4",
|
||||
"@lottiefiles/dotlottie-react": "^0.6.5",
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
"@react-native-community/netinfo": "^11.4.1",
|
||||
"@react-native-community/slider": "^4.5.6",
|
||||
"@react-native-picker/picker": "^2.11.0",
|
||||
"@react-native-community/slider": "4.5.5",
|
||||
"@react-native-picker/picker": "2.9.0",
|
||||
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||
"@react-navigation/native": "^7.1.6",
|
||||
"@react-navigation/native-stack": "^7.3.10",
|
||||
"@react-navigation/stack": "^7.2.10",
|
||||
"@sentry/react-native": "^6.15.1",
|
||||
"@shopify/flash-list": "^2.0.2",
|
||||
"@sentry/react-native": "~6.10.0",
|
||||
"@shopify/flash-list": "1.7.3",
|
||||
"@supabase/supabase-js": "^2.54.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/react-native-video": "^5.0.20",
|
||||
|
|
@ -30,7 +31,7 @@
|
|||
"cheerio-without-node-native": "^0.20.2",
|
||||
"date-fns": "^4.1.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"expo": "~52.0.43",
|
||||
"expo": "~52.0.47",
|
||||
"expo-application": "~6.0.2",
|
||||
"expo-auth-session": "^6.0.3",
|
||||
"expo-blur": "^14.0.3",
|
||||
|
|
@ -47,9 +48,10 @@
|
|||
"expo-screen-orientation": "~8.0.4",
|
||||
"expo-status-bar": "~2.0.1",
|
||||
"expo-system-ui": "^4.0.9",
|
||||
"expo-updates": "~0.27.4",
|
||||
"expo-web-browser": "~14.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lottie-react-native": "^7.3.1",
|
||||
"lottie-react-native": "7.1.0",
|
||||
"posthog-react-native": "^4.4.0",
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.76.9",
|
||||
|
|
@ -58,10 +60,10 @@
|
|||
"react-native-image-colors": "^2.5.0",
|
||||
"react-native-immersive-mode": "^2.0.2",
|
||||
"react-native-paper": "^5.13.1",
|
||||
"react-native-reanimated": "^3.18.0",
|
||||
"react-native-reanimated": "~3.16.1",
|
||||
"react-native-safe-area-context": "4.12.0",
|
||||
"react-native-screens": "~4.4.0",
|
||||
"react-native-svg": "^15.11.2",
|
||||
"react-native-svg": "15.8.0",
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-video": "^6.12.0",
|
||||
"react-native-vlc-media-player": "^1.0.87",
|
||||
|
|
@ -77,9 +79,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@0no-co/graphql.web": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.1.2.tgz",
|
||||
"integrity": "sha512-N2NGsU5FLBhT8NZ+3l2YrzZSHITjNXNuDhC4iDiikv0IujaJ0Xc6xIxQZ/Ek3Cb+rgPjnLHYyJm11tInuJn+cw==",
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@0no-co/graphql.web/-/graphql.web-1.2.0.tgz",
|
||||
"integrity": "sha512-/1iHy9TTr63gE1YcR5idjx8UREz1s0kFhydf3bBLCXyqjhkIc6igAzTOx3zPifCwFR87tsh/4Pa9cNts6d2otw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"graphql": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||
|
|
@ -2340,9 +2342,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/cli": {
|
||||
"version": "0.22.24",
|
||||
"resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.24.tgz",
|
||||
"integrity": "sha512-lhdenxBC8/x/vL39j79eXE09mOaqNNLmiSDdY/PblnI+UNzGgsQ48hBTYa/MQhd0ioXXVKurZL2941dLKwcxJw==",
|
||||
"version": "0.22.26",
|
||||
"resolved": "https://registry.npmjs.org/@expo/cli/-/cli-0.22.26.tgz",
|
||||
"integrity": "sha512-I689wc8Fn/AX7aUGiwrh3HnssiORMJtR2fpksX+JIe8Cj/EDleblYMSwRPd0025wrwOV9UN1KM/RuEt/QjCS3Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@0no-co/graphql.web": "^1.0.8",
|
||||
|
|
@ -2358,7 +2360,7 @@
|
|||
"@expo/osascript": "^2.1.6",
|
||||
"@expo/package-manager": "^1.7.2",
|
||||
"@expo/plist": "^0.2.2",
|
||||
"@expo/prebuild-config": "^8.0.31",
|
||||
"@expo/prebuild-config": "~8.2.0",
|
||||
"@expo/rudder-sdk-node": "^1.1.1",
|
||||
"@expo/spawn-async": "^1.7.2",
|
||||
"@expo/ws-tunnel": "^1.0.1",
|
||||
|
|
@ -2423,9 +2425,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/cli/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
|
|
@ -2729,9 +2731,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/metro-config/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
|
|
@ -2759,9 +2761,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/osascript": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.1.6.tgz",
|
||||
"integrity": "sha512-SbMp4BUwDAKiFF4zZEJf32rRYMeNnLK9u4FaPo0lQRer60F+SKd20NTSys0wgssiVeQyQz2OhGLRx3cxYowAGw==",
|
||||
"version": "2.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@expo/osascript/-/osascript-2.2.5.tgz",
|
||||
"integrity": "sha512-Bpp/n5rZ0UmpBOnl7Li3LtM7la0AR3H9NNesqL+ytW5UiqV/TbonYW3rDZY38u4u/lG7TnYflVIVQPD+iqZJ5w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/spawn-async": "^1.7.2",
|
||||
|
|
@ -2772,23 +2774,36 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/package-manager": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.7.2.tgz",
|
||||
"integrity": "sha512-wT/qh9ebNjl6xr00bYkSh93b6E/78J3JPlT6WzGbxbsnv5FIZKB/nr522oWqVe1E+ML7BpXs8WugErWDN9kOFg==",
|
||||
"version": "1.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@expo/package-manager/-/package-manager-1.8.6.tgz",
|
||||
"integrity": "sha512-gcdICLuL+nHKZagPIDC5tX8UoDDB8vNA5/+SaQEqz8D+T2C4KrEJc2Vi1gPAlDnKif834QS6YluHWyxjk0yZlQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/json-file": "^9.0.2",
|
||||
"@expo/json-file": "^9.1.5",
|
||||
"@expo/spawn-async": "^1.7.2",
|
||||
"ansi-regex": "^5.0.0",
|
||||
"chalk": "^4.0.0",
|
||||
"find-up": "^5.0.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"micromatch": "^4.0.8",
|
||||
"npm-package-arg": "^11.0.0",
|
||||
"ora": "^3.4.0",
|
||||
"resolve-workspace-root": "^2.0.0",
|
||||
"split": "^1.0.1",
|
||||
"sudo-prompt": "9.1.1"
|
||||
"resolve-workspace-root": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/package-manager/node_modules/@babel/code-frame": {
|
||||
"version": "7.10.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz",
|
||||
"integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/highlight": "^7.10.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/package-manager/node_modules/@expo/json-file": {
|
||||
"version": "9.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@expo/json-file/-/json-file-9.1.5.tgz",
|
||||
"integrity": "sha512-prWBhLUlmcQtvN6Y7BpW2k9zXGd3ySa3R6rAguMJkp1z22nunLN64KYTUWfijFlprFoxm9r2VNnGkcbndAlgKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "~7.10.4",
|
||||
"json5": "^2.2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/plist": {
|
||||
|
|
@ -2803,9 +2818,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/prebuild-config": {
|
||||
"version": "8.0.31",
|
||||
"resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.0.31.tgz",
|
||||
"integrity": "sha512-YTuS5ic9KolD/WA3GqgLcZytHQU1dpitlZ/cbDq8ZqkY+1ae5YWX+GkYEZf2VyECPaWnHYuDGddaTQVw5miTRg==",
|
||||
"version": "8.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@expo/prebuild-config/-/prebuild-config-8.2.0.tgz",
|
||||
"integrity": "sha512-CxiPpd980s0jyxi7eyN3i/7YKu3XL+8qPjBZUCYtc0+axpGweqIkq2CslyLSKHyqVyH/zlPkbVgWdyiYavFS5Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/config": "~10.0.11",
|
||||
|
|
@ -2837,9 +2852,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/prebuild-config/node_modules/jsonfile": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
|
||||
"integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz",
|
||||
"integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^2.0.0"
|
||||
|
|
@ -2849,9 +2864,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@expo/prebuild-config/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
|
|
@ -2912,14 +2927,12 @@
|
|||
"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==",
|
||||
"version": "14.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@expo/vector-icons/-/vector-icons-14.0.4.tgz",
|
||||
"integrity": "sha512-+yKshcbpDfbV4zoXOgHxCwh7lkE9VVTT5T03OUlBsqfze1PLy6Hi4jp1vSb1GVbY6eskvMIivGVc9SKzIv0oEQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo-font": "*",
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
"dependencies": {
|
||||
"prop-types": "^15.8.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@expo/ws-tunnel": {
|
||||
|
|
@ -3414,6 +3427,26 @@
|
|||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@lottiefiles/dotlottie-react": {
|
||||
"version": "0.6.5",
|
||||
"resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-react/-/dotlottie-react-0.6.5.tgz",
|
||||
"integrity": "sha512-4jbye+HKHaiKwai4+bcAwJfMwW0L55cAGIN0ZKCz+EqXs1R3YhB08VYeRu2LwDUybThgFQnl/XkB4loCfA7t2A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lottiefiles/dotlottie-web": "0.25.0",
|
||||
"debounce": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lottiefiles/dotlottie-web": {
|
||||
"version": "0.25.0",
|
||||
"resolved": "https://registry.npmjs.org/@lottiefiles/dotlottie-web/-/dotlottie-web-0.25.0.tgz",
|
||||
"integrity": "sha512-k+4tTckmy7y319qY4AlZiLm4dP95KLXfZd1l1jbss0qX/eyV4KKT+4iLuBfhoFSljfXmM15Oma+e8d663CHPyA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@nodelib/fs.scandir": {
|
||||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
|
|
@ -3462,9 +3495,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@npmcli/fs/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
|
|
@ -3521,9 +3554,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-native-community/slider": {
|
||||
"version": "4.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.5.6.tgz",
|
||||
"integrity": "sha512-UhLPFeqx0YfPLrEz8ffT3uqAyXWu6iqFjohNsbp4cOU7hnJwg2RXtDnYHoHMr7MOkZDVdlLMdrSrAuzY6KGqrg==",
|
||||
"version": "4.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-community/slider/-/slider-4.5.5.tgz",
|
||||
"integrity": "sha512-x2N415pg4ZxIltArOKczPwn7JEYh+1OxQ4+hTnafomnMsqs65HZuEWcX+Ch8c5r8V83DiunuQUf5hWGWlw8hQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@react-native-masked-view/masked-view": {
|
||||
|
|
@ -3538,13 +3571,10 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@react-native-picker/picker": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.11.0.tgz",
|
||||
"integrity": "sha512-QuZU6gbxmOID5zZgd/H90NgBnbJ3VV6qVzp6c7/dDrmWdX8S0X5YFYgDcQFjE3dRen9wB9FWnj2VVdPU64adSg==",
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@react-native-picker/picker/-/picker-2.9.0.tgz",
|
||||
"integrity": "sha512-khEhIW/uhfMqq/+tvg4rEAiPGT8GX+Y6QydlP2TSMSmRHoSJK+ShXvXZXSr4Sii4imkj4BwvLunGywwtQDODqg==",
|
||||
"license": "MIT",
|
||||
"workspaces": [
|
||||
"example"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
|
|
@ -4156,9 +4186,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sentry/babel-plugin-component-annotate": {
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.5.0.tgz",
|
||||
"integrity": "sha512-s2go8w03CDHbF9luFGtBHKJp4cSpsQzNVqgIa9Pfa4wnjipvrK6CxVT4icpLA3YO6kg5u622Yoa5GF3cJdippw==",
|
||||
"version": "3.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-3.2.2.tgz",
|
||||
"integrity": "sha512-D+SKQ266ra/wo87s9+UI/rKQi3qhGPCR8eSCDe0VJudhjHsqyNU+JJ5lnIGCgmZaWFTXgdBP/gdr1Iz1zqGs4Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
|
|
@ -4181,9 +4211,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sentry/cli": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.46.0.tgz",
|
||||
"integrity": "sha512-nqoPl7UCr446QFkylrsRrUXF51x8Z9dGquyf4jaQU+OzbOJMqclnYEvU6iwbwvaw3tu/2DnoZE/Og+Nq1h63sA==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.42.4.tgz",
|
||||
"integrity": "sha512-BoSZDAWJiz/40tu6LuMDkSgwk4xTsq6zwqYoUqLU3vKBR/VsaaQGvu6EWxZXORthfZU2/5Agz0+t220cge6VQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
|
|
@ -4200,20 +4230,19 @@
|
|||
"node": ">= 10"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@sentry/cli-darwin": "2.46.0",
|
||||
"@sentry/cli-linux-arm": "2.46.0",
|
||||
"@sentry/cli-linux-arm64": "2.46.0",
|
||||
"@sentry/cli-linux-i686": "2.46.0",
|
||||
"@sentry/cli-linux-x64": "2.46.0",
|
||||
"@sentry/cli-win32-arm64": "2.46.0",
|
||||
"@sentry/cli-win32-i686": "2.46.0",
|
||||
"@sentry/cli-win32-x64": "2.46.0"
|
||||
"@sentry/cli-darwin": "2.42.4",
|
||||
"@sentry/cli-linux-arm": "2.42.4",
|
||||
"@sentry/cli-linux-arm64": "2.42.4",
|
||||
"@sentry/cli-linux-i686": "2.42.4",
|
||||
"@sentry/cli-linux-x64": "2.42.4",
|
||||
"@sentry/cli-win32-i686": "2.42.4",
|
||||
"@sentry/cli-win32-x64": "2.42.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-darwin": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.46.0.tgz",
|
||||
"integrity": "sha512-5Ll+e5KAdIk9OYiZO8aifMBRNWmNyPjSqdjaHlBC1Qfh7pE3b1zyzoHlsUazG0bv0sNrSGea8e7kF5wIO1hvyg==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.42.4.tgz",
|
||||
"integrity": "sha512-PZV4Y97VDWBR4rIt0HkJfXaBXlebIN2s/FDzC3iHINZE5OG62CDFsnC4/lbGlf2/UZLDaGGIK7mYwSHhTvN+HQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
|
@ -4224,9 +4253,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-arm": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.46.0.tgz",
|
||||
"integrity": "sha512-WRrLNq/TEX/TNJkGqq6Ad0tGyapd5dwlxtsPbVBrIdryuL1mA7VCBoaHBr3kcwJLsgBHFH0lmkMee2ubNZZdkg==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.42.4.tgz",
|
||||
"integrity": "sha512-lBn0oeeg62h68/4Eo6zbPq99Idz5t0VRV48rEU/WKeM4MtQCvG/iGGQ3lBFW2yNiUBzXZIK9poXLEcgbwmcRVw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
|
|
@ -4234,17 +4263,16 @@
|
|||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd",
|
||||
"android"
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-arm64": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.46.0.tgz",
|
||||
"integrity": "sha512-OEJN8yAjI9y5B4telyqzu27Hi3+S4T8VxZCqJz1+z2Mp0Q/MZ622AahVPpcrVq/5bxrnlZR16+lKh8L1QwNFPg==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.42.4.tgz",
|
||||
"integrity": "sha512-Ex8vRnryyzC/9e43daEmEqPS+9uirY/l6Hw2lAvhBblFaL7PTWNx52H+8GnYGd9Zy2H3rWNyBDYfHwnErg38zA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
|
|
@ -4252,17 +4280,16 @@
|
|||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd",
|
||||
"android"
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-i686": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.46.0.tgz",
|
||||
"integrity": "sha512-xko3/BVa4LX8EmRxVOCipV+PwfcK5Xs8lP6lgF+7NeuAHMNL4DqF6iV9rrN8gkGUHCUI9RXSve37uuZnFy55+Q==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.42.4.tgz",
|
||||
"integrity": "sha512-IBJg0aHjsLCL4LvcFa3cXIjA+4t5kPqBT9y+PoDu4goIFxYD8zl7mbUdGJutvJafTk8Akf4ss4JJXQBjg019zA==",
|
||||
"cpu": [
|
||||
"x86",
|
||||
"ia32"
|
||||
|
|
@ -4271,17 +4298,16 @@
|
|||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd",
|
||||
"android"
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-linux-x64": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.46.0.tgz",
|
||||
"integrity": "sha512-hJ1g5UEboYcOuRia96LxjJ0jhnmk8EWLDvlGnXLnYHkwy3ree/L7sNgdp/QsY8Z4j2PGO5f22Va+UDhSjhzlfQ==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.42.4.tgz",
|
||||
"integrity": "sha512-gXI5OEiOSNiAEz7VCE6AZcAgHJ47mlgal3+NmbE8XcHmFOnyDws9FNie6PJAy8KZjXi3nqoBP9JVAbnmOix3uA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4289,33 +4315,16 @@
|
|||
"optional": true,
|
||||
"os": [
|
||||
"linux",
|
||||
"freebsd",
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-win32-arm64": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.46.0.tgz",
|
||||
"integrity": "sha512-mN7cpPoCv2VExFRGHt+IoK11yx4pM4ADZQGEso5BAUZ5duViXB2WrAXCLd8DrwMnP0OE978a7N8OtzsFqjkbNA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-win32-i686": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.46.0.tgz",
|
||||
"integrity": "sha512-6F73AUE3lm71BISUO19OmlnkFD5WVe4/wA1YivtLZTc1RU3eUYJLYxhDfaH3P77+ycDppQ2yCgemLRaA4A8mNQ==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.42.4.tgz",
|
||||
"integrity": "sha512-vZuR3UPHKqOMniyrijrrsNwn9usaRysXq78F6WV0cL0ZyPLAmY+KBnTDSFk1Oig2pURnzaTm+RtcZu2fc8mlzg==",
|
||||
"cpu": [
|
||||
"x86",
|
||||
"ia32"
|
||||
|
|
@ -4330,9 +4339,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sentry/cli-win32-x64": {
|
||||
"version": "2.46.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.46.0.tgz",
|
||||
"integrity": "sha512-yuGVcfepnNL84LGA0GjHzdMIcOzMe0bjPhq/rwPsPN+zu11N+nPR2wV2Bum4U0eQdqYH3iAlMdL5/BEQfuLJww==",
|
||||
"version": "2.42.4",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.42.4.tgz",
|
||||
"integrity": "sha512-OIBj3uaQ6nAERSm5Dcf8UIhyElEEwMNsZEEppQpN4IKl0mrwb/57AznM23Dvpu6GR8WGbVQUSolt879YZR5E9g==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
|
@ -4345,31 +4354,6 @@
|
|||
"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": "8.54.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-8.54.0.tgz",
|
||||
|
|
@ -4397,14 +4381,14 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@sentry/react-native": {
|
||||
"version": "6.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-6.15.1.tgz",
|
||||
"integrity": "sha512-uNYjkhi7LUeXe+a3ui3N+sUZ4PbBh/P3Q6Pz5esOQOAEV1N7hxkdnHVic1cVHsirEQvy9rUJPBnja47Va7OpQA==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/react-native/-/react-native-6.10.0.tgz",
|
||||
"integrity": "sha512-B56vc+pnFHMiu3cabFb454v4qD0zObW6JVzJ5Gb6fIMdt93AFIJg10ZErzC+ump7xM4BOEROFFRuLiyvadvlPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/babel-plugin-component-annotate": "3.5.0",
|
||||
"@sentry/babel-plugin-component-annotate": "3.2.2",
|
||||
"@sentry/browser": "8.54.0",
|
||||
"@sentry/cli": "2.46.0",
|
||||
"@sentry/cli": "2.42.4",
|
||||
"@sentry/core": "8.54.0",
|
||||
"@sentry/react": "8.54.0",
|
||||
"@sentry/types": "8.54.0",
|
||||
|
|
@ -4449,11 +4433,12 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@shopify/flash-list": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-2.0.2.tgz",
|
||||
"integrity": "sha512-zhlrhA9eiuEzja4wxVvotgXHtqd3qsYbXkQ3rsBfOgbFA9BVeErpDE/yEwtlIviRGEqpuFj/oU5owD6ByaNX+w==",
|
||||
"version": "1.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@shopify/flash-list/-/flash-list-1.7.3.tgz",
|
||||
"integrity": "sha512-RLhNptm02aqpqZvjj9pJPcU+EVYxOAJhPRCmDOaUbUP86+636w+plsbjpBPSYGvPZhPj56RtZ9FBlvolPeEmYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"recyclerlistview": "4.2.1",
|
||||
"tslib": "2.8.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -5214,22 +5199,22 @@
|
|||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@urql/core": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@urql/core/-/core-5.1.1.tgz",
|
||||
"integrity": "sha512-aGh024z5v2oINGD/In6rAtVKTm4VmQ2TxKQBAtk2ZSME5dunZFcjltw4p5ENQg+5CBhZ3FHMzl0Oa+rwqiWqlg==",
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@urql/core/-/core-5.2.0.tgz",
|
||||
"integrity": "sha512-/n0ieD0mvvDnVAXEQgX/7qJiVcvYvNkOHeBvkwtylfjydar123caCXcl58PXFY11oU1oquJocVXHxLAbtv4x1A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@0no-co/graphql.web": "^1.0.5",
|
||||
"@0no-co/graphql.web": "^1.0.13",
|
||||
"wonka": "^6.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@urql/exchange-retry": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-1.3.1.tgz",
|
||||
"integrity": "sha512-EEmtFu8JTuwsInqMakhLq+U3qN8ZMd5V3pX44q0EqD2imqTDsa8ikZqJ1schVrN8HljOdN+C08cwZ1/r5uIgLw==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@urql/exchange-retry/-/exchange-retry-1.3.2.tgz",
|
||||
"integrity": "sha512-TQMCz2pFJMfpNxmSfX1VSfTjwUIFx/mL+p1bnfM1xjjdla7Z+KnGMW/EhFbpckp3LyWAH4PgOsMwOMnIN+MBFg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@urql/core": "^5.1.1",
|
||||
"@urql/core": "^5.1.2",
|
||||
"wonka": "^6.3.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
@ -6769,16 +6754,16 @@
|
|||
}
|
||||
},
|
||||
"node_modules/compression": {
|
||||
"version": "1.8.0",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.0.tgz",
|
||||
"integrity": "sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==",
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
|
||||
"integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.2",
|
||||
"compressible": "~2.0.18",
|
||||
"debug": "2.6.9",
|
||||
"negotiator": "~0.6.4",
|
||||
"on-headers": "~1.0.2",
|
||||
"on-headers": "~1.1.0",
|
||||
"safe-buffer": "5.2.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
|
|
@ -7070,6 +7055,18 @@
|
|||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/debounce": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/debounce/-/debounce-2.2.0.tgz",
|
||||
"integrity": "sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||
|
|
@ -7422,9 +7419,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
|
|
@ -7705,18 +7702,18 @@
|
|||
"integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw=="
|
||||
},
|
||||
"node_modules/expo": {
|
||||
"version": "52.0.44",
|
||||
"resolved": "https://registry.npmjs.org/expo/-/expo-52.0.44.tgz",
|
||||
"integrity": "sha512-qj3+MWxmqLyBaYQ8jDOvVLEgSqNplH3cf+nDhxCo4C1cpTPD1u/HGh1foibtaeuCYLHsE5km1lrcOpRbFJ4luQ==",
|
||||
"version": "52.0.47",
|
||||
"resolved": "https://registry.npmjs.org/expo/-/expo-52.0.47.tgz",
|
||||
"integrity": "sha512-Mkvl7Qi2k+V3FdNRUD+yDj8GqU4IiYulLfl36BmSZs8lh/kCYPhTiyBLiEGPfz7d25QKbPWG727ESozbkbvatw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.0",
|
||||
"@expo/cli": "0.22.24",
|
||||
"@expo/cli": "0.22.26",
|
||||
"@expo/config": "~10.0.11",
|
||||
"@expo/config-plugins": "~9.0.17",
|
||||
"@expo/fingerprint": "0.11.11",
|
||||
"@expo/metro-config": "0.19.12",
|
||||
"@expo/vector-icons": "^14.0.0",
|
||||
"@expo/vector-icons": "~14.0.4",
|
||||
"babel-preset-expo": "~12.0.11",
|
||||
"expo-asset": "~11.0.5",
|
||||
"expo-constants": "~17.0.8",
|
||||
|
|
@ -7924,6 +7921,12 @@
|
|||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-eas-client": {
|
||||
"version": "0.13.3",
|
||||
"resolved": "https://registry.npmjs.org/expo-eas-client/-/expo-eas-client-0.13.3.tgz",
|
||||
"integrity": "sha512-t+1F1tiDocSot8iSnrn/CjTUMvVvPV2DpafSVcticpbSzMGybEN7wcamO1t18fK7WxGXpZE9gxtd80qwv/LLqQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/expo-file-system": {
|
||||
"version": "18.0.12",
|
||||
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-18.0.12.tgz",
|
||||
|
|
@ -8169,6 +8172,12 @@
|
|||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-structured-headers": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-structured-headers/-/expo-structured-headers-4.0.0.tgz",
|
||||
"integrity": "sha512-uPiwZjWq3AdFGgY52+I2nGPrNa6izxAglymPXHUZLekZW290GqIUOk7MBNDD4sg4JwUbSi3gdxEurpEvuq+FSg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/expo-system-ui": {
|
||||
"version": "4.0.9",
|
||||
"resolved": "https://registry.npmjs.org/expo-system-ui/-/expo-system-ui-4.0.9.tgz",
|
||||
|
|
@ -8195,6 +8204,35 @@
|
|||
"integrity": "sha512-FRjRvs7RgsXjkbGSOjYSxhX5V70c0IzA/jy3HXeYpATMwD9fOR1DbveLW497QGsVdCa0vThbJUtR8rIzAfpHQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/expo-updates": {
|
||||
"version": "0.27.4",
|
||||
"resolved": "https://registry.npmjs.org/expo-updates/-/expo-updates-0.27.4.tgz",
|
||||
"integrity": "sha512-0rg4L2fFPEjTR/qnZ9Te4Q4irVC8uvNcTZW1pWnWbadG1SLv2PKjS1MYX5BboKzC3ao0H7m++5TP3hWhNg9org==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@expo/code-signing-certificates": "0.0.5",
|
||||
"@expo/config": "~10.0.11",
|
||||
"@expo/config-plugins": "~9.0.17",
|
||||
"@expo/spawn-async": "^1.7.2",
|
||||
"arg": "4.1.0",
|
||||
"chalk": "^4.1.2",
|
||||
"expo-eas-client": "~0.13.3",
|
||||
"expo-manifests": "~0.15.7",
|
||||
"expo-structured-headers": "~4.0.0",
|
||||
"expo-updates-interface": "~1.0.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fbemitter": "^3.0.0",
|
||||
"ignore": "^5.3.1",
|
||||
"resolve-from": "^5.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"expo-updates": "bin/cli.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"expo": "*",
|
||||
"react": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-updates-interface": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/expo-updates-interface/-/expo-updates-interface-1.0.0.tgz",
|
||||
|
|
@ -8204,6 +8242,12 @@
|
|||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-updates/node_modules/arg": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz",
|
||||
"integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/expo-web-browser": {
|
||||
"version": "14.0.2",
|
||||
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-14.0.2.tgz",
|
||||
|
|
@ -8524,14 +8568,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.3.tgz",
|
||||
"integrity": "sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==",
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.4.tgz",
|
||||
"integrity": "sha512-f0cRzm6dkyVYV3nPoooP8XlccPQukegwhAnpoLcXy+X+A8KfpGOoXwDr9FLZd3wzgLaBGQBE3lY93Zm/i1JvIQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.35"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -9094,6 +9139,31 @@
|
|||
"npm": ">=1.3.7"
|
||||
}
|
||||
},
|
||||
"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/https-proxy-agent/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/human-signals": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
|
||||
|
|
@ -10497,9 +10567,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lottie-react-native": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-7.3.1.tgz",
|
||||
"integrity": "sha512-VW0gtiP1i3Jv6+PaVaNg6QDIqAXwAqmxVp1UOJFqsB6FeBN0zc8M/XR8DE8YiayZzd149nlqGOgmwoV7FbRGDw==",
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lottie-react-native/-/lottie-react-native-7.1.0.tgz",
|
||||
"integrity": "sha512-73jtQySxRZ8KTTSKf6CtcpCt8tpOCw4NRiCST4HTYgXlycxIihIp89jRcK8rS/QiBKl5bzyixMzpVmd4mYVH5Q==",
|
||||
"license": "Apache-2.0",
|
||||
"peerDependencies": {
|
||||
"@lottiefiles/dotlottie-react": "^0.6.5",
|
||||
|
|
@ -11406,9 +11476,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/npm-package-arg/node_modules/semver": {
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
|
|
@ -11558,9 +11628,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/on-headers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
|
||||
"integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
|
||||
"integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
|
|
@ -12357,9 +12427,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
|
||||
"integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
|
|
@ -12502,7 +12572,6 @@
|
|||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0",
|
||||
|
|
@ -12517,7 +12586,6 @@
|
|||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
||||
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"loose-envify": "^1.1.0"
|
||||
|
|
@ -12659,16 +12727,6 @@
|
|||
"react-native": ">=0.60.5"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-is-edge-to-edge": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.1.7.tgz",
|
||||
"integrity": "sha512-EH6i7E8epJGIcu7KpfXYXiV2JFIYITtq+rVS8uEb+92naMRBdxhTuS8Wn2Q7j9sqyO0B+Xbaaf9VdipIAmGW4w==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-paper": {
|
||||
"version": "5.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-native-paper/-/react-native-paper-5.13.1.tgz",
|
||||
|
|
@ -12721,9 +12779,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-reanimated": {
|
||||
"version": "3.18.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.18.0.tgz",
|
||||
"integrity": "sha512-eVcNcqeOkMW+BUWAHdtvN3FKgC8J8wiEJkX6bNGGQaLS7m7e4amTfjIcqf/Ta+lerZLurmDaQ0lICI1CKPrb1Q==",
|
||||
"version": "3.16.7",
|
||||
"resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-3.16.7.tgz",
|
||||
"integrity": "sha512-qoUUQOwE1pHlmQ9cXTJ2MX9FQ9eHllopCLiWOkDkp6CER95ZWeXhJCP4cSm6AD4jigL5jHcZf/SkWrg8ttZUsw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-arrow-functions": "^7.0.0-0",
|
||||
|
|
@ -12736,8 +12794,7 @@
|
|||
"@babel/plugin-transform-unicode-regex": "^7.0.0-0",
|
||||
"@babel/preset-typescript": "^7.16.7",
|
||||
"convert-source-map": "^2.0.0",
|
||||
"invariant": "^2.2.4",
|
||||
"react-native-is-edge-to-edge": "1.1.7"
|
||||
"invariant": "^2.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0",
|
||||
|
|
@ -12779,9 +12836,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/react-native-svg": {
|
||||
"version": "15.11.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.11.2.tgz",
|
||||
"integrity": "sha512-+YfF72IbWQUKzCIydlijV1fLuBsQNGMT6Da2kFlo1sh+LE3BIm/2Q7AR1zAAR6L0BFLi1WaQPLfFUC9bNZpOmw==",
|
||||
"version": "15.8.0",
|
||||
"resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.8.0.tgz",
|
||||
"integrity": "sha512-KHJzKpgOjwj1qeZzsBjxNdoIgv2zNCO9fVcoq2TEhTRsVV5DGTZ9JzUZwybd7q4giT/H3RdtqC3u44dWdO0Ffw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"css-select": "^5.1.0",
|
||||
|
|
@ -13266,6 +13323,21 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/recyclerlistview": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/recyclerlistview/-/recyclerlistview-4.2.1.tgz",
|
||||
"integrity": "sha512-NtVYjofwgUCt1rEsTp6jHQg/47TWjnO92TU2kTVgJ9wsc/ely4HnizHHa+f/dI7qaw4+zcSogElrLjhMltN2/g==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"lodash.debounce": "4.0.8",
|
||||
"prop-types": "15.8.1",
|
||||
"ts-object-utils": "0.0.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">= 15.2.1",
|
||||
"react-native": ">= 0.30.0"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerate": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
|
||||
|
|
@ -14062,18 +14134,6 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/split": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
|
||||
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"through": "2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/split-on-first": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
|
||||
|
|
@ -14394,13 +14454,6 @@
|
|||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/sudo-prompt": {
|
||||
"version": "9.1.1",
|
||||
"resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.1.1.tgz",
|
||||
"integrity": "sha512-es33J1g2HjMpyAhz8lOR+ICmXXAqTuKbuXuUWLhOLew20oN9oUCgCJx615U/v7aioZg7IX5lIh9x34vwneu4pA==",
|
||||
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
|
|
@ -14767,12 +14820,6 @@
|
|||
"integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/through": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
|
||||
"integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/timm": {
|
||||
"version": "1.7.1",
|
||||
"resolved": "https://registry.npmjs.org/timm/-/timm-1.7.1.tgz",
|
||||
|
|
@ -14874,6 +14921,12 @@
|
|||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/ts-object-utils": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ts-object-utils/-/ts-object-utils-0.0.5.tgz",
|
||||
"integrity": "sha512-iV0GvHqOmilbIKJsfyfJY9/dNHCs969z3so90dQWsO1eMMozvTpnB1MEaUbb3FYtZTGjv5sIy/xmslEz0Rg2TA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
|
|
@ -14972,9 +15025,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.21.2",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.2.tgz",
|
||||
"integrity": "sha512-uROZWze0R0itiAKVPsYhFov9LxrPMHLMEQFszeI2gCN6bnIIZ8twzBCJcN2LJrBBLfrP0t1FW0g+JmKVl8Vk1g==",
|
||||
"version": "6.21.3",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.21.3.tgz",
|
||||
"integrity": "sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
|
|
|
|||
20
package.json
20
package.json
|
|
@ -11,18 +11,19 @@
|
|||
"dependencies": {
|
||||
"@backpackapp-io/react-native-toast": "^0.14.0",
|
||||
"@expo/metro-runtime": "~4.0.1",
|
||||
"@expo/vector-icons": "^14.1.0",
|
||||
"@expo/vector-icons": "~14.0.4",
|
||||
"@lottiefiles/dotlottie-react": "^0.6.5",
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
"@react-native-community/netinfo": "^11.4.1",
|
||||
"@react-native-community/slider": "^4.5.6",
|
||||
"@react-native-picker/picker": "^2.11.0",
|
||||
"@react-native-community/slider": "4.5.5",
|
||||
"@react-native-picker/picker": "2.9.0",
|
||||
"@react-navigation/bottom-tabs": "^7.3.10",
|
||||
"@react-navigation/native": "^7.1.6",
|
||||
"@react-navigation/native-stack": "^7.3.10",
|
||||
"@react-navigation/stack": "^7.2.10",
|
||||
"@sentry/react-native": "^6.15.1",
|
||||
"@shopify/flash-list": "^2.0.2",
|
||||
"@sentry/react-native": "~6.10.0",
|
||||
"@shopify/flash-list": "1.7.3",
|
||||
"@supabase/supabase-js": "^2.54.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/react-native-video": "^5.0.20",
|
||||
|
|
@ -31,7 +32,7 @@
|
|||
"cheerio-without-node-native": "^0.20.2",
|
||||
"date-fns": "^4.1.0",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"expo": "~52.0.43",
|
||||
"expo": "~52.0.47",
|
||||
"expo-application": "~6.0.2",
|
||||
"expo-auth-session": "^6.0.3",
|
||||
"expo-blur": "^14.0.3",
|
||||
|
|
@ -48,9 +49,10 @@
|
|||
"expo-screen-orientation": "~8.0.4",
|
||||
"expo-status-bar": "~2.0.1",
|
||||
"expo-system-ui": "^4.0.9",
|
||||
"expo-updates": "~0.27.4",
|
||||
"expo-web-browser": "~14.0.2",
|
||||
"lodash": "^4.17.21",
|
||||
"lottie-react-native": "^7.3.1",
|
||||
"lottie-react-native": "7.1.0",
|
||||
"posthog-react-native": "^4.4.0",
|
||||
"react": "18.3.1",
|
||||
"react-native": "0.76.9",
|
||||
|
|
@ -59,10 +61,10 @@
|
|||
"react-native-image-colors": "^2.5.0",
|
||||
"react-native-immersive-mode": "^2.0.2",
|
||||
"react-native-paper": "^5.13.1",
|
||||
"react-native-reanimated": "^3.18.0",
|
||||
"react-native-reanimated": "~3.16.1",
|
||||
"react-native-safe-area-context": "4.12.0",
|
||||
"react-native-screens": "~4.4.0",
|
||||
"react-native-svg": "^15.11.2",
|
||||
"react-native-svg": "15.8.0",
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-video": "^6.12.0",
|
||||
"react-native-vlc-media-player": "^1.0.87",
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ import {
|
|||
Dimensions,
|
||||
Image,
|
||||
Button,
|
||||
Linking
|
||||
Linking,
|
||||
Clipboard
|
||||
} from 'react-native';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import { useNavigation } from '@react-navigation/native';
|
||||
|
|
@ -30,6 +31,7 @@ import { useAccount } from '../contexts/AccountContext';
|
|||
import { catalogService } from '../services/catalogService';
|
||||
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
||||
import * as Sentry from '@sentry/react-native';
|
||||
import UpdateService from '../services/updateService';
|
||||
|
||||
const { width, height } = Dimensions.get('window');
|
||||
const isTablet = width >= 768;
|
||||
|
|
@ -43,6 +45,7 @@ const SETTINGS_CATEGORIES = [
|
|||
{ id: 'appearance', title: 'Appearance', icon: 'palette' },
|
||||
{ id: 'integrations', title: 'Integrations', icon: 'extension' },
|
||||
{ id: 'playback', title: 'Playback', icon: 'play-circle-outline' },
|
||||
{ id: 'updates', title: 'Updates', icon: 'system-update' },
|
||||
{ id: 'about', title: 'About', icon: 'info-outline' },
|
||||
{ id: 'developer', title: 'Developer', icon: 'code' },
|
||||
{ id: 'cache', title: 'Cache', icon: 'cached' },
|
||||
|
|
@ -220,6 +223,348 @@ const Sidebar: React.FC<SidebarProps> = ({ selectedCategory, onCategorySelect, c
|
|||
);
|
||||
};
|
||||
|
||||
// Updates Section Component
|
||||
interface UpdatesSectionProps {
|
||||
isTablet: boolean;
|
||||
}
|
||||
|
||||
const UpdatesSection: React.FC<UpdatesSectionProps> = ({ isTablet }) => {
|
||||
const { currentTheme } = useTheme();
|
||||
const [updateInfo, setUpdateInfo] = useState<any>(null);
|
||||
const [isChecking, setIsChecking] = useState(false);
|
||||
const [isInstalling, setIsInstalling] = useState(false);
|
||||
const [lastChecked, setLastChecked] = useState<Date | null>(null);
|
||||
const [logs, setLogs] = useState<string[]>([]);
|
||||
const [showLogs, setShowLogs] = useState(false);
|
||||
const [lastOperation, setLastOperation] = useState<string>('');
|
||||
|
||||
const checkForUpdates = async () => {
|
||||
try {
|
||||
setIsChecking(true);
|
||||
setLastOperation('Checking for updates...');
|
||||
|
||||
const info = await UpdateService.checkForUpdates();
|
||||
setUpdateInfo(info);
|
||||
setLastChecked(new Date());
|
||||
|
||||
// Refresh logs after operation
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
|
||||
if (info.isAvailable) {
|
||||
setLastOperation(`Update available: ${info.manifest?.id?.substring(0, 8) || 'unknown'}...`);
|
||||
} else {
|
||||
setLastOperation('No updates available');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking for updates:', error);
|
||||
setLastOperation(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
Alert.alert('Error', 'Failed to check for updates');
|
||||
} finally {
|
||||
setIsChecking(false);
|
||||
}
|
||||
};
|
||||
|
||||
const installUpdate = async () => {
|
||||
try {
|
||||
setIsInstalling(true);
|
||||
setLastOperation('Installing update...');
|
||||
|
||||
const success = await UpdateService.downloadAndInstallUpdate();
|
||||
|
||||
// Refresh logs after operation
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
|
||||
if (success) {
|
||||
setLastOperation('Update installed successfully');
|
||||
Alert.alert('Success', 'Update will be applied on next app restart');
|
||||
} else {
|
||||
setLastOperation('No update available to install');
|
||||
Alert.alert('No Update', 'No update available to install');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error installing update:', error);
|
||||
setLastOperation(`Installation error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
Alert.alert('Error', 'Failed to install update');
|
||||
} finally {
|
||||
setIsInstalling(false);
|
||||
}
|
||||
};
|
||||
|
||||
const getCurrentUpdateInfo = async () => {
|
||||
const info = await UpdateService.getCurrentUpdateInfo();
|
||||
setUpdateInfo(info);
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
};
|
||||
|
||||
const refreshLogs = () => {
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
};
|
||||
|
||||
const clearLogs = () => {
|
||||
UpdateService.clearLogs();
|
||||
setLogs([]);
|
||||
setLastOperation('Logs cleared');
|
||||
};
|
||||
|
||||
const copyLog = (logText: string) => {
|
||||
Clipboard.setString(logText);
|
||||
Alert.alert('Copied', 'Log entry copied to clipboard');
|
||||
};
|
||||
|
||||
const copyAllLogs = () => {
|
||||
const allLogsText = logs.join('\n');
|
||||
Clipboard.setString(allLogsText);
|
||||
Alert.alert('Copied', 'All logs copied to clipboard');
|
||||
};
|
||||
|
||||
const addTestLog = () => {
|
||||
UpdateService.addTestLog(`Test log entry at ${new Date().toISOString()}`);
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
setLastOperation('Test log added');
|
||||
};
|
||||
|
||||
const testConnectivity = async () => {
|
||||
try {
|
||||
setLastOperation('Testing connectivity...');
|
||||
const isReachable = await UpdateService.testUpdateConnectivity();
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
|
||||
if (isReachable) {
|
||||
setLastOperation('Update server is reachable');
|
||||
} else {
|
||||
setLastOperation('Update server is not reachable');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error testing connectivity:', error);
|
||||
setLastOperation(`Connectivity test error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
}
|
||||
};
|
||||
|
||||
const testAssetUrls = async () => {
|
||||
try {
|
||||
setLastOperation('Testing asset URLs...');
|
||||
await UpdateService.testAllAssetUrls();
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
setLastOperation('Asset URL testing completed');
|
||||
} catch (error) {
|
||||
console.error('Error testing asset URLs:', error);
|
||||
setLastOperation(`Asset URL test error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
||||
const logs = UpdateService.getLogs();
|
||||
setLogs(logs);
|
||||
}
|
||||
};
|
||||
|
||||
// Load current update info on mount
|
||||
useEffect(() => {
|
||||
const loadInitialData = async () => {
|
||||
await getCurrentUpdateInfo();
|
||||
// Also refresh logs to ensure we have the latest
|
||||
refreshLogs();
|
||||
};
|
||||
loadInitialData();
|
||||
}, []);
|
||||
|
||||
const formatDate = (date: Date) => {
|
||||
return date.toLocaleString();
|
||||
};
|
||||
|
||||
return (
|
||||
<View>
|
||||
<SettingsCard title="APP UPDATES" isTablet={isTablet}>
|
||||
<SettingItem
|
||||
title="Check for Updates"
|
||||
description={isChecking ? "Checking..." : lastOperation || "Manually check for new updates"}
|
||||
icon="system-update"
|
||||
onPress={checkForUpdates}
|
||||
renderControl={() => (
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
{isChecking && (
|
||||
<View style={[styles.loadingSpinner, { borderColor: currentTheme.colors.primary }]} />
|
||||
)}
|
||||
<MaterialIcons
|
||||
name="chevron-right"
|
||||
size={24}
|
||||
color={currentTheme.colors.mediumEmphasis}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
|
||||
{updateInfo?.isAvailable && (
|
||||
<SettingItem
|
||||
title="Install Update"
|
||||
description={isInstalling ? "Installing..." : "Download and install the latest update"}
|
||||
icon="download"
|
||||
onPress={installUpdate}
|
||||
renderControl={() => (
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
{isInstalling && (
|
||||
<View style={[styles.loadingSpinner, { borderColor: currentTheme.colors.primary }]} />
|
||||
)}
|
||||
<MaterialIcons
|
||||
name="chevron-right"
|
||||
size={24}
|
||||
color={currentTheme.colors.mediumEmphasis}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
)}
|
||||
|
||||
<SettingItem
|
||||
title="Current Version"
|
||||
description={updateInfo?.manifest?.id ? `Update ID: ${updateInfo.manifest.id.substring(0, 8)}...` : "App version info"}
|
||||
icon="info"
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
|
||||
{lastChecked && (
|
||||
<SettingItem
|
||||
title="Last Checked"
|
||||
description={formatDate(lastChecked)}
|
||||
icon="schedule"
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
)}
|
||||
|
||||
<SettingItem
|
||||
title="Update Logs"
|
||||
description={`${logs.length} log entries`}
|
||||
icon="history"
|
||||
onPress={() => setShowLogs(!showLogs)}
|
||||
renderControl={() => (
|
||||
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
||||
<MaterialIcons
|
||||
name={showLogs ? "expand-less" : "expand-more"}
|
||||
size={24}
|
||||
color={currentTheme.colors.mediumEmphasis}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
isTablet={isTablet}
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
||||
{showLogs && (
|
||||
<SettingsCard title="UPDATE LOGS" isTablet={isTablet}>
|
||||
<View style={styles.logsContainer}>
|
||||
<View style={styles.logsHeader}>
|
||||
<Text style={[styles.logsHeaderText, { color: currentTheme.colors.highEmphasis }]}>
|
||||
Update Service Logs
|
||||
</Text>
|
||||
<View style={styles.logsActions}>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={testConnectivity}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="wifi" size={16} color={currentTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={testAssetUrls}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="link" size={16} color={currentTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={addTestLog}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="add" size={16} color={currentTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={copyAllLogs}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="content-copy" size={16} color={currentTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={refreshLogs}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="refresh" size={16} color={currentTheme.colors.primary} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
style={[styles.logActionButton, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
onPress={clearLogs}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<MaterialIcons name="clear" size={16} color={currentTheme.colors.error || '#ff4444'} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ScrollView
|
||||
style={[styles.logsScrollView, { backgroundColor: currentTheme.colors.elevation2 }]}
|
||||
showsVerticalScrollIndicator={true}
|
||||
nestedScrollEnabled={true}
|
||||
>
|
||||
{logs.length === 0 ? (
|
||||
<Text style={[styles.noLogsText, { color: currentTheme.colors.mediumEmphasis }]}>
|
||||
No logs available
|
||||
</Text>
|
||||
) : (
|
||||
logs.map((log, index) => {
|
||||
const isError = log.includes('[ERROR]');
|
||||
const isWarning = log.includes('[WARN]');
|
||||
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={index}
|
||||
style={[
|
||||
styles.logEntry,
|
||||
{ backgroundColor: 'rgba(255,255,255,0.05)' }
|
||||
]}
|
||||
onPress={() => copyLog(log)}
|
||||
activeOpacity={0.7}
|
||||
>
|
||||
<View style={styles.logEntryContent}>
|
||||
<Text style={[
|
||||
styles.logText,
|
||||
{
|
||||
color: isError
|
||||
? (currentTheme.colors.error || '#ff4444')
|
||||
: isWarning
|
||||
? (currentTheme.colors.warning || '#ffaa00')
|
||||
: currentTheme.colors.mediumEmphasis
|
||||
}
|
||||
]}>
|
||||
{log}
|
||||
</Text>
|
||||
<MaterialIcons
|
||||
name="content-copy"
|
||||
size={14}
|
||||
color={currentTheme.colors.mediumEmphasis}
|
||||
style={styles.logCopyIcon}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</ScrollView>
|
||||
</View>
|
||||
</SettingsCard>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const SettingsScreen: React.FC = () => {
|
||||
const { settings, updateSetting } = useSettings();
|
||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||
|
|
@ -582,7 +927,7 @@ const SettingsScreen: React.FC = () => {
|
|||
/>
|
||||
<SettingItem
|
||||
title="Version"
|
||||
description="0.6.0-beta.8"
|
||||
description="0.6.0-beta.8-test"
|
||||
icon="info-outline"
|
||||
isLast={true}
|
||||
isTablet={isTablet}
|
||||
|
|
@ -657,6 +1002,9 @@ const SettingsScreen: React.FC = () => {
|
|||
</SettingsCard>
|
||||
) : null;
|
||||
|
||||
case 'updates':
|
||||
return <UpdatesSection isTablet={isTablet} />;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -748,6 +1096,7 @@ const SettingsScreen: React.FC = () => {
|
|||
{renderCategoryContent('appearance')}
|
||||
{renderCategoryContent('integrations')}
|
||||
{renderCategoryContent('playback')}
|
||||
{renderCategoryContent('updates')}
|
||||
{renderCategoryContent('about')}
|
||||
{renderCategoryContent('developer')}
|
||||
{renderCategoryContent('cache')}
|
||||
|
|
@ -1048,6 +1397,70 @@ const styles = StyleSheet.create({
|
|||
fontSize: 14,
|
||||
fontWeight: '500',
|
||||
},
|
||||
loadingSpinner: {
|
||||
width: 16,
|
||||
height: 16,
|
||||
borderWidth: 2,
|
||||
borderRadius: 8,
|
||||
borderTopColor: 'transparent',
|
||||
marginRight: 8,
|
||||
},
|
||||
// Logs styles
|
||||
logsContainer: {
|
||||
padding: 16,
|
||||
},
|
||||
logsHeader: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
marginBottom: 12,
|
||||
},
|
||||
logsHeaderText: {
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
},
|
||||
logsActions: {
|
||||
flexDirection: 'row',
|
||||
gap: 8,
|
||||
},
|
||||
logActionButton: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 16,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
logsScrollView: {
|
||||
maxHeight: 200,
|
||||
borderRadius: 8,
|
||||
padding: 12,
|
||||
},
|
||||
logEntry: {
|
||||
marginBottom: 4,
|
||||
paddingVertical: 4,
|
||||
paddingHorizontal: 8,
|
||||
borderRadius: 4,
|
||||
},
|
||||
logEntryContent: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
logText: {
|
||||
fontSize: 12,
|
||||
fontFamily: Platform.OS === 'ios' ? 'Menlo' : 'monospace',
|
||||
lineHeight: 16,
|
||||
flex: 1,
|
||||
marginRight: 8,
|
||||
},
|
||||
logCopyIcon: {
|
||||
opacity: 0.6,
|
||||
},
|
||||
noLogsText: {
|
||||
fontSize: 14,
|
||||
textAlign: 'center',
|
||||
paddingVertical: 20,
|
||||
},
|
||||
});
|
||||
|
||||
export default SettingsScreen;
|
||||
467
src/services/updateService.ts
Normal file
467
src/services/updateService.ts
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
import * as Updates from 'expo-updates';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
export interface UpdateInfo {
|
||||
isAvailable: boolean;
|
||||
manifest?: Partial<Updates.Manifest>;
|
||||
isNew?: boolean;
|
||||
isEmbeddedLaunch?: boolean;
|
||||
}
|
||||
|
||||
export class UpdateService {
|
||||
private static instance: UpdateService;
|
||||
private updateCheckInterval: NodeJS.Timeout | null = null;
|
||||
private readonly CHECK_INTERVAL = 5 * 60 * 1000; // 5 minutes
|
||||
private logs: string[] = [];
|
||||
private readonly MAX_LOGS = 100; // Keep last 100 logs
|
||||
|
||||
private constructor() {}
|
||||
|
||||
public static getInstance(): UpdateService {
|
||||
if (!UpdateService.instance) {
|
||||
UpdateService.instance = new UpdateService();
|
||||
}
|
||||
return UpdateService.instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a log entry with timestamp - always log to console for adb logcat visibility
|
||||
*/
|
||||
private addLog(message: string, level: 'INFO' | 'WARN' | 'ERROR' = 'INFO'): void {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logEntry = `[${timestamp}] [${level}] ${message}`;
|
||||
|
||||
this.logs.unshift(logEntry);
|
||||
|
||||
// Keep only the last MAX_LOGS entries
|
||||
if (this.logs.length > this.MAX_LOGS) {
|
||||
this.logs = this.logs.slice(0, this.MAX_LOGS);
|
||||
}
|
||||
|
||||
// Always log to console - this will be visible in adb logcat for production builds
|
||||
// Use different console methods for better filtering in logcat
|
||||
if (level === 'ERROR') {
|
||||
console.error(`[UpdateService] ${logEntry}`);
|
||||
} else if (level === 'WARN') {
|
||||
console.warn(`[UpdateService] ${logEntry}`);
|
||||
} else {
|
||||
console.log(`[UpdateService] ${logEntry}`);
|
||||
}
|
||||
|
||||
// Also log with a consistent prefix for easy filtering
|
||||
console.log(`UpdateService: ${logEntry}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all logs
|
||||
*/
|
||||
public getLogs(): string[] {
|
||||
return [...this.logs];
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all logs
|
||||
*/
|
||||
public clearLogs(): void {
|
||||
this.logs = [];
|
||||
this.addLog('Logs cleared', 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a test log entry (useful for debugging)
|
||||
*/
|
||||
public addTestLog(message: string): void {
|
||||
this.addLog(`TEST: ${message}`, 'INFO');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the update URL connectivity
|
||||
*/
|
||||
public async testUpdateConnectivity(): Promise<boolean> {
|
||||
this.addLog('Testing update server connectivity...', 'INFO');
|
||||
|
||||
try {
|
||||
const updateUrl = this.getUpdateUrl();
|
||||
this.addLog(`Testing URL: ${updateUrl}`, 'INFO');
|
||||
|
||||
const response = await fetch(updateUrl, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'expo-runtime-version': Updates.runtimeVersion || '0.6.0-beta.8',
|
||||
'expo-platform': Platform.OS,
|
||||
'expo-protocol-version': '1',
|
||||
'expo-api-version': '1',
|
||||
},
|
||||
});
|
||||
|
||||
this.addLog(`Response status: ${response.status}`, 'INFO');
|
||||
this.addLog(`Response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`, 'INFO');
|
||||
|
||||
if (response.ok) {
|
||||
this.addLog('Update server is reachable', 'INFO');
|
||||
|
||||
// Try to get the response body to see what we're getting
|
||||
try {
|
||||
const responseText = await response.text();
|
||||
this.addLog(`Response body preview: ${responseText.substring(0, 500)}...`, 'INFO');
|
||||
} catch (bodyError) {
|
||||
this.addLog(`Could not read response body: ${bodyError instanceof Error ? bodyError.message : String(bodyError)}`, 'WARN');
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
this.addLog(`Update server returned error: ${response.status} ${response.statusText}`, 'ERROR');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Connectivity test failed: ${errorMessage}`, 'ERROR');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test individual asset URL accessibility
|
||||
*/
|
||||
public async testAssetUrl(assetUrl: string): Promise<boolean> {
|
||||
this.addLog(`Testing asset URL: ${assetUrl}`, 'INFO');
|
||||
|
||||
try {
|
||||
const response = await fetch(assetUrl, {
|
||||
method: 'HEAD', // Use HEAD to avoid downloading the full asset
|
||||
});
|
||||
|
||||
this.addLog(`Asset response status: ${response.status}`, 'INFO');
|
||||
this.addLog(`Asset response headers: ${JSON.stringify(Object.fromEntries(response.headers.entries()))}`, 'INFO');
|
||||
|
||||
if (response.ok) {
|
||||
this.addLog('Asset URL is accessible', 'INFO');
|
||||
return true;
|
||||
} else {
|
||||
this.addLog(`Asset URL returned error: ${response.status} ${response.statusText}`, 'ERROR');
|
||||
return false;
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Asset URL test failed: ${errorMessage}`, 'ERROR');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test all asset URLs from the latest update manifest
|
||||
*/
|
||||
public async testAllAssetUrls(): Promise<void> {
|
||||
this.addLog('Testing all asset URLs from latest update...', 'INFO');
|
||||
|
||||
try {
|
||||
const update = await Updates.checkForUpdateAsync();
|
||||
|
||||
if (!update.isAvailable || !update.manifest) {
|
||||
this.addLog('No update available or no manifest found', 'WARN');
|
||||
return;
|
||||
}
|
||||
|
||||
this.addLog(`Found update with ${update.manifest.assets?.length || 0} assets`, 'INFO');
|
||||
|
||||
if (update.manifest.assets && update.manifest.assets.length > 0) {
|
||||
for (let i = 0; i < update.manifest.assets.length; i++) {
|
||||
const asset = update.manifest.assets[i];
|
||||
if (asset.url) {
|
||||
this.addLog(`Testing asset ${i + 1}/${update.manifest.assets.length}: ${asset.key || 'unknown'}`, 'INFO');
|
||||
const isAccessible = await this.testAssetUrl(asset.url);
|
||||
if (!isAccessible) {
|
||||
this.addLog(`Asset ${i + 1} is not accessible: ${asset.url}`, 'ERROR');
|
||||
}
|
||||
} else {
|
||||
this.addLog(`Asset ${i + 1} has no URL`, 'ERROR');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test launch asset (check if it exists in the manifest)
|
||||
const manifest = update.manifest as any; // Type assertion to access launchAsset
|
||||
if (manifest.launchAsset?.url) {
|
||||
this.addLog('Testing launch asset...', 'INFO');
|
||||
const isAccessible = await this.testAssetUrl(manifest.launchAsset.url);
|
||||
if (!isAccessible) {
|
||||
this.addLog(`Launch asset is not accessible: ${manifest.launchAsset.url}`, 'ERROR');
|
||||
}
|
||||
} else {
|
||||
this.addLog('No launch asset URL found', 'ERROR');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Failed to test asset URLs: ${errorMessage}`, 'ERROR');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the update service
|
||||
*/
|
||||
public async initialize(): Promise<void> {
|
||||
this.addLog('Initializing UpdateService...', 'INFO');
|
||||
this.addLog(`Environment: ${__DEV__ ? 'Development' : 'Production'}`, 'INFO');
|
||||
this.addLog(`Platform: ${Platform.OS}`, 'INFO');
|
||||
this.addLog(`Updates enabled: ${Updates.isEnabled}`, 'INFO');
|
||||
this.addLog(`Runtime version: ${Updates.runtimeVersion || 'unknown'}`, 'INFO');
|
||||
this.addLog(`Update URL: ${this.getUpdateUrl()}`, 'INFO');
|
||||
|
||||
try {
|
||||
// Always perform update check regardless of environment for debugging
|
||||
this.addLog('Performing initial update check...', 'INFO');
|
||||
const updateInfo = await this.checkForUpdates();
|
||||
|
||||
if (updateInfo.isAvailable) {
|
||||
this.addLog(`Update available: ${updateInfo.manifest?.id || 'unknown'}`, 'INFO');
|
||||
} else {
|
||||
this.addLog('No updates available', 'INFO');
|
||||
}
|
||||
|
||||
// Check if we're running in a development environment
|
||||
if (__DEV__) {
|
||||
this.addLog('Running in development mode, but allowing update checks for testing', 'WARN');
|
||||
this.addLog('UpdateService initialization completed (dev mode)', 'INFO');
|
||||
// Don't return early - allow update checks in dev mode for testing
|
||||
}
|
||||
|
||||
// Check if updates are enabled
|
||||
if (!Updates.isEnabled) {
|
||||
this.addLog('Updates are not enabled in this environment', 'WARN');
|
||||
this.addLog('UpdateService initialization completed (updates disabled)', 'INFO');
|
||||
return;
|
||||
}
|
||||
|
||||
this.addLog('Updates are enabled, setting up periodic checks', 'INFO');
|
||||
|
||||
// Set up periodic update checks
|
||||
this.startPeriodicUpdateChecks();
|
||||
this.addLog('UpdateService initialization completed successfully', 'INFO');
|
||||
} catch (error) {
|
||||
this.addLog(`Initialization failed: ${error instanceof Error ? error.message : String(error)}`, 'ERROR');
|
||||
console.error('Update service initialization failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for available updates
|
||||
*/
|
||||
public async checkForUpdates(): Promise<UpdateInfo> {
|
||||
this.addLog('Starting update check...', 'INFO');
|
||||
this.addLog(`Update URL: ${this.getUpdateUrl()}`, 'INFO');
|
||||
this.addLog(`Runtime version: ${Updates.runtimeVersion || 'unknown'}`, 'INFO');
|
||||
this.addLog(`Platform: ${Platform.OS}`, 'INFO');
|
||||
this.addLog(`Updates enabled: ${Updates.isEnabled}`, 'INFO');
|
||||
|
||||
try {
|
||||
// Always attempt the check for debugging purposes
|
||||
this.addLog('Calling Updates.checkForUpdateAsync()...', 'INFO');
|
||||
const startTime = Date.now();
|
||||
|
||||
const update = await Updates.checkForUpdateAsync();
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
this.addLog(`Update check completed in ${duration}ms`, 'INFO');
|
||||
this.addLog(`Check result - isAvailable: ${update.isAvailable}`, 'INFO');
|
||||
|
||||
if (update.isAvailable) {
|
||||
this.addLog(`Update available! ID: ${update.manifest?.id || 'unknown'}`, 'INFO');
|
||||
|
||||
if (update.manifest) {
|
||||
this.addLog(`Manifest ID: ${update.manifest.id || 'unknown'}`, 'INFO');
|
||||
}
|
||||
|
||||
// Check if we can actually install updates
|
||||
if (__DEV__) {
|
||||
this.addLog('WARNING: Update found but in development mode - installation will be skipped', 'WARN');
|
||||
} else if (!Updates.isEnabled) {
|
||||
this.addLog('WARNING: Update found but updates disabled - installation will be skipped', 'WARN');
|
||||
} else {
|
||||
this.addLog('Update found and installation is possible', 'INFO');
|
||||
}
|
||||
|
||||
return {
|
||||
isAvailable: true,
|
||||
manifest: update.manifest,
|
||||
isNew: false, // Default value since isNew is not available in the type
|
||||
isEmbeddedLaunch: false // Default value since isEmbeddedLaunch is not available in the type
|
||||
};
|
||||
}
|
||||
|
||||
this.addLog('No updates available', 'INFO');
|
||||
return { isAvailable: false };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Update check failed: ${errorMessage}`, 'ERROR');
|
||||
console.error('Failed to check for updates:', error);
|
||||
return { isAvailable: false };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download and install the latest update
|
||||
*/
|
||||
public async downloadAndInstallUpdate(): Promise<boolean> {
|
||||
this.addLog('Starting update download and installation...', 'INFO');
|
||||
|
||||
try {
|
||||
// Check environment and updates status first
|
||||
if (__DEV__) {
|
||||
this.addLog('Running in development mode - update installation may have limitations', 'WARN');
|
||||
this.addLog('In development mode, Updates.checkForUpdateAsync() may not work properly', 'WARN');
|
||||
// Don't return false - allow attempting updates in dev mode for testing
|
||||
}
|
||||
|
||||
if (!Updates.isEnabled) {
|
||||
this.addLog('Update installation skipped (updates disabled)', 'WARN');
|
||||
this.addLog('Updates.isEnabled is false - this is why installation fails', 'ERROR');
|
||||
return false;
|
||||
}
|
||||
|
||||
this.addLog('Environment checks passed, proceeding with installation', 'INFO');
|
||||
this.addLog('Checking for available updates before installation...', 'INFO');
|
||||
this.addLog(`Update URL: ${this.getUpdateUrl()}`, 'INFO');
|
||||
this.addLog(`Runtime version: ${Updates.runtimeVersion || 'unknown'}`, 'INFO');
|
||||
this.addLog(`Platform: ${Platform.OS}`, 'INFO');
|
||||
|
||||
const update = await Updates.checkForUpdateAsync();
|
||||
|
||||
if (update.isAvailable) {
|
||||
this.addLog(`Update found, starting download. ID: ${update.manifest?.id || 'unknown'}`, 'INFO');
|
||||
this.addLog(`Manifest details: ${JSON.stringify(update.manifest, null, 2)}`, 'INFO');
|
||||
|
||||
const downloadStartTime = Date.now();
|
||||
this.addLog('Calling Updates.fetchUpdateAsync()...', 'INFO');
|
||||
|
||||
try {
|
||||
await Updates.fetchUpdateAsync();
|
||||
const downloadDuration = Date.now() - downloadStartTime;
|
||||
|
||||
this.addLog(`Update downloaded successfully in ${downloadDuration}ms`, 'INFO');
|
||||
this.addLog('Calling Updates.reloadAsync() to apply update...', 'INFO');
|
||||
|
||||
await Updates.reloadAsync();
|
||||
|
||||
this.addLog('Update installation completed successfully', 'INFO');
|
||||
return true;
|
||||
} catch (fetchError) {
|
||||
const errorMessage = fetchError instanceof Error ? fetchError.message : String(fetchError);
|
||||
this.addLog(`Update fetch failed: ${errorMessage}`, 'ERROR');
|
||||
this.addLog(`Fetch error stack: ${fetchError instanceof Error ? fetchError.stack : 'No stack available'}`, 'ERROR');
|
||||
throw fetchError; // Re-throw to be caught by outer catch block
|
||||
}
|
||||
}
|
||||
|
||||
this.addLog('No update available for installation', 'WARN');
|
||||
this.addLog('Updates.checkForUpdateAsync() returned isAvailable: false', 'INFO');
|
||||
return false;
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Update installation failed: ${errorMessage}`, 'ERROR');
|
||||
this.addLog(`Error stack: ${error instanceof Error ? error.stack : 'No stack available'}`, 'ERROR');
|
||||
console.error('Failed to download/install update:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current update info
|
||||
*/
|
||||
public async getCurrentUpdateInfo(): Promise<UpdateInfo> {
|
||||
try {
|
||||
this.addLog('Getting current update info...', 'INFO');
|
||||
this.addLog(`Updates.isEnabled: ${Updates.isEnabled}`, 'INFO');
|
||||
this.addLog(`Updates.isEmbeddedLaunch: ${Updates.isEmbeddedLaunch}`, 'INFO');
|
||||
|
||||
if (__DEV__) {
|
||||
this.addLog('In development mode - update info may not be accurate', 'WARN');
|
||||
}
|
||||
|
||||
if (!Updates.isEnabled) {
|
||||
this.addLog('Updates disabled - returning false for isAvailable', 'WARN');
|
||||
return { isAvailable: false };
|
||||
}
|
||||
|
||||
const info = {
|
||||
isAvailable: Updates.isEmbeddedLaunch === false,
|
||||
manifest: Updates.manifest,
|
||||
isNew: false, // Default value since Updates.isNew is not available
|
||||
isEmbeddedLaunch: Updates.isEmbeddedLaunch
|
||||
};
|
||||
|
||||
this.addLog(`Current update info - Available: ${info.isAvailable}, Embedded: ${info.isEmbeddedLaunch}`, 'INFO');
|
||||
|
||||
if (info.manifest) {
|
||||
this.addLog(`Current manifest ID: ${info.manifest.id || 'unknown'}`, 'INFO');
|
||||
} else {
|
||||
this.addLog('No manifest available', 'INFO');
|
||||
}
|
||||
|
||||
return info;
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Failed to get current update info: ${errorMessage}`, 'ERROR');
|
||||
console.error('Failed to get current update info:', error);
|
||||
return { isAvailable: false };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start periodic update checks
|
||||
*/
|
||||
private startPeriodicUpdateChecks(): void {
|
||||
if (this.updateCheckInterval) {
|
||||
this.addLog('Stopping existing periodic update checks', 'INFO');
|
||||
clearInterval(this.updateCheckInterval);
|
||||
}
|
||||
|
||||
this.addLog(`Starting periodic update checks every ${this.CHECK_INTERVAL / 1000} seconds`, 'INFO');
|
||||
|
||||
this.updateCheckInterval = setInterval(async () => {
|
||||
try {
|
||||
this.addLog('Performing scheduled update check...', 'INFO');
|
||||
await this.checkForUpdates();
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
this.addLog(`Scheduled update check failed: ${errorMessage}`, 'ERROR');
|
||||
console.error('Periodic update check failed:', error);
|
||||
}
|
||||
}, this.CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop periodic update checks
|
||||
*/
|
||||
public stopPeriodicUpdateChecks(): void {
|
||||
if (this.updateCheckInterval) {
|
||||
this.addLog('Stopping periodic update checks', 'INFO');
|
||||
clearInterval(this.updateCheckInterval);
|
||||
this.updateCheckInterval = null;
|
||||
} else {
|
||||
this.addLog('No periodic update checks running to stop', 'INFO');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the update URL for the current platform
|
||||
*/
|
||||
public getUpdateUrl(): string {
|
||||
// Use the URL from app.json configuration
|
||||
return 'https://grim-reyna-tapframe-69970143.koyeb.app/api/manifest';
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup resources
|
||||
*/
|
||||
public cleanup(): void {
|
||||
this.addLog('Cleaning up UpdateService resources...', 'INFO');
|
||||
this.stopPeriodicUpdateChecks();
|
||||
this.addLog('UpdateService cleanup completed', 'INFO');
|
||||
}
|
||||
}
|
||||
|
||||
export default UpdateService.getInstance();
|
||||
|
||||
|
||||
|
||||
1
xavia-ota
Submodule
1
xavia-ota
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit ba2fe779d75a8ed285c5d37f05532c3ff4acce22
|
||||
Loading…
Reference in a new issue