icon update
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 99 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2 KiB |
|
Before Width: | Height: | Size: 7 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 7 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 55 KiB |
|
|
@ -1,4 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#151515</color>
|
||||
<color name="ic_launcher_background">#d1d1d2</color>
|
||||
</resources>
|
||||
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 111 KiB |
BIN
assets/icon.png
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 718 B After Width: | Height: | Size: 675 B |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 55 KiB |
|
Before Width: | Height: | Size: 189 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 111 KiB |
|
|
@ -460,7 +460,7 @@
|
|||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuviohub.app;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app;
|
||||
PRODUCT_NAME = Nuvio;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
|
|
@ -492,7 +492,7 @@
|
|||
"-lc++",
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuviohub.app;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.nuvio.app;
|
||||
PRODUCT_NAME = Nuvio;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Nuvio/Nuvio-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
|
|
|||
|
|
@ -1,98 +1,101 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Nuvio</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>nuvio</string>
|
||||
<string>com.nuvio.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>exp+nuvio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>20</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_http._tcp</string>
|
||||
</array>
|
||||
<key>RCTNewArchEnabled</key>
|
||||
<true/>
|
||||
<key>RCTRootViewBackgroundColor</key>
|
||||
<integer>4278322180</integer>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
<string>fetch</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>SplashScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<false/>
|
||||
<key>UIStatusBarStyle</key>
|
||||
<string>UIStatusBarStyleDefault</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIUserInterfaceStyle</key>
|
||||
<string>Dark</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Nuvio</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.2.5</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>nuvio</string>
|
||||
<string>com.nuvio.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>exp+nuvio</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>20</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>12.0</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>NSBonjourServices</key>
|
||||
<array>
|
||||
<string>_http._tcp</string>
|
||||
</array>
|
||||
<key>NSLocalNetworkUsageDescription</key>
|
||||
<string>Allow $(PRODUCT_NAME) to access your local network</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app does not require microphone access.</string>
|
||||
<key>RCTNewArchEnabled</key>
|
||||
<true/>
|
||||
<key>RCTRootViewBackgroundColor</key>
|
||||
<integer>4278322180</integer>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>audio</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>SplashScreen</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>UIRequiresFullScreen</key>
|
||||
<false/>
|
||||
<key>UIStatusBarStyle</key>
|
||||
<string>UIStatusBarStyleDefault</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIUserInterfaceStyle</key>
|
||||
<string>Dark</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,5 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict/>
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
146
package-lock.json
generated
|
|
@ -17,6 +17,7 @@
|
|||
"@expo/metro-runtime": "~6.1.2",
|
||||
"@expo/vector-icons": "^15.0.2",
|
||||
"@gorhom/bottom-sheet": "^5.2.6",
|
||||
"@legendapp/list": "^2.0.13",
|
||||
"@lottiefiles/dotlottie-react": "^0.6.5",
|
||||
"@react-native-async-storage/async-storage": "2.2.0",
|
||||
"@react-native-community/blur": "^4.4.1",
|
||||
|
|
@ -29,7 +30,6 @@
|
|||
"@react-navigation/stack": "^7.2.10",
|
||||
"@sentry/react-native": "~7.3.0",
|
||||
"@shopify/flash-list": "^2.1.0",
|
||||
"@supabase/supabase-js": "^2.54.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/react-native-video": "^5.0.20",
|
||||
"axios": "^1.12.2",
|
||||
|
|
@ -67,6 +67,7 @@
|
|||
"posthog-react-native": "^4.4.0",
|
||||
"react": "19.1.0",
|
||||
"react-native": "0.81.4",
|
||||
"react-native-boost": "^0.6.2",
|
||||
"react-native-bottom-tabs": "^0.12.2",
|
||||
"react-native-gesture-handler": "~2.28.0",
|
||||
"react-native-get-random-values": "^1.11.0",
|
||||
|
|
@ -80,7 +81,7 @@
|
|||
"react-native-svg": "15.12.1",
|
||||
"react-native-url-polyfill": "^2.0.0",
|
||||
"react-native-vector-icons": "^10.3.0",
|
||||
"react-native-video": "^6.12.0",
|
||||
"react-native-video": "^6.17.0",
|
||||
"react-native-web": "^0.21.0",
|
||||
"react-native-wheel-color-picker": "^1.3.1",
|
||||
"react-native-worklets": "^0.6.1",
|
||||
|
|
@ -2347,6 +2348,27 @@
|
|||
"integrity": "sha512-F0YfUDjvT+Mtt/R4xdl2X0EYCHMMiJqNLdxHD++jDT5ydEFIyqbCHh51Qx2E211dgZprPKhV7sHmnXKpLuvc5g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/balanced-match": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz",
|
||||
"integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/brace-expansion": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz",
|
||||
"integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@isaacs/balanced-match": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/@isaacs/cliui": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
|
|
@ -3636,80 +3658,6 @@
|
|||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/auth-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.75.0.tgz",
|
||||
"integrity": "sha512-J8TkeqCOMCV4KwGKVoxmEBuDdHRwoInML2vJilthOo7awVCro2SM+tOcpljORwuBQ1vHUtV62Leit+5wlxrNtw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "2.6.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/functions-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.75.0.tgz",
|
||||
"integrity": "sha512-18yk07Moj/xtQ28zkqswxDavXC3vbOwt1hDuYM3/7xPnwwpKnsmPyZ7bQ5th4uqiJzQ135t74La9tuaxBR6e7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "2.6.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/node-fetch": {
|
||||
"version": "2.6.15",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz",
|
||||
"integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"whatwg-url": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "4.x || >=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/postgrest-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.75.0.tgz",
|
||||
"integrity": "sha512-YfBz4W/z7eYCFyuvHhfjOTTzRrQIvsMG2bVwJAKEVVUqGdzqfvyidXssLBG0Fqlql1zJFgtsPpK1n4meHrI7tg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "2.6.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/realtime-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.75.0.tgz",
|
||||
"integrity": "sha512-B4Xxsf2NHd5cEnM6MGswOSPSsZKljkYXpvzKKmNxoUmNQOfB7D8HOa6NwHcUBSlxcjV+vIrYKcYXtavGJqeGrw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "2.6.15",
|
||||
"@types/phoenix": "^1.6.6",
|
||||
"@types/ws": "^8.18.1",
|
||||
"ws": "^8.18.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/storage-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.75.0.tgz",
|
||||
"integrity": "sha512-wpJMYdfFDckDiHQaTpK+Ib14N/O2o0AAWWhguKvmmMurB6Unx17GGmYp5rrrqCTf8S1qq4IfIxTXxS4hzrUySg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/node-fetch": "2.6.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@supabase/supabase-js": {
|
||||
"version": "2.75.0",
|
||||
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.75.0.tgz",
|
||||
"integrity": "sha512-8UN/vATSgS2JFuJlMVr51L3eUDz+j1m7Ww63wlvHLKULzCDaVWYzvacCjBTLW/lX/vedI2LBI4Vg+01G9ufsJQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@supabase/auth-js": "2.75.0",
|
||||
"@supabase/functions-js": "2.75.0",
|
||||
"@supabase/node-fetch": "2.6.15",
|
||||
"@supabase/postgrest-js": "2.75.0",
|
||||
"@supabase/realtime-js": "2.75.0",
|
||||
"@supabase/storage-js": "2.75.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@svgr/babel-plugin-add-jsx-attribute": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz",
|
||||
|
|
@ -4234,12 +4182,6 @@
|
|||
"undici-types": "~7.14.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/phoenix": {
|
||||
"version": "1.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz",
|
||||
"integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/prop-types": {
|
||||
"version": "15.7.15",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz",
|
||||
|
|
@ -4283,15 +4225,6 @@
|
|||
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/ws": {
|
||||
"version": "8.18.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
|
||||
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/yargs": {
|
||||
"version": "17.0.33",
|
||||
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
|
||||
|
|
@ -10759,6 +10692,37 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-boost": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-boost/-/react-native-boost-0.6.2.tgz",
|
||||
"integrity": "sha512-6w9PdGvFzyI1dyN516+mLfFF5vETPsjoc26rUFlzWav7PNbC7WV0KyfTBr0q/cDjZkWLMleWQZkGTqSQ1H4PHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.25.0",
|
||||
"@babel/helper-module-imports": "^7.25.0",
|
||||
"@babel/helper-plugin-utils": "^7.25.0",
|
||||
"minimatch": "^10.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "*",
|
||||
"react-native": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-boost/node_modules/minimatch": {
|
||||
"version": "10.0.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
|
||||
"integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@isaacs/brace-expansion": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/react-native-bottom-tabs": {
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmjs.org/react-native-bottom-tabs/-/react-native-bottom-tabs-0.12.2.tgz",
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@
|
|||
"@react-navigation/stack": "^7.2.10",
|
||||
"@sentry/react-native": "~7.3.0",
|
||||
"@shopify/flash-list": "^2.1.0",
|
||||
"@supabase/supabase-js": "^2.54.0",
|
||||
"@types/lodash": "^4.17.16",
|
||||
"@types/react-native-video": "^5.0.20",
|
||||
"axios": "^1.12.2",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import React, { createContext, useContext, useEffect, useMemo, useState, useRef } from 'react';
|
||||
import { InteractionManager } from 'react-native';
|
||||
import accountService, { AuthUser } from '../services/AccountService';
|
||||
import supabase from '../services/supabaseClient';
|
||||
import syncService from '../services/SyncService';
|
||||
|
||||
type AccountContextValue = {
|
||||
user: AuthUser | null;
|
||||
|
|
@ -22,73 +19,19 @@ export const AccountProvider: React.FC<{ children: React.ReactNode }> = ({ child
|
|||
const loadingTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
// Initial session (load full profile)
|
||||
// Defer heavy work until after initial interactions to reduce launch CPU spike
|
||||
const task = InteractionManager.runAfterInteractions(() => {
|
||||
(async () => {
|
||||
// Initial user load
|
||||
const loadUser = async () => {
|
||||
try {
|
||||
const u = await accountService.getCurrentUser();
|
||||
setUser(u);
|
||||
} catch (error) {
|
||||
console.warn('[AccountContext] Failed to load user:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
// Stage sync operations to avoid blocking the JS thread
|
||||
syncService.init();
|
||||
if (u) {
|
||||
try {
|
||||
await syncService.migrateLocalScopeToUser();
|
||||
// Longer yield to event loop to reduce CPU pressure
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
await syncService.subscribeRealtime();
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
// Pull first to hydrate local state, then push to avoid wiping server with empty local
|
||||
await syncService.fullPull();
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
await syncService.fullPush();
|
||||
} catch {}
|
||||
}
|
||||
})();
|
||||
});
|
||||
|
||||
// Auth state listener
|
||||
const { data: subscription } = supabase.auth.onAuthStateChange(async (event, session) => {
|
||||
// Only set loading for actual auth changes, not initial session
|
||||
if (event !== 'INITIAL_SESSION') {
|
||||
setLoading(true);
|
||||
}
|
||||
try {
|
||||
const fullUser = session?.user ? await accountService.getCurrentUser() : null;
|
||||
setUser(fullUser);
|
||||
// Immediately clear loading so UI can transition to MainTabs/Auth
|
||||
setLoading(false);
|
||||
if (fullUser) {
|
||||
// Run sync in background without blocking UI
|
||||
setTimeout(async () => {
|
||||
try {
|
||||
await syncService.migrateLocalScopeToUser();
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
await syncService.subscribeRealtime();
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
await syncService.fullPull();
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
await syncService.fullPush();
|
||||
} catch (error) {
|
||||
console.warn('[AccountContext] Background sync failed:', error);
|
||||
}
|
||||
}, 0);
|
||||
} else {
|
||||
syncService.unsubscribeRealtime();
|
||||
}
|
||||
} catch (e) {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
subscription.subscription.unsubscribe();
|
||||
task.cancel();
|
||||
if (loadingTimeoutRef.current) {
|
||||
clearTimeout(loadingTimeoutRef.current);
|
||||
loadingTimeoutRef.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
loadUser();
|
||||
}, []);
|
||||
|
||||
const value = useMemo<AccountContextValue>(() => ({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { syncService } from '../services/SyncService';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
// Simple event emitter for settings changes
|
||||
|
|
@ -230,8 +229,6 @@ export const useSettings = () => {
|
|||
settingsEmitter.emit();
|
||||
}
|
||||
|
||||
// If authenticated, push settings to server to prevent overwrite on next pull
|
||||
try { syncService.pushSettings(); } catch {}
|
||||
} catch (error) {
|
||||
if (__DEV__) console.error('Failed to save settings:', error);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
import supabase from './supabaseClient';
|
||||
|
||||
export type AuthUser = {
|
||||
id: string;
|
||||
|
|
@ -8,6 +7,7 @@ export type AuthUser = {
|
|||
displayName?: string;
|
||||
};
|
||||
|
||||
const USER_DATA_KEY = '@user:data';
|
||||
const USER_SCOPE_KEY = '@user:current';
|
||||
|
||||
class AccountService {
|
||||
|
|
@ -20,53 +20,41 @@ class AccountService {
|
|||
}
|
||||
|
||||
async signUpWithEmail(email: string, password: string): Promise<{ user?: AuthUser; error?: string }> {
|
||||
const { data, error } = await supabase.auth.signUp({ email, password });
|
||||
if (error) return { error: error.message };
|
||||
const user = data.user ? { id: data.user.id, email: data.user.email ?? undefined } : undefined;
|
||||
if (user) await AsyncStorage.setItem(USER_SCOPE_KEY, user.id);
|
||||
// Initialize profile row
|
||||
if (user) {
|
||||
await supabase.from('user_profiles').upsert({ user_id: user.id }, { onConflict: 'user_id' });
|
||||
}
|
||||
return { user };
|
||||
// Since signup is disabled, always return error
|
||||
return { error: 'Sign up is currently disabled due to upcoming system changes' };
|
||||
}
|
||||
|
||||
async signInWithEmail(email: string, password: string): Promise<{ user?: AuthUser; error?: string }> {
|
||||
const { data, error } = await supabase.auth.signInWithPassword({ email, password });
|
||||
if (error) return { error: error.message };
|
||||
const user = data.user ? { id: data.user.id, email: data.user.email ?? undefined } : undefined;
|
||||
if (user) await AsyncStorage.setItem(USER_SCOPE_KEY, user.id);
|
||||
return { user };
|
||||
// Since signin is disabled, always return error
|
||||
return { error: 'Authentication is currently disabled' };
|
||||
}
|
||||
|
||||
async signOut(): Promise<void> {
|
||||
await supabase.auth.signOut();
|
||||
await AsyncStorage.removeItem(USER_DATA_KEY);
|
||||
await AsyncStorage.setItem(USER_SCOPE_KEY, 'local');
|
||||
}
|
||||
|
||||
async getCurrentUser(): Promise<AuthUser | null> {
|
||||
const { data } = await supabase.auth.getUser();
|
||||
const u = data.user;
|
||||
if (!u) return null;
|
||||
// Fetch profile for avatar and display name
|
||||
const { data: profile } = await supabase
|
||||
.from('user_profiles')
|
||||
.select('avatar_url, display_name')
|
||||
.eq('user_id', u.id)
|
||||
.maybeSingle();
|
||||
return { id: u.id, email: u.email ?? undefined, avatarUrl: profile?.avatar_url ?? undefined, displayName: profile?.display_name ?? undefined };
|
||||
try {
|
||||
const userData = await AsyncStorage.getItem(USER_DATA_KEY);
|
||||
if (!userData) return null;
|
||||
return JSON.parse(userData);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async updateProfile(partial: { avatarUrl?: string; displayName?: string }): Promise<string | null> {
|
||||
const { data } = await supabase.auth.getUser();
|
||||
const userId = data.user?.id;
|
||||
if (!userId) return 'Not authenticated';
|
||||
const { error } = await supabase.from('user_profiles').upsert({
|
||||
user_id: userId,
|
||||
avatar_url: partial.avatarUrl,
|
||||
display_name: partial.displayName,
|
||||
}, { onConflict: 'user_id' });
|
||||
return error?.message ?? null;
|
||||
try {
|
||||
const currentUser = await this.getCurrentUser();
|
||||
if (!currentUser) return 'Not authenticated';
|
||||
|
||||
const updatedUser = { ...currentUser, ...partial };
|
||||
await AsyncStorage.setItem(USER_DATA_KEY, JSON.stringify(updatedUser));
|
||||
return null;
|
||||
} catch {
|
||||
return 'Failed to update profile';
|
||||
}
|
||||
}
|
||||
|
||||
async getCurrentUserIdScoped(): Promise<string> {
|
||||
|
|
|
|||
|
|
@ -573,7 +573,6 @@ class StremioService {
|
|||
|
||||
await this.saveInstalledAddons();
|
||||
await this.saveAddonOrder();
|
||||
try { (require('./SyncService').syncService as any).pushAddons?.(); } catch {}
|
||||
// Emit an event that an addon was added
|
||||
addonEmitter.emit(ADDON_EVENTS.ADDON_ADDED, manifest.id);
|
||||
} else {
|
||||
|
|
@ -596,7 +595,6 @@ class StremioService {
|
|||
// Persist removals before app possibly exits
|
||||
await this.saveInstalledAddons();
|
||||
await this.saveAddonOrder();
|
||||
try { (require('./SyncService').syncService as any).pushAddons?.(); } catch {}
|
||||
// Emit an event that an addon was removed
|
||||
addonEmitter.emit(ADDON_EVENTS.ADDON_REMOVED, id);
|
||||
}
|
||||
|
|
@ -1637,8 +1635,6 @@ class StremioService {
|
|||
[this.addonOrder[index - 1], this.addonOrder[index]] =
|
||||
[this.addonOrder[index], this.addonOrder[index - 1]];
|
||||
this.saveAddonOrder();
|
||||
// Immediately push to server to avoid resets on restart
|
||||
try { (require('./SyncService').syncService as any).pushAddons?.(); } catch {}
|
||||
// Emit an event that the order has changed
|
||||
addonEmitter.emit(ADDON_EVENTS.ORDER_CHANGED);
|
||||
return true;
|
||||
|
|
@ -1653,8 +1649,6 @@ class StremioService {
|
|||
[this.addonOrder[index], this.addonOrder[index + 1]] =
|
||||
[this.addonOrder[index + 1], this.addonOrder[index]];
|
||||
this.saveAddonOrder();
|
||||
// Immediately push to server to avoid resets on restart
|
||||
try { (require('./SyncService').syncService as any).pushAddons?.(); } catch {}
|
||||
// Emit an event that the order has changed
|
||||
addonEmitter.emit(ADDON_EVENTS.ORDER_CHANGED);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
import 'react-native-url-polyfill/auto';
|
||||
import 'react-native-get-random-values';
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||||
|
||||
|
||||
const SUPABASE_URL = process.env.EXPO_PUBLIC_SUPABASE_URL;
|
||||
const SUPABASE_ANON_KEY = process.env.EXPO_PUBLIC_SUPABASE_ANON_KEY;
|
||||
|
||||
if (!SUPABASE_URL || !SUPABASE_ANON_KEY) {
|
||||
throw new Error('Missing Supabase environment variables. Please check your .env file.');
|
||||
}
|
||||
|
||||
export const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
|
||||
auth: {
|
||||
persistSession: true,
|
||||
storage: AsyncStorage as unknown as Storage,
|
||||
autoRefreshToken: true,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default supabase;
|
||||
|
||||