diff --git a/.github/ISSUE_TEMPLATE/issue_report.yml b/.github/ISSUE_TEMPLATE/issue_report.yml index af86644d..365afca2 100644 --- a/.github/ISSUE_TEMPLATE/issue_report.yml +++ b/.github/ISSUE_TEMPLATE/issue_report.yml @@ -75,10 +75,13 @@ body: id: version attributes: label: Streamyfin Version - description: What version of Streamyfin are you using? + description: What version of Streamyfin are you running? On a TestFlight or development build, choose "TestFlight/Development build" and include the exact version string shown in the app's Settings. options: - 0.54.1 - 0.51.0 + - 0.47.1 + - 0.30.2 + - 0.28.0 - Older - TestFlight/Development build validations: diff --git a/.github/renovate.json b/.github/renovate.json index fdbe3734..21c5b931 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -30,9 +30,17 @@ "customType": "regex", "managerFilePatterns": ["/\\.ya?ml$/"], "matchStrings": [ - "# renovate: datasource=(?\\S+) depName=(?\\S+)(?: versioning=(?\\S+))?\\s+xcode-version:\\s*[\"']?(?[^\"'\\s]+)" + "# renovate: datasource=(?\\S+) depName=(?\\S+)(?: versioning=(?\\S+))?\\s+[A-Za-z0-9._-]+:\\s*[\"']?(?[^\"'\\s]+)" ], "versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}loose{{/if}}" + }, + { + "customType": "regex", + "description": "Track the Bun version pinned in eas.json build profiles (strict JSON can't hold inline annotations)", + "managerFilePatterns": ["/(^|/)eas\\.json$/"], + "matchStrings": ["\"bun\"\\s*:\\s*\"(?[^\"]+)\""], + "datasourceTemplate": "npm", + "depNameTemplate": "bun" } ], "customDatasources": { @@ -44,22 +52,42 @@ ] } }, - "lockFileMaintenance": { - "vulnerabilityAlerts": { - "enabled": true, - "addLabels": ["security", "vulnerability"], - "assigneesFromCodeOwners": true, - "commitMessageSuffix": " [SECURITY]" + "vulnerabilityAlerts": { + "enabled": true, + "addLabels": ["security", "vulnerability"], + "assigneesFromCodeOwners": true, + "commitMessageSuffix": " [SECURITY]" + }, + "packageRules": [ + { + "description": "Expo SDK coherence: expo, react, react-native and Expo-managed modules are pinned by the Expo SDK and must move together (via `expo install --fix`), so do not raise individual update PRs β€” group them and require manual approval from the Dependency Dashboard", + "matchPackageNames": [ + "expo", + "react", + "react-dom", + "react-native", + "react-native-web", + "expo-*", + "@expo/*" + ], + "groupName": "Expo SDK", + "dependencyDashboardApproval": true }, - "packageRules": [ - { - "description": "Group minor and patch GitHub Action updates into a single PR", - "matchManagers": ["github-actions"], - "groupName": "CI dependencies", - "groupSlug": "ci-deps", - "matchUpdateTypes": ["minor", "patch", "digest", "pin"], - "automerge": true - } - ] - } + { + "description": "Group minor and patch GitHub Action updates into a single PR", + "matchManagers": ["github-actions"], + "groupName": "CI dependencies", + "groupSlug": "ci-deps", + "matchUpdateTypes": ["minor", "patch", "digest", "pin"], + "automerge": true + }, + { + "description": "androidx and other Google-hosted Maven packages resolve from Google's Maven repository (not Maven Central)", + "matchDatasources": ["maven"], + "registryUrls": [ + "https://dl.google.com/dl/android/maven2/", + "https://repo.maven.apache.org/maven2/" + ] + } + ] } diff --git a/.github/workflows/artifact-comment.yml b/.github/workflows/artifact-comment.yml index 8c7d5331..b81eeeaf 100644 --- a/.github/workflows/artifact-comment.yml +++ b/.github/workflows/artifact-comment.yml @@ -18,7 +18,7 @@ jobs: comment-artifacts: if: github.event_name == 'workflow_dispatch' || github.event_name == 'pull_request' || (github.event_name == 'workflow_run' && github.event.workflow_run.event == 'pull_request') name: πŸ“¦ Post Build Artifacts - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 permissions: contents: read pull-requests: write @@ -387,11 +387,12 @@ jobs: let status = '⏳ Pending'; let downloadLink = '*Waiting for build...*'; - // tvOS builds are temporarily disabled until feat/tv-interface - // is merged - show them as disabled instead of stuck pending. - if (target.name === 'tvOS' || target.name === 'tvOS Unsigned') { + // Signed tvOS stays disabled until EAS has tvOS provisioning + // profiles (app + TopShelf targets); non-interactive builds can't + // create them. Unsigned tvOS builds, so it flows through normally. + if (target.name === 'tvOS') { status = 'πŸ’€ Disabled'; - downloadLink = '*Disabled until feat/tv-interface is merged*'; + downloadLink = '*Disabled β€” signed tvOS needs EAS provisioning profiles*'; } else if (matchingStatus) { if (matchingStatus.conclusion === 'success' && matchingArtifact) { status = 'βœ… Complete'; @@ -450,6 +451,20 @@ jobs: commentBody += `- **Android APK**: Download and install directly on your device (enable "Install from unknown sources")\n`; commentBody += `- **iOS IPA**: Install using [AltStore](https://altstore.io/), [Sideloadly](https://sideloadly.io/), or Xcode\n\n`; commentBody += `> ⚠️ **Note**: Artifacts expire in 7 days from build date\n\n`; + + // Collapsible rundown of the build optimisations + what each + // artifact actually installs on, so testers grab the right file. + commentBody += `
\n`; + commentBody += `πŸ“¦ Build details & device compatibility\n\n`; + commentBody += `These CI builds are trimmed for size and speed. What that means for installing them:\n\n`; + commentBody += `| Artifact | Architectures | Installs on |\n`; + commentBody += `|---|---|---|\n`; + commentBody += `| πŸ€– Android Phone APK | \`arm64-v8a\` | Every 64-bit Android phone (all since ~2017). **Not** an x86_64 emulator or a 32-bit device. |\n`; + commentBody += `| πŸ“Ί Android TV APK | \`arm64-v8a\` + \`armeabi-v7a\` | Modern boxes **and** older / cheap 32-bit Android TV sticks. No x86_64. |\n`; + commentBody += `| 🍎 iOS / tvOS IPA | \`arm64\` | iPhone / Apple TV (all current devices). |\n\n`; + commentBody += `**Why no x86_64?** That slice only runs on Android emulators / Chromebooks, never a real phone or TV box β€” dropping it shrinks the APK and speeds up the build. Local \`bun run android\` is unaffected (it still builds x86_64 from \`app.json\`).\n\n`; + commentBody += `**Runners:** Android on \`ubuntu-26.04\`; iOS / tvOS on Apple Silicon (\`macos-26\`). The size/speed win comes from the ABI trim above, not the runner.\n`; + commentBody += `
\n\n`; } else { commentBody += `⏳ **Builds are starting up...** This comment will update automatically as each build completes.\n\n`; } diff --git a/.github/workflows/build-apps.yml b/.github/workflows/build-apps.yml index fd68e23a..f305fbfc 100644 --- a/.github/workflows/build-apps.yml +++ b/.github/workflows/build-apps.yml @@ -11,10 +11,19 @@ on: push: branches: [develop, master] +# Exposed to `expo prebuild` (app.config.js β†’ extra.build) so Settings can show the +# branch + commit + Actions run a CI build was made from. EAS cloud builds use +# EAS_BUILD_* instead. The run number maps a sideloaded build back to its Actions +# run (artifacts + logs) without needing Expo access. +env: + EXPO_PUBLIC_GIT_BRANCH: ${{ github.head_ref || github.ref_name }} + EXPO_PUBLIC_GIT_COMMIT: ${{ github.sha }} + EXPO_PUBLIC_GIT_RUN_NUMBER: ${{ github.run_number }} + jobs: build-android-phone: if: (!contains(github.event.head_commit.message, '[skip ci]')) - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 name: πŸ€– Build Android APK (Phone) permissions: contents: read @@ -28,12 +37,12 @@ jobs: android: false dotnet: true haskell: true - large-packages: true + large-packages: false docker-images: true swap-storage: false - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -43,31 +52,40 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-${{ runner.arch }}-bun-develop-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-bun-develop - ${{ runner.os }}-bun-develop + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | bun install --frozen-lockfile bun run submodule-reload + - name: β˜• Set up JDK 17 + # ubuntu-26.04 defaults to JDK 25, which breaks the RN/AGP native build + # (Kotlin falls back to JVM_23, the foojay toolchain + CMake configure + # fail). Pin Temurin 17 for a deterministic Android build. + uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 + with: + distribution: temurin + java-version: "17" + - name: πŸ’Ύ Cache Gradle global uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | - ~/.gradle/caches + ~/.gradle/caches/modules-2 ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-${{ runner.arch }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.os }}-gradle- + ${{ runner.os }}-${{ runner.arch }}-gradle- - name: πŸ› οΈ Generate project files run: bun run prebuild @@ -76,12 +94,16 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: android/.gradle - key: ${{ runner.os }}-android-gradle-develop-${{ hashFiles('android/**/build.gradle', 'android/gradle/wrapper/gradle-wrapper.properties') }} - restore-keys: ${{ runner.os }}-android-gradle-develop + key: ${{ runner.os }}-${{ runner.arch }}-android-gradle-develop-${{ hashFiles('android/**/build.gradle', 'android/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-${{ runner.arch }}-android-gradle-develop - name: πŸš€ Build APK env: EXPO_TV: 0 + # CI artifact ships arm64 only (phones; emulators/Chromebooks not a + # sideload target). Overrides app.json buildArchs for this build only, + # so local `bun run android` (x86_64 emulator) is unaffected. + ORG_GRADLE_PROJECT_reactNativeArchitectures: arm64-v8a run: bun run build:android:local - name: πŸ“… Set date tag @@ -97,7 +119,7 @@ jobs: build-android-tv: if: (!contains(github.event.head_commit.message, '[skip ci]')) - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 name: πŸ€– Build Android APK (TV) permissions: contents: read @@ -111,12 +133,12 @@ jobs: android: false dotnet: true haskell: true - large-packages: true + large-packages: false docker-images: true swap-storage: false - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -126,31 +148,40 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-${{ runner.arch }}-bun-develop-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-${{ runner.arch }}-bun-develop - ${{ runner.os }}-bun-develop + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | bun install --frozen-lockfile bun run submodule-reload + - name: β˜• Set up JDK 17 + # ubuntu-26.04 defaults to JDK 25, which breaks the RN/AGP native build + # (Kotlin falls back to JVM_23, the foojay toolchain + CMake configure + # fail). Pin Temurin 17 for a deterministic Android build. + uses: actions/setup-java@ad2b38190b15e4d6bdf0c97fb4fca8412226d287 # v5.3.0 + with: + distribution: temurin + java-version: "17" + - name: πŸ’Ύ Cache Gradle global uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | - ~/.gradle/caches + ~/.gradle/caches/modules-2 ~/.gradle/wrapper - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + key: ${{ runner.os }}-${{ runner.arch }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} restore-keys: | - ${{ runner.os }}-gradle- + ${{ runner.os }}-${{ runner.arch }}-gradle- - name: πŸ› οΈ Generate project files run: bun run prebuild:tv @@ -159,12 +190,15 @@ jobs: uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: android/.gradle - key: ${{ runner.os }}-android-gradle-develop-${{ hashFiles('android/**/build.gradle', 'android/gradle/wrapper/gradle-wrapper.properties') }} - restore-keys: ${{ runner.os }}-android-gradle-develop + key: ${{ runner.os }}-${{ runner.arch }}-android-gradle-develop-${{ hashFiles('android/**/build.gradle', 'android/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-${{ runner.arch }}-android-gradle-develop - name: πŸš€ Build APK env: EXPO_TV: 1 + # TV artifact keeps armeabi-v7a too: many older/cheap Android TV boxes + # and sticks are still 32-bit ARM. Drops only x86_64. CI build only. + ORG_GRADLE_PROJECT_reactNativeArchitectures: arm64-v8a,armeabi-v7a run: bun run build:android:local - name: πŸ“… Set date tag @@ -187,7 +221,7 @@ jobs: steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -197,15 +231,16 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-bun-cache + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | @@ -219,10 +254,10 @@ jobs: uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1 with: # renovate: datasource=custom.xcode depName=xcode versioning=loose - xcode-version: "26.4" + xcode-version: "26.5" - name: πŸ—οΈ Setup EAS - uses: expo/expo-github-action@b184ff86a3c926240f1b6db41764c83a01c02eef # main + uses: expo/expo-github-action@eab7a230208c952974db8c3245cfd78402c7b385 # main with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -231,7 +266,9 @@ jobs: - name: πŸš€ Build iOS app env: EXPO_TV: 0 - run: eas build -p ios --local --non-interactive + # `ci` profile (extends production, autoIncrement off): keeps CI builds out of + # the production version tier and stops them inflating the store build counter. + run: eas build -p ios --local --non-interactive --profile ci - name: πŸ“… Set date tag run: echo "DATE_TAG=$(date +%d-%m-%Y_%H-%M-%S)" >> $GITHUB_ENV @@ -252,7 +289,7 @@ jobs: steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -262,15 +299,16 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-bun-cache + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | @@ -284,7 +322,7 @@ jobs: uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1 with: # renovate: datasource=custom.xcode depName=xcode versioning=loose - xcode-version: "26.4" + xcode-version: "26.5" - name: πŸš€ Build iOS app env: @@ -302,8 +340,10 @@ jobs: retention-days: 7 build-ios-tv: - # Temporarily disabled until feat/tv-interface is merged (TV UI not ready). - # Re-enable by removing the `false &&` prefix below. + # Disabled: EAS has no provisioning profiles / distribution cert for the tvOS + # targets (app + StreamyfinTopShelf extension), so non-interactive signed + # builds fail. Set up tvOS credentials in EAS (`eas credentials`), then remove + # the `false &&` prefix below. Unsigned tvOS builds run (see job below). if: false && (!contains(github.event.head_commit.message, '[skip ci]') && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'streamyfin/streamyfin')) runs-on: macos-26 name: 🍎 Build tvOS IPA @@ -312,7 +352,7 @@ jobs: steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -322,15 +362,16 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-bun-cache + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | @@ -344,10 +385,10 @@ jobs: uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1 with: # renovate: datasource=custom.xcode depName=xcode versioning=loose - xcode-version: "26.4" + xcode-version: "26.5" - name: πŸ—οΈ Setup EAS - uses: expo/expo-github-action@b184ff86a3c926240f1b6db41764c83a01c02eef # main + uses: expo/expo-github-action@eab7a230208c952974db8c3245cfd78402c7b385 # main with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -356,7 +397,7 @@ jobs: - name: πŸš€ Build iOS app env: EXPO_TV: 1 - run: eas build -p ios --local --non-interactive + run: eas build -p ios --local --non-interactive --profile ci_tv - name: πŸ“… Set date tag run: echo "DATE_TAG=$(date +%d-%m-%Y_%H-%M-%S)" >> $GITHUB_ENV @@ -380,7 +421,7 @@ jobs: steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -390,15 +431,16 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-bun-cache + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | @@ -412,7 +454,7 @@ jobs: uses: maxim-lobanov/setup-xcode@ed7a3b1fda3918c0306d1b724322adc0b8cc0a90 # v1 with: # renovate: datasource=custom.xcode depName=xcode versioning=loose - xcode-version: "26.4" + xcode-version: "26.5" - name: πŸš€ Build iOS app env: diff --git a/.github/workflows/check-lockfile.yml b/.github/workflows/check-lockfile.yml index ae4c0fe0..efb5f221 100644 --- a/.github/workflows/check-lockfile.yml +++ b/.github/workflows/check-lockfile.yml @@ -13,13 +13,13 @@ concurrency: jobs: check-lockfile: name: πŸ” Check bun.lock and package.json consistency - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: read steps: - name: πŸ“₯ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} show-progress: false @@ -29,14 +29,17 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: | ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} + restore-keys: | + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ›‘οΈ Verify lockfile consistency run: | diff --git a/.github/workflows/ci-codeql.yml b/.github/workflows/ci-codeql.yml index ba1c08dc..b77665f5 100644 --- a/.github/workflows/ci-codeql.yml +++ b/.github/workflows/ci-codeql.yml @@ -8,11 +8,14 @@ on: schedule: - cron: '24 2 * * *' +concurrency: + group: codeql-${{ github.ref }} + cancel-in-progress: true jobs: analyze: name: πŸ”Ž Analyze with CodeQL - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: read security-events: write @@ -24,16 +27,16 @@ jobs: steps: - name: πŸ“₯ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: 🏁 Initialize CodeQL - uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: languages: ${{ matrix.language }} queries: +security-extended,security-and-quality - name: πŸ› οΈ Autobuild - uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/autobuild@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 - name: πŸ§ͺ Perform CodeQL Analysis - uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 diff --git a/.github/workflows/conflict.yml b/.github/workflows/conflict.yml index 7793851c..125ad771 100644 --- a/.github/workflows/conflict.yml +++ b/.github/workflows/conflict.yml @@ -10,14 +10,14 @@ on: jobs: label: name: 🏷️ Labeling Merge Conflicts - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 if: ${{ github.repository == 'streamyfin/streamyfin' }} permissions: contents: read pull-requests: write steps: - name: 🚩 Apply merge conflict label - uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 + uses: eps1lon/actions-label-merge-conflict@0273be72a0bbd58fcd71d0d6c02c209b50d1e5e1 # v3.1.0 with: dirtyLabel: 'βš”οΈ merge-conflict' commentOnDirty: 'This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged.' diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index feb9a00f..39883d8c 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -19,16 +19,16 @@ permissions: jobs: sync-translations: - runs-on: ubuntu-latest + runs-on: ubuntu-26.04 steps: - name: πŸ“₯ Checkout Repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 - name: 🌐 Sync Translations with Crowdin - uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2 + uses: crowdin/github-action@52aa776766211d83d975df51f3b9c53c2f8ba35f # v2.16.3 with: upload_sources: true upload_translations: true diff --git a/.github/workflows/detect-duplicate.yml b/.github/workflows/detect-duplicate.yml index 09aa2356..26da4f57 100644 --- a/.github/workflows/detect-duplicate.yml +++ b/.github/workflows/detect-duplicate.yml @@ -15,18 +15,19 @@ jobs: detect: name: πŸ” Find similar issues if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: issues: write contents: read steps: - name: πŸ“₯ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ” Detect duplicate issues run: bun scripts/detect-duplicate-issue.mjs diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 50013ba2..d36da31f 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -15,7 +15,7 @@ jobs: validate_pr_title: name: "πŸ“ Validate PR Title" if: github.event_name == 'pull_request' - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: pull-requests: write contents: read @@ -46,12 +46,12 @@ jobs: dependency-review: name: πŸ” Vulnerable Dependencies - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: read steps: - name: Checkout Repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 0 @@ -65,11 +65,10 @@ jobs: expo-doctor: name: πŸš‘ Expo Doctor Check - if: false - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 steps: - name: πŸ›’ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} submodules: recursive @@ -78,17 +77,21 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ“¦ Install dependencies (bun) run: bun install --frozen-lockfile - name: πŸš‘ Run Expo Doctor + # Re-enabled but non-blocking: surfaces doctor warnings in the logs + # without failing the gate (some checks are known-noisy for this setup). + continue-on-error: true run: bun expo-doctor code_quality: name: "πŸ” Lint & Test (${{ matrix.command }})" - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 strategy: fail-fast: false matrix: @@ -97,10 +100,11 @@ jobs: - "check" - "format" - "typecheck" + - "i18n:check" steps: - name: "πŸ“₯ Checkout PR code" - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} submodules: recursive @@ -109,12 +113,14 @@ jobs: - name: "🟒 Setup Node.js" uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 with: - node-version: '24.x' + # renovate: datasource=node-version depName=node versioning=node + node-version: "24.16.0" - name: "🍞 Setup Bun" uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: "πŸ“¦ Install dependencies" run: bun install --frozen-lockfile diff --git a/.github/workflows/notification.yml b/.github/workflows/notification.yml index cf0e4624..df9e4fa5 100644 --- a/.github/workflows/notification.yml +++ b/.github/workflows/notification.yml @@ -12,7 +12,7 @@ on: jobs: notify: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 if: github.event_name == 'pull_request' steps: - name: πŸ›ŽοΈ Notify Discord @@ -29,7 +29,7 @@ jobs: πŸ”— ${{ github.event.pull_request.html_url }} notify-on-failure: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' steps: - name: 🚨 Notify Discord on Failure diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 06dba5e3..454f8645 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,8 +22,9 @@ on: jobs: approve: name: πŸ” Approve release - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 environment: production + permissions: {} steps: - name: βœ… Release approved run: echo "Release approved for ${{ github.sha }}" @@ -31,7 +32,7 @@ jobs: build: name: πŸš€ ${{ matrix.name }} needs: approve - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: read strategy: @@ -63,7 +64,7 @@ jobs: steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 submodules: recursive @@ -72,15 +73,16 @@ jobs: - name: 🍞 Setup Bun uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - bun-version: latest + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - name: πŸ’Ύ Cache Bun dependencies uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-bun-${{ hashFiles('bun.lock') }} restore-keys: | - ${{ runner.os }}-bun-cache + ${{ runner.os }}-${{ runner.arch }}-bun- - name: πŸ“¦ Install dependencies and reload submodules run: | @@ -88,7 +90,7 @@ jobs: bun run submodule-reload - name: πŸ—οΈ Setup EAS - uses: expo/expo-github-action@b184ff86a3c926240f1b6db41764c83a01c02eef # main + uses: expo/expo-github-action@eab7a230208c952974db8c3245cfd78402c7b385 # main with: eas-version: latest token: ${{ secrets.EXPO_TOKEN }} @@ -176,13 +178,13 @@ jobs: name: πŸ“¦ Draft GitHub Release needs: build if: ${{ !cancelled() }} - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: write actions: read # required for `gh run download` to list/fetch this run's artifacts steps: - name: πŸ“₯ Checkout code - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: fetch-depth: 0 show-progress: false diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml index 9eea1fbc..2f02dcfc 100644 --- a/.github/workflows/trivy-scan.yml +++ b/.github/workflows/trivy-scan.yml @@ -21,27 +21,17 @@ concurrency: jobs: trivy: name: πŸ”Ž Filesystem scan - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: contents: read security-events: write # upload SARIF to code scanning steps: - name: πŸ“₯ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - # Rotate the DB cache weekly (matches the scheduled scan): cache hits within the week - # instead of a fresh immutable entry per run, still refreshing the DB every week. - - name: πŸ—“οΈ Compute weekly Trivy cache key - id: trivy-cache-key - run: echo "value=trivy-db-${{ runner.os }}-$(date -u +%G-%V)" >> "$GITHUB_OUTPUT" - - - name: πŸ’Ύ Cache Trivy vulnerability DB - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: ~/.cache/trivy - key: ${{ steps.trivy-cache-key.outputs.value }} - restore-keys: trivy-db-${{ runner.os }}- + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + # Trivy's own action caches the vulnerability DB + binary internally + # (cache-trivy-* / trivy-binary-* entries), so no manual ~/.cache/trivy + # step is needed β€” it only duplicated the cache. - name: πŸ”Ž Run Trivy filesystem scan uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 with: @@ -54,7 +44,7 @@ jobs: output: trivy-results.sarif - name: πŸ“€ Upload results to code scanning - uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0 + uses: github/codeql-action/upload-sarif@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 with: sarif_file: trivy-results.sarif category: trivy-fs diff --git a/.github/workflows/update-issue-form.yml b/.github/workflows/update-issue-form.yml index 7cc32197..0754735e 100644 --- a/.github/workflows/update-issue-form.yml +++ b/.github/workflows/update-issue-form.yml @@ -1,67 +1,103 @@ -name: πŸ› Update Bug Report Template +name: πŸ› Update Issue Form Versions on: release: - types: [published] # Run on every published release on any branch + # Only full releases populate the dropdown (no drafts/prereleases). + types: [released] + schedule: + - cron: "0 3 * * 1" # Weekly safety net (Mondays 03:00 UTC) in case a release event was missed + workflow_dispatch: +# Fixed group so a release event and the weekly cron can't race on the same +# ci/update-issue-form branch β€” runs queue instead of force-pushing over each other. concurrency: - group: update-issue-form-${{ github.event.release.tag_name || github.run_id }} - cancel-in-progress: true + group: update-issue-form + cancel-in-progress: false + +permissions: + contents: read jobs: - update-bug-report: + update-issue-form: + name: πŸ”’ Populate version dropdown + runs-on: ubuntu-26.04 permissions: contents: write pull-requests: write - issues: write - runs-on: ubuntu-24.04 - steps: - name: πŸ“₯ Checkout repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: "🟒 Setup Node.js" - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: - node-version: '24.x' - cache: 'npm' + # On `release` events GITHUB_SHA is the tagged commit β€” without this the + # script would regenerate the form from the tag's (stale) copy and the bot + # PR would revert any form edits made on develop since that release. + ref: develop - - name: πŸ” Extract minor version from app.json - id: minor - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # main + - name: 🍞 Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 with: - result-encoding: string - script: | - const fs = require('fs-extra'); - const semver = require('semver'); - const content = fs.readJsonSync('./app.json'); - const version = content.expo.version; - const minorVersion = semver.minor(version); - return minorVersion.toString(); + # renovate: datasource=npm depName=bun + bun-version: "1.3.14" - - name: πŸ“ Update bug report version - uses: ShaMan123/gha-populate-form-version@be012141ca560dbb92156e3fe098c46035f6260d #v2.0.5 - with: - semver: '^0.${{ steps.minor.outputs.result }}.0' - dry_run: no-push + - name: πŸ”’ Populate version dropdown from GitHub releases + id: populate + run: bun scripts/update-issue-form.mjs + env: + GH_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ github.repository }} - - name: βš™οΈ Update bug report node version dropdown - uses: ShaMan123/gha-populate-form-version@be012141ca560dbb92156e3fe098c46035f6260d #v2.0.5 - with: - dropdown: _node_version - package: node - semver: '>=24.0.0' - dry_run: no-push - - - name: πŸ“¬ Commit and create pull request + - name: πŸ“¬ Create pull request + id: cpr uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 with: - add-paths: .github/ISSUE_TEMPLATE/bug_report.yml - branch: ci-update-bug-report + add-paths: .github/ISSUE_TEMPLATE/issue_report.yml + branch: ci/update-issue-form base: develop delete-branch: true labels: βš™οΈ ci, πŸ€– github-actions - title: 'chore(): Update bug report template to match release version' + commit-message: "chore: update issue form version dropdown" + title: "chore: update issue form version dropdown" + # Follows .github/pull_request_template.md so the bot PR isn't flagged by PR validation. body: | - Automated update to `.github/ISSUE_TEMPLATE/bug_report.yml` - Triggered by workflow run [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) + # πŸ“¦ Pull Request + + ## πŸ“ Description + + Automated update of the **Streamyfin Version** dropdown in `.github/ISSUE_TEMPLATE/issue_report.yml`, populated from the latest published GitHub releases by `scripts/update-issue-form.mjs`. + + **Version dropdown now lists:** ${{ steps.populate.outputs.versions }} + + Triggered by `${{ github.event_name }}`${{ github.event.release.tag_name && format(' β€” release {0}', github.event.release.tag_name) || '' }} Β· [run ${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}). + + ## 🏷️ Ticket / Issue + + N/A β€” automated maintenance. + + ### πŸ–ΌοΈ Screenshots / GIFs (if UI) + + N/A β€” issue-template metadata only, no app UI. + + ## βœ… Checklist + + - [x] I’ve read the [contribution guidelines](CONTRIBUTING.md) + - [x] Verified that changes behave as expected for all platforms + - [x] Code passes lint/formatting and type checks (`tsc`/`biome`) + - [x] No secrets, hardcoded credentials, or private config files are included + - [x] I've declared if AI was used to assist with this PR (by uncommenting the line at the bottom, or not) + + ## πŸ” Testing Instructions + + N/A β€” generated by CI from published releases; review the dropdown diff in `issue_report.yml`. + + - name: πŸ”€ Enable auto-merge + if: steps.cpr.outputs.pull-request-operation == 'created' + env: + GH_TOKEN: ${{ github.token }} + # Known limitation: PRs created with GITHUB_TOKEN don't trigger CI workflows + # (GitHub anti-recursion), so the required checks stay "Expected" until a + # maintainer kicks them (close/reopen the PR, or push an empty commit). + # Auto-merge is still worth enabling: once checks run and reviews land, + # the PR merges itself. + run: | + gh pr merge --squash --auto "${{ steps.cpr.outputs.pull-request-number }}" \ + || echo "::warning::Could not enable auto-merge β€” enable 'Allow auto-merge' in repo settings (and branch protection); merge the PR manually for now." diff --git a/GLOBAL_MODAL_GUIDE.md b/GLOBAL_MODAL_GUIDE.md index 5426ca72..11a05f10 100644 --- a/GLOBAL_MODAL_GUIDE.md +++ b/GLOBAL_MODAL_GUIDE.md @@ -143,14 +143,6 @@ interface ModalOptions { } ``` -## Examples - -See `components/ExampleGlobalModalUsage.tsx` for comprehensive examples including: -- Simple content modal -- Modal with custom snap points -- Complex component in modal -- Success/error modals triggered from functions - ## Default Styling The modal uses these default styles (can be overridden via options): diff --git a/app.config.js b/app.config.js index 96bbd8ea..d29ddc32 100644 --- a/app.config.js +++ b/app.config.js @@ -1,3 +1,47 @@ +const { execFileSync } = require("node:child_process"); + +// Build metadata, injected into `extra.build` and read at runtime via +// expo-constants (see utils/version.ts). Sources in priority order: +// EAS cloud build β†’ GitHub Actions β†’ explicit EXPO_PUBLIC_* β†’ local git β†’ null. +const git = (args) => { + try { + return execFileSync("git", args, { stdio: ["ignore", "pipe", "ignore"] }) + .toString() + .trim(); + } catch { + return null; + } +}; + +const buildMeta = { + commit: + ( + process.env.EAS_BUILD_GIT_COMMIT_HASH || + process.env.GITHUB_SHA || + process.env.EXPO_PUBLIC_GIT_COMMIT || + git(["rev-parse", "HEAD"]) || + "" + ).slice(0, 7) || null, + branch: + process.env.EAS_BUILD_GIT_BRANCH || + process.env.GITHUB_HEAD_REF || + process.env.GITHUB_REF_NAME || + process.env.EXPO_PUBLIC_GIT_BRANCH || + git(["rev-parse", "--abbrev-ref", "HEAD"]) || + null, + profile: + process.env.EAS_BUILD_PROFILE || + process.env.EXPO_PUBLIC_BUILD_PROFILE || + null, + // GitHub Actions run number (#2098) β€” lets anyone map a sideloaded CI build back + // to its Actions run (artifacts + logs) without Expo access. Null outside CI. + runNumber: + process.env.GITHUB_RUN_NUMBER || + process.env.EXPO_PUBLIC_GIT_RUN_NUMBER || + null, + builtAt: new Date().toISOString(), +}; + module.exports = ({ config }) => { if (process.env.EXPO_TV !== "1") { config.plugins.push("expo-background-task"); @@ -22,6 +66,8 @@ module.exports = ({ config }) => { androidConfig.googleServicesFile = process.env.GOOGLE_SERVICES_JSON; } + config.extra = { ...config.extra, build: buildMeta }; + return { ...(Object.keys(androidConfig).length > 0 && { android: androidConfig }), ...config, diff --git a/app.json b/app.json index 296d674d..e7095490 100644 --- a/app.json +++ b/app.json @@ -107,6 +107,9 @@ ], "expo-localization", "expo-asset", + "expo-audio", + "expo-image", + "expo-sharing", [ "react-native-edge-to-edge", { diff --git a/augmentations/index.ts b/augmentations/index.ts index abec02c9..0c193e83 100644 --- a/augmentations/index.ts +++ b/augmentations/index.ts @@ -1,4 +1,3 @@ export * from "./api"; export * from "./mmkv"; export * from "./number"; -export * from "./string"; diff --git a/augmentations/number.ts b/augmentations/number.ts index bef44ac5..c8146d65 100644 --- a/augmentations/number.ts +++ b/augmentations/number.ts @@ -3,7 +3,6 @@ declare global { bytesToReadable(decimals?: number): string; secondsToMilliseconds(): number; minutesToMilliseconds(): number; - hoursToMilliseconds(): number; } } @@ -28,8 +27,4 @@ Number.prototype.minutesToMilliseconds = function () { return this.valueOf() * (60).secondsToMilliseconds(); }; -Number.prototype.hoursToMilliseconds = function () { - return this.valueOf() * (60).minutesToMilliseconds(); -}; - export {}; diff --git a/augmentations/string.ts b/augmentations/string.ts deleted file mode 100644 index f4a50b55..00000000 --- a/augmentations/string.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare global { - interface String { - toTitle(): string; - } -} - -String.prototype.toTitle = function () { - return this.replaceAll("_", " ").replace( - /\w\S*/g, - (text) => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase(), - ); -}; - -export {}; diff --git a/bun.lock b/bun.lock index cf584477..7f6baa66 100644 --- a/bun.lock +++ b/bun.lock @@ -7,9 +7,9 @@ "dependencies": { "@bottom-tabs/react-navigation": "1.2.0", "@douglowder/expo-av-route-picker-view": "^0.0.5", - "@expo/metro-runtime": "~56.0.13", + "@expo/metro-runtime": "~56.0.15", "@expo/react-native-action-sheet": "^4.1.1", - "@expo/ui": "~56.0.14", + "@expo/ui": "~56.0.17", "@expo/vector-icons": "^15.0.3", "@gorhom/bottom-sheet": "5.2.14", "@jellyfin/sdk": "^0.13.0", @@ -22,35 +22,35 @@ "@tanstack/react-query": "5.100.14", "@tanstack/react-query-persist-client": "^5.100.14", "axios": "^1.7.9", - "expo": "~56.0.6", + "expo": "~56.0.11", "expo-application": "~56.0.3", - "expo-asset": "~56.0.15", - "expo-audio": "~56.0.11", - "expo-background-task": "~56.0.15", + "expo-asset": "~56.0.17", + "expo-audio": "~56.0.12", + "expo-background-task": "~56.0.18", "expo-blur": "~56.0.3", "expo-brightness": "~56.0.5", - "expo-build-properties": "~56.0.15", - "expo-camera": "~56.0.7", - "expo-constants": "~56.0.16", + "expo-build-properties": "~56.0.18", + "expo-camera": "~56.0.8", + "expo-constants": "~56.0.18", "expo-crypto": "~56.0.4", - "expo-dev-client": "~56.0.16", + "expo-dev-client": "~56.0.20", "expo-device": "~56.0.4", - "expo-font": "~56.0.5", + "expo-font": "~56.0.6", "expo-haptics": "~56.0.3", - "expo-image": "~56.0.9", + "expo-image": "~56.0.11", "expo-linear-gradient": "~56.0.4", - "expo-linking": "~56.0.12", + "expo-linking": "~56.0.14", "expo-localization": "~56.0.6", - "expo-location": "~56.0.14", - "expo-notifications": "~56.0.14", - "expo-router": "~56.2.7", + "expo-location": "~56.0.17", + "expo-notifications": "~56.0.17", + "expo-router": "~56.2.10", "expo-screen-orientation": "~56.0.5", "expo-secure-store": "~56.0.4", - "expo-sharing": "~56.0.14", + "expo-sharing": "~56.0.17", "expo-splash-screen": "~56.0.10", "expo-status-bar": "~56.0.4", "expo-system-ui": "~56.0.5", - "expo-task-manager": "~56.0.15", + "expo-task-manager": "~56.0.18", "expo-web-browser": "~56.0.5", "i18next": "^26.3.0", "jotai": "2.20.0", @@ -105,14 +105,15 @@ "@react-native-tvos/config-tv": "0.1.6", "@types/jest": "29.5.14", "@types/lodash": "4.17.24", + "@types/node": "^18.19.130", "@types/react": "~19.2.10", "@types/react-test-renderer": "19.1.0", "cross-env": "10.1.0", - "expo-doctor": "1.19.7", + "expo-doctor": "1.19.9", "husky": "9.1.7", "lint-staged": "17.0.5", "react-test-renderer": "19.2.3", - "typescript": "5.9.3", + "typescript": "6.0.3", }, }, }, @@ -189,7 +190,7 @@ "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="], - "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA=="], + "@babel/plugin-transform-arrow-functions": ["@babel/plugin-transform-arrow-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ=="], "@babel/plugin-transform-async-generator-functions": ["@babel/plugin-transform-async-generator-functions@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-remap-async-to-generator": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA=="], @@ -197,11 +198,11 @@ "@babel/plugin-transform-block-scoping": ["@babel/plugin-transform-block-scoping@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ=="], - "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.27.1", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA=="], + "@babel/plugin-transform-class-properties": ["@babel/plugin-transform-class-properties@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA=="], "@babel/plugin-transform-class-static-block": ["@babel/plugin-transform-class-static-block@7.29.7", "", { "dependencies": { "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.12.0" } }, "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A=="], - "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.28.4", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-compilation-targets": "^7.27.2", "@babel/helper-globals": "^7.28.0", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-replace-supers": "^7.27.1", "@babel/traverse": "^7.28.4" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA=="], + "@babel/plugin-transform-classes": ["@babel/plugin-transform-classes@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-globals": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g=="], "@babel/plugin-transform-destructuring": ["@babel/plugin-transform-destructuring@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg=="], @@ -217,13 +218,13 @@ "@babel/plugin-transform-named-capturing-groups-regex": ["@babel/plugin-transform-named-capturing-groups-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ=="], - "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA=="], + "@babel/plugin-transform-nullish-coalescing-operator": ["@babel/plugin-transform-nullish-coalescing-operator@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg=="], "@babel/plugin-transform-object-rest-spread": ["@babel/plugin-transform-object-rest-spread@7.29.7", "", { "dependencies": { "@babel/helper-compilation-targets": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-transform-destructuring": "^7.29.7", "@babel/plugin-transform-parameters": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A=="], "@babel/plugin-transform-optional-catch-binding": ["@babel/plugin-transform-optional-catch-binding@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng=="], - "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-BQmKPPIuc8EkZgNKsv0X4bPmOoayeu4F1YCwx2/CfmDSXDbp7GnzlUH+/ul5VGfRg1AoFPsrIThlEBj2xb4CAg=="], + "@babel/plugin-transform-optional-chaining": ["@babel/plugin-transform-optional-chaining@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ=="], "@babel/plugin-transform-parameters": ["@babel/plugin-transform-parameters@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g=="], @@ -247,13 +248,13 @@ "@babel/plugin-transform-runtime": ["@babel/plugin-transform-runtime@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "babel-plugin-polyfill-corejs2": "^0.4.14", "babel-plugin-polyfill-corejs3": "^0.13.0", "babel-plugin-polyfill-regenerator": "^0.6.5", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xmAscdE/AsqRW7vutbPNoUmu/nF5SrLKPs7aoJgEjo35lLKA/Bc0i2rMv/hr1+Y0o1bQCiVtith3u2vdgRL39Q=="], - "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ=="], + "@babel/plugin-transform-shorthand-properties": ["@babel/plugin-transform-shorthand-properties@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg=="], - "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg=="], + "@babel/plugin-transform-template-literals": ["@babel/plugin-transform-template-literals@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA=="], "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="], - "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.27.1", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw=="], + "@babel/plugin-transform-unicode-regex": ["@babel/plugin-transform-unicode-regex@7.29.7", "", { "dependencies": { "@babel/helper-create-regexp-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA=="], "@babel/preset-typescript": ["@babel/preset-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ=="], @@ -295,15 +296,15 @@ "@expo-google-fonts/material-symbols": ["@expo-google-fonts/material-symbols@0.4.38", "", {}, "sha512-IJkBtN1o8u9BW5fvSii1MyHPQ7Q0HxbWcVBvOrOzgMLpVtZw7R2w94wBTVR7kZwv3w1JNTESMmLA5Sqn1+Z36A=="], - "@expo/cli": ["@expo/cli@56.1.12", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.8", "@expo/devcert": "^1.2.1", "@expo/env": "~2.3.0", "@expo/image-utils": "^0.10.1", "@expo/inline-modules": "^0.0.10", "@expo/json-file": "^10.2.0", "@expo/log-box": "^56.0.12", "@expo/metro": "~56.0.0", "@expo/metro-config": "~56.0.13", "@expo/metro-file-map": "^56.0.3", "@expo/osascript": "^2.6.0", "@expo/package-manager": "^1.12.0", "@expo/plist": "^0.7.0", "@expo/prebuild-config": "^56.0.13", "@expo/require-utils": "^56.1.3", "@expo/router-server": "^56.0.12", "@expo/schema-utils": "^56.0.0", "@expo/spawn-async": "^1.8.0", "@expo/ws-tunnel": "^1.0.1", "@expo/xcpretty": "^4.4.4", "@react-native/dev-middleware": "0.85.3", "accepts": "^1.3.8", "arg": "^5.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^56.0.4", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.4", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "main.js" } }, "sha512-Ya/13E1yDx1oAuPw5MDmqzIGyzwSs7KSr1EjgSObOF0VO0GD9jqJjvjOiwurjScLUfxcGZQgq23UzMlBVHwdvA=="], + "@expo/cli": ["@expo/cli@56.1.16", "", { "dependencies": { "@expo/code-signing-certificates": "^0.0.6", "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.9", "@expo/devcert": "^1.2.1", "@expo/env": "~2.3.0", "@expo/image-utils": "^0.10.1", "@expo/inline-modules": "^0.0.12", "@expo/json-file": "^10.2.0", "@expo/log-box": "^56.0.13", "@expo/metro": "~56.0.0", "@expo/metro-config": "~56.0.14", "@expo/metro-file-map": "^56.0.3", "@expo/osascript": "^2.6.0", "@expo/package-manager": "^1.12.1", "@expo/plist": "^0.7.0", "@expo/prebuild-config": "^56.0.16", "@expo/require-utils": "^56.1.3", "@expo/router-server": "^56.0.14", "@expo/schema-utils": "^56.0.0", "@expo/spawn-async": "^1.8.0", "@expo/ws-tunnel": "^2.0.0", "@expo/xcpretty": "^4.4.4", "@react-native/dev-middleware": "0.85.3", "accepts": "^1.3.8", "arg": "^5.0.2", "bplist-creator": "0.1.0", "bplist-parser": "^0.3.1", "chalk": "^4.0.0", "ci-info": "^3.3.0", "compression": "^1.7.4", "connect": "^3.7.0", "debug": "^4.3.4", "dnssd-advertise": "^1.1.4", "expo-server": "^56.0.5", "fetch-nodeshim": "^0.4.10", "getenv": "^2.0.0", "glob": "^13.0.0", "lan-network": "^0.2.1", "multitars": "^1.0.0", "node-forge": "^1.3.3", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "picomatch": "^4.0.4", "pretty-format": "^29.7.0", "progress": "^2.0.3", "prompts": "^2.3.2", "resolve-from": "^5.0.0", "semver": "^7.6.0", "send": "^0.19.0", "slugify": "^1.3.4", "stacktrace-parser": "^0.1.10", "structured-headers": "^0.4.1", "terminal-link": "^2.1.1", "toqr": "^0.1.1", "wrap-ansi": "^7.0.0", "ws": "^8.12.1", "zod": "^3.25.76" }, "peerDependencies": { "expo": "*", "expo-router": "*", "react-native": "*" }, "optionalPeers": ["expo-router", "react-native"], "bin": { "expo-internal": "main.js" } }, "sha512-VBQn0mqAwc67b9Cn0RVXyeodghomAx5xGRhA/bXaQzuxDjMQk0zIOb6pXMZX7yiIwJW66UZt/zQiJNSv6aWJYw=="], "@expo/code-signing-certificates": ["@expo/code-signing-certificates@0.0.6", "", { "dependencies": { "node-forge": "^1.3.3" } }, "sha512-iNe0puxwBNEcuua9gmTGzq+SuMDa0iATai1FlFTMHJ/vUmKvN/V//drXoLJkVb5i5H3iE/n/qIJxyoBnXouD0w=="], "@expo/config": ["@expo/config@56.0.9", "", { "dependencies": { "@expo/config-plugins": "~56.0.8", "@expo/config-types": "^56.0.5", "@expo/json-file": "^10.2.0", "@expo/require-utils": "^56.1.3", "deepmerge": "^4.3.1", "getenv": "^2.0.0", "glob": "^13.0.0", "resolve-workspace-root": "^2.0.0", "semver": "^7.6.0", "slugify": "^1.3.4" } }, "sha512-/lqFeWGSrhpKJVP8tTN8LjuoIe8u8q2w7FzBL0C+wHgl+WM8l1qUIEYWy/sMvsG/NbpUIUsDHJRhQvOkU58eIw=="], - "@expo/config-plugins": ["@expo/config-plugins@56.0.8", "", { "dependencies": { "@expo/config-types": "^56.0.5", "@expo/json-file": "~10.2.0", "@expo/plist": "^0.7.0", "@expo/require-utils": "^56.1.3", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-phTuyBhgVLfqUHMjQkAfRtbyoY6yTxoKja1awtpVnEkoJDxPJuXx1KX5uvq1eZtt4bJQ08OBJ6P95INqRSHpRg=="], + "@expo/config-plugins": ["@expo/config-plugins@56.0.9", "", { "dependencies": { "@expo/config-types": "^56.0.6", "@expo/json-file": "~10.2.0", "@expo/plist": "^0.7.0", "@expo/require-utils": "^56.1.3", "@expo/sdk-runtime-versions": "^1.0.0", "chalk": "^4.1.2", "debug": "^4.3.5", "getenv": "^2.0.0", "glob": "^13.0.0", "semver": "^7.5.4", "slugify": "^1.6.6", "xcode": "^3.0.1", "xml2js": "0.6.0" } }, "sha512-/6a/S9USwx8OC9tGjHxbviLFiBHyueN3aoNWMLvWDEJoZ1CIVW800ZBzwXq/FYNK2qzcN1LxFmQtzD1zeFQKNA=="], - "@expo/config-types": ["@expo/config-types@56.0.5", "", {}, "sha512-GsAHO/MwW9ZRdgnmyfRXqVGLCP/zejD6rWnp5OROp8mBGRObKm4HfrjlUyT1skjMwCj1OrURx9ZfIc6yeBAkIA=="], + "@expo/config-types": ["@expo/config-types@56.0.6", "", {}, "sha512-4Y6Aum5J4Re5NnxGVofRNe1aDwUBOmWhQYkynZsqzRtX/zEA1ADUeyHXuEckv9YD9djiyT7bKtLt5gKL3mA6VQ=="], "@expo/devcert": ["@expo/devcert@1.2.1", "", { "dependencies": { "@expo/sudo-prompt": "^9.3.1", "debug": "^3.1.0" } }, "sha512-qC4eaxmKMTmJC2ahwyui6ud8f3W60Ss7pMkpBq40Hu3zyiAaugPXnZ24145U7K36qO9UHdZUVxsCvIpz2RYYCA=="], @@ -313,41 +314,41 @@ "@expo/env": ["@expo/env@2.3.0", "", { "dependencies": { "chalk": "^4.0.0", "debug": "^4.3.4", "getenv": "^2.0.0" } }, "sha512-9HnnIbzwTTdbwSjNLXTk0fPm9ZwMJ7c1/31tsni8HZ8Q62KzYCyspahH+V365vg5J6lr001DzNwBxVWSaYCQLg=="], - "@expo/expo-modules-macros-plugin": ["@expo/expo-modules-macros-plugin@0.0.9", "", {}, "sha512-odai6D7ng/gA7At8ukFcWcauNEeDdyVqzVPbQxDkyU2NTJ4kgphA4I5iigS5C4LXFicSIzEt2nzdlLM8sjsTdA=="], + "@expo/expo-modules-macros-plugin": ["@expo/expo-modules-macros-plugin@0.2.2", "", {}, "sha512-4IMzPDIo/VOXREQjsJtliSfqYVZvfzU2SLFS/9sKMWF848S8CHx+e/E+Vf0TcMvpWCCKX5umyqxb13KJJ+YUzg=="], - "@expo/fingerprint": ["@expo/fingerprint@0.19.3", "", { "dependencies": { "@expo/env": "^2.3.0", "@expo/spawn-async": "^1.8.0", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-w9Au2IVrtc0Ct+WRa05DVHGNHXYq6VyPZWuFP+5x055OeZ5q6k5Yg+aJ1gfShmjdOhDftRcsvmWmTdTZlWaTZw=="], + "@expo/fingerprint": ["@expo/fingerprint@0.19.4", "", { "dependencies": { "@expo/env": "^2.3.0", "@expo/spawn-async": "^1.8.0", "arg": "^5.0.2", "chalk": "^4.1.2", "debug": "^4.3.4", "getenv": "^2.0.0", "glob": "^13.0.0", "ignore": "^5.3.1", "minimatch": "^10.2.2", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "bin": { "fingerprint": "bin/cli.js" } }, "sha512-PsowRlO8+S7JlO8go7yhNEXp7sqlsWDE2AlCwoss7zH0dcajXFo74Fy0KdXEc4UXK7kKoHD37oDgsZ8aHSLr7A=="], "@expo/image-utils": ["@expo/image-utils@0.10.1", "", { "dependencies": { "@expo/require-utils": "^56.1.3", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "getenv": "^2.0.0", "jimp-compact": "0.16.1", "parse-png": "^2.1.0", "semver": "^7.6.0" } }, "sha512-YDeefvmYdihS7Wp3ESDUVnOgOSWmj2Cczm9lVNDdm4MqQLdAKm/LPYg83HtFQPfefRlAxyHrQR/O9kIXN9C1Wg=="], - "@expo/inline-modules": ["@expo/inline-modules@0.0.10", "", { "dependencies": { "@expo/config-plugins": "~56.0.8" } }, "sha512-DKEfq877UTAmL/gOT5aFhlLNDg/EVmTSca7JQMKDGR6mjFSAcrmQf4GJNsi6ztiaqj6cTnIfoSz0hAYdnr6RJQ=="], + "@expo/inline-modules": ["@expo/inline-modules@0.0.12", "", { "dependencies": { "@expo/config-plugins": "~56.0.9" } }, "sha512-SNIZr/HWfIQPTZBwmukItxpc7ws1SgMUywYq1dnQvDknQDjJcuWAasIRFUjsK15yQ1xb4G5CP7VHtbN3V4lENg=="], "@expo/json-file": ["@expo/json-file@10.2.0", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "json5": "^2.2.3" } }, "sha512-S6XzKe3R9GQeHiUPXc3xJjOv2VJhOEwFYf7xdC2z2cUqt3kZJ9mSO877sNQloVdnW/SUCtPY3bexlM7nwq+CAQ=="], "@expo/local-build-cache-provider": ["@expo/local-build-cache-provider@56.0.8", "", { "dependencies": { "@expo/config": "~56.0.9", "chalk": "^4.1.2" } }, "sha512-UsuXwpNi57MNhzZ3be4XThc8xW6nzk3Wu37s1+2qcfZGeJcMLKDFfwO6n8YXeIiGlCsOi0Ee1rsTdgjrKt/YJQ=="], - "@expo/log-box": ["@expo/log-box@56.0.12", "", { "dependencies": { "@expo/dom-webview": "^56.0.5", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-budE6AGmJbpOJfGSOz+JVP3+FevElT82IEIg+ukQ4gZpW/dGO7QX1unFjanKdSaYgudBwJ4FCFGMwWhW/1tXVQ=="], + "@expo/log-box": ["@expo/log-box@56.0.13", "", { "dependencies": { "@expo/dom-webview": "^56.0.5", "anser": "^1.4.9", "stacktrace-parser": "^0.1.10" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-QWRZSpWPyjkDLVQio4R7oAzg/Av2MOt/DciFkfjr8qQ3qxGVn1Rt1oHP/80hvcWDcHFV7N6PqpyxRXw6nbxzKQ=="], "@expo/metro": ["@expo/metro@56.0.0", "", { "dependencies": { "metro": "0.84.4", "metro-babel-transformer": "0.84.4", "metro-cache": "0.84.4", "metro-cache-key": "0.84.4", "metro-config": "0.84.4", "metro-core": "0.84.4", "metro-file-map": "0.84.4", "metro-minify-terser": "0.84.4", "metro-resolver": "0.84.4", "metro-runtime": "0.84.4", "metro-source-map": "0.84.4", "metro-symbolicate": "0.84.4", "metro-transform-plugins": "0.84.4", "metro-transform-worker": "0.84.4" } }, "sha512-5gIgQHtEpjjvsjKfVtIv23a98LLRV0/y07PDShEwYSytAMlE3FSF8RHXqtHc1sUJL6dn7hnuIBpIbrLXXuVi0A=="], - "@expo/metro-config": ["@expo/metro-config@56.0.13", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~56.0.9", "@expo/env": "~2.3.0", "@expo/json-file": "~10.2.0", "@expo/metro": "~56.0.0", "@expo/require-utils": "^56.1.3", "@expo/spawn-async": "^1.8.0", "@jridgewell/gen-mapping": "^0.3.13", "@jridgewell/remapping": "^2.3.5", "@jridgewell/sourcemap-codec": "^1.5.5", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.33.3", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "msgpackr": "^2.0.1", "picomatch": "^4.0.4", "postcss": "^8.5.14", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-OPyNYiex/6Ms8zT2POdIZsLhcAZYk7O+yJvpz5uG/4QRA7aiESfCy1I+0YHewMlR4P1YQeyxIrfTurs6m9xfZA=="], + "@expo/metro-config": ["@expo/metro-config@56.0.14", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.20.0", "@babel/generator": "^7.20.5", "@expo/config": "~56.0.9", "@expo/env": "~2.3.0", "@expo/json-file": "~10.2.0", "@expo/metro": "~56.0.0", "@expo/require-utils": "^56.1.3", "@expo/spawn-async": "^1.8.0", "@jridgewell/gen-mapping": "^0.3.13", "@jridgewell/remapping": "^2.3.5", "@jridgewell/sourcemap-codec": "^1.5.5", "browserslist": "^4.25.0", "chalk": "^4.1.0", "debug": "^4.3.2", "getenv": "^2.0.0", "glob": "^13.0.0", "hermes-parser": "^0.33.3", "jsc-safe-url": "^0.2.4", "lightningcss": "^1.30.1", "picomatch": "^4.0.4", "postcss": "^8.5.14", "resolve-from": "^5.0.0" }, "peerDependencies": { "expo": "*" }, "optionalPeers": ["expo"] }, "sha512-O3CIHruaTJhswPAf/nf3i8QQ3f2jl+mEwSea1eb3khuplabdy/wTQz+JvHN8VGUFyg7JKwUGU1QfO6T3JiSQqA=="], "@expo/metro-file-map": ["@expo/metro-file-map@56.0.3", "", { "dependencies": { "debug": "^4.3.4", "fb-watchman": "^2.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } }, "sha512-5OGW3z8LgEYgMJOR7F3pC8llFLkb1fVqwAewbCl6S4Vkha8AFQMwOjT+9Wbka+V4rmpljpGqOnMhF4xZbD961w=="], - "@expo/metro-runtime": ["@expo/metro-runtime@56.0.13", "", { "dependencies": { "@expo/log-box": "^56.0.12", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-aMaFa/RPYm2iQoyYOB5q8AxDmWvf4E2yFbZ6rmBIQWaIPDdixGVUlLQeV8DlDAfZ/j+pNYO7l5M+774WbgkTgg=="], + "@expo/metro-runtime": ["@expo/metro-runtime@56.0.15", "", { "dependencies": { "@expo/log-box": "^56.0.13", "anser": "^1.4.9", "pretty-format": "^29.7.0", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-dom": "*", "react-native": "*" }, "optionalPeers": ["react-dom"] }, "sha512-WIWeVsL6kCSB57oYZdUA4MTkH7c67UFMIjdNoQzKXwxZYwBFE/xL2cGPDC3z8RWt0femzJTVxAVZUOW/hiqRzA=="], "@expo/osascript": ["@expo/osascript@2.6.0", "", { "dependencies": { "@expo/spawn-async": "^1.8.0" } }, "sha512-QvqDBlJXa8CS2vRORJ4wEflY1m0vVI07uSJdIRgBrLxRPBcsrXxrtU7+wXRXMqfq9zLwNP9XbvRsXF2omoDylg=="], - "@expo/package-manager": ["@expo/package-manager@1.12.0", "", { "dependencies": { "@expo/json-file": "^10.2.0", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-SWr6093nwBjn94cvElsYZNUnhvs+XtUatUz3h0vAn0IbaWG0B6l/V5ZfOBptX/xq6rMpFG5ibIf/eckLSXw8Gg=="], + "@expo/package-manager": ["@expo/package-manager@1.12.1", "", { "dependencies": { "@expo/json-file": "^10.2.0", "@expo/spawn-async": "^1.8.0", "chalk": "^4.0.0", "npm-package-arg": "^11.0.0", "ora": "^3.4.0", "resolve-workspace-root": "^2.0.0" } }, "sha512-fQLiFAcFRWF53mtuLK32SUJQ1ahhrTcBZPZPedYTiUT5ha5FF+UO6bPtCc0Y/hgj0/m3HCGBAuSHjbg2kI9oPQ=="], "@expo/plist": ["@expo/plist@0.7.0", "", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-vrpryU1GoqSIRNqRB2D3IjXDmzNYfiQpEF6AH/xknlD7eiYmEDt3mb26V7cLcedcPG8PY/1xWHdBXVQJfEAh6Q=="], - "@expo/prebuild-config": ["@expo/prebuild-config@56.0.13", "", { "dependencies": { "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.8", "@expo/config-types": "^56.0.5", "@expo/image-utils": "^0.10.1", "@expo/json-file": "^10.2.0", "@react-native/normalize-colors": "0.85.3", "debug": "^4.3.1", "expo-modules-autolinking": "~56.0.13", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-caR1karpDasbNmM+LrcHKZrSnyEYdmxm7kedq+WjiuZg+9XAW5sbEjojo2i9Dq6cfbDJPyr7I0yEprLabnvmpA=="], + "@expo/prebuild-config": ["@expo/prebuild-config@56.0.16", "", { "dependencies": { "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.9", "@expo/config-types": "^56.0.6", "@expo/image-utils": "^0.10.1", "@expo/json-file": "^10.2.0", "@react-native/normalize-colors": "0.85.3", "debug": "^4.3.1", "expo-modules-autolinking": "~56.0.16", "resolve-from": "^5.0.0", "semver": "^7.6.0" } }, "sha512-ce9ENfPWO4WUWUVQz0OaqL3KYZ7YofP8O35ncnn7CHCaKwQ7BqxcCGJbh+qvP1UjlWeNB3CjHPrXXJ3bnZwlJw=="], "@expo/react-native-action-sheet": ["@expo/react-native-action-sheet@4.1.1", "", { "dependencies": { "@types/hoist-non-react-statics": "^3.3.1", "hoist-non-react-statics": "^3.3.0" }, "peerDependencies": { "react": ">=18.0.0" } }, "sha512-4KRaba2vhqDRR7ObBj6nrD5uJw8ePoNHdIOMETTpgGTX7StUbrF4j/sfrP1YUyaPEa1P8FXdwG6pB+2WtrJd1A=="], "@expo/require-utils": ["@expo/require-utils@56.1.3", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "@babel/core": "^7.25.2", "@babel/plugin-transform-modules-commonjs": "^7.24.8" }, "peerDependencies": { "typescript": "^5.0.0 || ^5.0.0-0 || ^6.0.0" }, "optionalPeers": ["typescript"] }, "sha512-KyLeOn/zzQSvuPpV5YhB/FPKnpQytno4luN918bGdPDssLBoS3N/0UbC3W0rJAn9kSFu+XpfR81eABRVsSdfgQ=="], - "@expo/router-server": ["@expo/router-server@56.0.12", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^56.0.13", "expo": "*", "expo-constants": "^56.0.16", "expo-font": "^56.0.5", "expo-router": "*", "expo-server": "^56.0.4", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-RqKV2/Z8BH/z8l0ngSpG6//5xxJPaF5dTQvSfPQ0nrvCjikGMeIvyj3B9BeLnmZZhxb3gBtXqrj3irAoiIp2aQ=="], + "@expo/router-server": ["@expo/router-server@56.0.14", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "@expo/metro-runtime": "^56.0.15", "expo": "*", "expo-constants": "^56.0.18", "expo-font": "^56.0.6", "expo-router": "*", "expo-server": "^56.0.5", "react": "*", "react-dom": "*", "react-server-dom-webpack": "~19.0.1 || ~19.1.2 || ~19.2.1" }, "optionalPeers": ["@expo/metro-runtime", "expo-router", "react-dom", "react-server-dom-webpack"] }, "sha512-2UCTtZfcq1ZPgp3wk8/+sq9DvFI9UxrPr1jcEKMAF2DGAJLosnpc8GWNNg2hkjt6SHUOdFHIPxujWPYyho2y3A=="], "@expo/schema-utils": ["@expo/schema-utils@56.0.1", "", {}, "sha512-CZ/+mYbQmWeOnkCGlWy9K+lFxbJSMFY7+TqBZcKzBSTU5Q7IGRvn/sOG3TdNjIdLPmbA8xe7R/c3UUQ28R9i9w=="], @@ -357,11 +358,11 @@ "@expo/sudo-prompt": ["@expo/sudo-prompt@9.3.2", "", {}, "sha512-HHQigo3rQWKMDzYDLkubN5WQOYXJJE2eNqIQC2axC2iO3mHdwnIR7FgZVvHWtBwAdzBgAP0ECp8KqS8TiMKvgw=="], - "@expo/ui": ["@expo/ui@56.0.14", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0", "vaul": "^1.1.2" }, "peerDependencies": { "@babel/core": "*", "expo": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-reanimated": "*", "react-native-worklets": "*" }, "optionalPeers": ["@babel/core", "react-dom", "react-native-reanimated", "react-native-worklets"] }, "sha512-0Wr8nsvk2C+BmhmZDQzYr/hxxddHK+ajuJ7ahacUvxt+gQnEXwbueTm0S/hk/54YGASEgplrPGDuR5zzcY+IZg=="], + "@expo/ui": ["@expo/ui@56.0.18", "", { "dependencies": { "sf-symbols-typescript": "^2.1.0", "vaul": "^1.1.2" }, "peerDependencies": { "@babel/core": "*", "expo": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-reanimated": "*", "react-native-worklets": "*" }, "optionalPeers": ["@babel/core", "react-dom", "react-native-reanimated", "react-native-worklets"] }, "sha512-2XgH5obigGtXm8zlb/V3g87NSiIcBcJ1xoQOEQYPoExL1DCNsHzaIecTh1XG/f/45ardo4OZNJwpbfYJ9X3qrQ=="], "@expo/vector-icons": ["@expo/vector-icons@15.1.1", "", { "peerDependencies": { "expo-font": ">=14.0.4", "react": "*", "react-native": "*" } }, "sha512-Iu2VkcoI5vygbtYngm7jb4ifxElNVXQYdDrYkT7UCEIiKLeWnQY0wf2ZhHZ+Wro6Sc5TaumpKUOqDRpLi5rkvw=="], - "@expo/ws-tunnel": ["@expo/ws-tunnel@1.0.6", "", {}, "sha512-nDRbLmSrJar7abvUjp3smDwH8HcbZcoOEa5jVPUv9/9CajgmWw20JNRwTuBRzWIWIkEJDkz20GoNA+tSwUqk0Q=="], + "@expo/ws-tunnel": ["@expo/ws-tunnel@2.0.0", "", { "peerDependencies": { "ws": "^8.0.0" } }, "sha512-j+JfTRdCk820J9dU0sA2SqshQIKFOMo7ED84w9MJFcebfbNQgsLztEY/SABDkGnjatrW4xGqnUhVRxSBVyCkXw=="], "@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="], @@ -417,19 +418,7 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="], - - "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="], - - "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="], - - "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="], - - "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="], - - "@nodable/entities": ["@nodable/entities@2.1.0", "", {}, "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA=="], + "@nodable/entities": ["@nodable/entities@2.2.0", "", {}, "sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg=="], "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], @@ -437,47 +426,47 @@ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], - "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.4", "", {}, "sha512-7AdCK9PQyiljKoBDbN8OuctCbd/esdwZPQ8RtOE3SsyQtUpiPb+ND75q0jEhC1m1ecBI0MFNeLJvwIh9iKHRcQ=="], - "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.10", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IVVz4EvBcKjrzKgof714qDnz/SzQAkLA2Emh5edlHbgcE6fNd3Un6CJLlaYcnm8N4JmAtzQgse4dOKxcD2yc9g=="], - "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-rYOP8OMnuuPMQF1uhPVlGNcCDlkokKqGFE3JcxFViIkAXP7EvFWUliJAstrapypaBLJNHbZL6jGhbVDGTwmVhA=="], - "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + "@radix-ui/react-context": ["@radix-ui/react-context@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QwH4PO5urrbO+FaGd5Aglg+YJgWTyyuZ3g/6mKvsqraLkglDdckw9JafgL5McL5VEJ6EPNduPaT3ZE9BttDAqg=="], - "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="], + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.17", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.13", "@radix-ui/react-focus-guards": "1.1.4", "@radix-ui/react-focus-scope": "1.1.10", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-portal": "1.1.12", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-slot": "1.3.0", "@radix-ui/react-use-controllable-state": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TDTYmpdq8dI2+Xgvgj9AJ8Ghqq+Eph/TRVEdaFQPDItIY+6QSkU7MJMeevw1568Yw/2Ijz8BTphPSP2XejKphw=="], - "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-C3vFhbyi4SW3PmbAi6Awpu4OzJtd0MxGurvSsYtr7p7nM8RNB3VAF3CUmnp2j50knpkrRcB7+ycVXzgLgF6yNA=="], - "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="], + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-escape-keydown": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-2v+zNAWWe0ySxgC0D0yeXMPQ23xZVgXZTerTz+JKlmdRj6gfTqmCcR29jb6d290DezXPGgruHWDX/vYUebtErg=="], - "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cot/aB/mOm0IYVYTTmQcEEK1M48lZWi8FlYe5nDPQQ8NYZUlXEFgncJ9p2Kzer3RKSrY7cTTpEMLZKNo9QoP5Q=="], - "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.10", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fas/lXQqhVvqwAb64s5RFeHiHYElZ6SUQbZaNd6EkfhP/Al7wTIQ9WIR4QVX475tlu5yFCEdDcJH6/UwsZjMWw=="], - "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-orBC88futVpqCmhX1p4cvquNHsELQ+w+vBJnuj3ftETI5bJb0bZn3Tqu3SWN2IOcPycTnMGnhwoermvISt72sA=="], - "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="], + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.12", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m309havGzsjLHHaIX50G5PlvRs3xkgPCsGk/5PTvYm8D5q33yG0J7w/712PTOhid7NTaFETtnSXjngHQavvhVw=="], - "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.6", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zdTk4PlUO0E18HnZ3wYbW0KkJJxWCdiNYp6g6X1PtONFhxVkg01vliTJAmwIszU6mHiyBOoW9P0rAugl5/hULQ=="], - "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.6", "", { "dependencies": { "@radix-ui/react-slot": "1.3.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wetd0QI77DbvrPpTAvH1SqOxsYF2wZe5TNxqwOd5Ty4XDpV3dpV0s8K/1MGMJBeY5o7lg8ub5VIt1Ub+yVen6g=="], - "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="], + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-collection": "1.1.10", "@radix-ui/react-compose-refs": "1.1.3", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-use-callback-ref": "1.1.2", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9gkwneI0guf8JDmrFxPjJF6Ozzgioyw+/lonYNCwefS9ZHA05er0BVHiXr+LbWGHxUfczvMY6G1oiZZi1VzjRw=="], - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MojKku4U/miO8Av4Dkb+ctMAQx7JmY96LmtDQlAarCRtd7rN52QCSzBF+XAvr5S6coSVj9HEPBgHAHKEJVk/WA=="], - "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="], + "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.4", "@radix-ui/react-context": "1.1.4", "@radix-ui/react-direction": "1.1.2", "@radix-ui/react-id": "1.1.2", "@radix-ui/react-presence": "1.1.6", "@radix-ui/react-primitive": "2.1.6", "@radix-ui/react-roving-focus": "1.1.13", "@radix-ui/react-use-controllable-state": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kxc9gI6/HfcU4nfMMVS3AmQK414kbU1IE6UCJmMmxjhO3cRPXOyYnmvyKD+ODt7q56nRq9l7Wovi6uaGwKgMlg=="], - "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-xCso9j1/u8sEgP1RNHjFrXJLApL8LiqOkI1R4ywuN00rxWdYg4oQXuwKLS3i0j5NWLromUD27/4nlxj2UFVvIw=="], - "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.3", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.3", "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-PLzC90MS+ReootmjC597dvopoelpZ8Q61HJkDXZSExitIq7PL55vHNnesAHwguHK0aPfBnpdNzQtv1uliaqQrA=="], - "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.3", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-6c8ZqvPTWILEKnyVkP53EGRCcpnJiKTC21sS/6R1GF5xKyHJJWQEPfkqlcgUkdRQivd6tb23abUwe4ngWmY0JA=="], - "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.2", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2uVLvLjgO7NZCWw01/FdqRwmA42J0BcjPMUCA+koFEOAb+zjqIP7SiFz/7zWPrKnVmSqr76Omq2ALyCuX4dhLw=="], - "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jrBWOxZITuGcnjRCM2t2U5ZPkCLxD+Ym6DjfssS5haTj2iiak/DOb64JeN6OdLfLgptb6/e2kKR+ZuTrGoZTPA=="], "@react-native-community/cli": ["@react-native-community/cli@20.1.3", "", { "dependencies": { "@react-native-community/cli-clean": "20.1.3", "@react-native-community/cli-config": "20.1.3", "@react-native-community/cli-doctor": "20.1.3", "@react-native-community/cli-server-api": "20.1.3", "@react-native-community/cli-tools": "20.1.3", "@react-native-community/cli-types": "20.1.3", "commander": "^9.4.1", "deepmerge": "^4.3.0", "execa": "^5.0.0", "find-up": "^5.0.0", "fs-extra": "^8.1.0", "graceful-fs": "^4.1.3", "picocolors": "^1.1.1", "prompts": "^2.4.2", "semver": "^7.5.2" }, "bin": { "rnc-cli": "build/bin.js" } }, "sha512-sLo8cu9JyFNfuuF1C+8NJ4DHE/PEFaXGd4enkcxi/OJjGG8+sOQrdjNQ4i+cVh/2c+ah1mEMwsYjc3z0+/MqSg=="], @@ -515,7 +504,7 @@ "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.85.3", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.85.3" } }, "sha512-Wc94zGfeFG8Njf9SHMPfYZP04kjigkOps6F1TYTvd7ZVXuGxqseCDgxc50LWcOhOCLypI9n3oVVqz81C3p44ZA=="], - "@react-native/babel-preset": ["@react-native/babel-preset@0.85.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@react-native/babel-plugin-codegen": "0.85.3", "babel-plugin-syntax-hermes-parser": "0.33.3", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-fD7fxEhkJB/aF57tWoXjaAWpklfrExYZS3k6aXPP3BQ77DZY7gvf/b7dbirwjID6NVnP1JDRJyTuPBGr0K/vlw=="], + "@react-native/babel-preset": ["@react-native/babel-preset@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.25.2", "@babel/plugin-transform-react-jsx-self": "^7.24.7", "@babel/plugin-transform-react-jsx-source": "^7.24.7", "@babel/plugin-transform-regenerator": "^7.24.7", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@react-native/babel-plugin-codegen": "0.86.0", "babel-plugin-syntax-hermes-parser": "0.36.0", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-bYQcWiPySNvF4dns9Ls9gMmwgq66ohvM9Fwc/Kn8r85t66UNHxch3p1QwPiSorDelFauZwJbgo9+ReibTgvpbA=="], "@react-native/codegen": ["@react-native/codegen@0.85.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.33.3", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-/JkS1lGLyzBWP1FbgDwaqEf7qShIC6pUC1M0a/YMAd/v4iqR24MRkQWe7jkYvcBQ2LpEhs5NGE9InhxSv21zCA=="], @@ -531,21 +520,21 @@ "@react-native/js-polyfills": ["@react-native/js-polyfills@0.85.3", "", {}, "sha512-U2+aMshIXf1uFn77tpBb/xhHWB9vkVrMpt7kkucAugF8hJKYTDGB587X7WwelHduK2KBfhl4giSv0rzZGoef9A=="], - "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.85.3", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.85.3", "hermes-parser": "0.33.3", "nullthrows": "^1.1.1" } }, "sha512-omuKq+r7jM4XvCMIlNMPP7Up3SyB8o5EAdZtF7YXniKyq7UOMBqhYHFqgsdOXr0lT+3ADf7VCJG3sb82jlBrrQ=="], + "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.86.0", "hermes-parser": "0.36.0", "nullthrows": "^1.1.1" } }, "sha512-SjKej3E5qIahqo/G+rSOrmJUQM44RyKtWtO+VfmKAAMoJWkBFomM22hTLKCIS5cdbIAJ9COAmU+KAi2wVSO0wQ=="], - "@react-native/metro-config": ["@react-native/metro-config@0.85.3", "", { "dependencies": { "@react-native/js-polyfills": "0.85.3", "@react-native/metro-babel-transformer": "0.85.3", "metro-config": "^0.84.3", "metro-runtime": "^0.84.3" } }, "sha512-sVo6HepUmCcpdfozEf91lA0FjpLNNZYu/Zi9FiYiAQTK8pzATXDVTqhvdxpFrQn435p5eUTSbllvbH/KN+bnyA=="], + "@react-native/metro-config": ["@react-native/metro-config@0.86.0", "", { "dependencies": { "@react-native/js-polyfills": "0.86.0", "@react-native/metro-babel-transformer": "0.86.0", "metro-config": "^0.84.3", "metro-runtime": "^0.84.3" } }, "sha512-7v+xbTeEci9ZcQ/Z1OqI4RXcqN69wSMDYL5BAMvOReZ7U04+aDQ0/SQhClYPn6x2/RxM4WzMKSAuNyLKqvYVtw=="], "@react-native/normalize-colors": ["@react-native/normalize-colors@0.85.3", "", {}, "sha512-hj0PScZEhIbcOvQV5yMKX3ha4XEIOy/SVE1Rrpp0beW0dpNLOgSC7KDxGewmDnIHK9YdQUXGY9eMEfShUMIaZw=="], - "@react-navigation/core": ["@react-navigation/core@7.17.5", "", { "dependencies": { "@react-navigation/routers": "^7.5.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-6fDCwDTWC7DJn0SDb9DJGRlipaygHIc+2elpZBJI6Crl/2Pu+Z1d6W4jMJ2gZO6iHKf+Pe5sUiQ/uwepGprZtg=="], + "@react-navigation/core": ["@react-navigation/core@7.21.1", "", { "dependencies": { "@react-navigation/routers": "^7.6.0", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-9eOK71VFEyJjm1bP8o4Gf7YYppWPZ+RdNIjTc+WbSM7AFEH0XXEIHkkhpIBuB416sDlRZ1CRxHk2frh1HPBZqw=="], - "@react-navigation/elements": ["@react-navigation/elements@2.9.19", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.2.5", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-gBUvCZuUkOGw1KpLQEZIkByUz8RYPwXeoA6mZFJy9K1mxd8GdqHDMFCIoB0lfPz9rgrHj99RvtdlGZ/ZzkZv2A=="], + "@react-navigation/elements": ["@react-navigation/elements@2.9.25", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.3.3", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-cV7Hny55aE/uge6f4UB0pbGQbFl3XjXLMW+lTBNuJs8P7a9tuf7dkkPHxxgnLIvxE+KJVI2K8CGabfDk4Ht0Sg=="], "@react-navigation/material-top-tabs": ["@react-navigation/material-top-tabs@7.4.28", "", { "dependencies": { "@react-navigation/elements": "^2.9.19", "color": "^4.2.3", "react-native-tab-view": "^4.3.0" }, "peerDependencies": { "@react-navigation/native": "^7.2.5", "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0" } }, "sha512-WZHJSGV2PQOD2Vr9LF8apGvcsbDKukzF3Fhh8xVNIesqaSi9TPProv4dRw6YkenUkjvFVZYkOjvwAJOToePVpA=="], - "@react-navigation/native": ["@react-navigation/native@7.2.5", "", { "dependencies": { "@react-navigation/core": "^7.17.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-01AAUQiiHQAfTabq+ZyU1/ZWq+AbB/J3v0CB0UTJSON6M6cuadWNsbChzrZUdqQvHrXvg96U5i2PQLJzK3+zpg=="], + "@react-navigation/native": ["@react-navigation/native@7.3.3", "", { "dependencies": { "@react-navigation/core": "^7.21.1", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "standard-navigation": "^0.0.7", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-VjZngfeiyJestZPT99CKHRi3qOR6XwnEEPWb6uHF/L7fBI6RBVP842iJf61MUHRTzsWPUT+epJqdf1wm8N5YkQ=="], - "@react-navigation/routers": ["@react-navigation/routers@7.5.5", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-9/hhMte12Kgu+pMnLfA4EWJ0OQmIEAMVMX06FPH2yGkEQSQ3JhhCN/GkcRikzQhtEi97VYYQA15umptBUShcOQ=="], + "@react-navigation/routers": ["@react-navigation/routers@7.6.0", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-lblhDXfS75jLc7G2K7BZGM+7cjqQXk13X/MA4fq/12r62zM+fBhhreLzYflSitrDDXFRJpSvJXy0ziiGU04Xow=="], "@shopify/flash-list": ["@shopify/flash-list@2.0.2", "", { "dependencies": { "tslib": "2.8.1" }, "peerDependencies": { "@babel/runtime": "*", "react": "*", "react-native": "*" } }, "sha512-zhlrhA9eiuEzja4wxVvotgXHtqd3qsYbXkQ3rsBfOgbFA9BVeErpDE/yEwtlIviRGEqpuFj/oU5owD6ByaNX+w=="], @@ -561,17 +550,17 @@ "@tanstack/pacer": ["@tanstack/pacer@0.18.0", "", { "dependencies": { "@tanstack/devtools-event-client": "^0.4.0", "@tanstack/store": "^0.8.0" } }, "sha512-qhCRSFei0hokQr3xYcQXqxsRD/LKlgHCxHXtKHrQoImp4x2Zu6tUOpUGVH4y2qexIrzSu3aibQBNNfC3Eay6Mg=="], - "@tanstack/query-core": ["@tanstack/query-core@5.100.14", "", {}, "sha512-5X41dGpxgeaHISCRW2oYwcSycZeULZzAunaudXT9ov1KOTj9xwt0CH6hbwqP1/z74ZWF7rYFnDpyYH07XFcZew=="], + "@tanstack/query-core": ["@tanstack/query-core@5.101.0", "", {}, "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow=="], - "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.100.14", "", { "dependencies": { "@tanstack/query-core": "5.100.14" } }, "sha512-mn60cqoQO/xB6aHxp/hxlSj5mcdcTO4tjj4SXSz5MKzkaMZnvcEGySz3+cGQOT8McREN56fL41L0eR//v5RwNw=="], + "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.101.0", "", { "dependencies": { "@tanstack/query-core": "5.101.0" } }, "sha512-LH99WepGVLwlLfuOcQcPK7f3Xg/Gf+xlMMIj9xWu/8oQ3egnDzjr+a4HvEmi6PGob5SmGXvmDKZaH5+In9dzjw=="], - "@tanstack/query-sync-storage-persister": ["@tanstack/query-sync-storage-persister@5.100.14", "", { "dependencies": { "@tanstack/query-core": "5.100.14", "@tanstack/query-persist-client-core": "5.100.14" } }, "sha512-sDsiVjLJqslUdqIANGvRyB4hYpAooYj5R1fe2EzKfrSY7XufSe+AFBvirLgX/nL2uS1JeP4XeyUuG3TM0bAN9w=="], + "@tanstack/query-sync-storage-persister": ["@tanstack/query-sync-storage-persister@5.101.0", "", { "dependencies": { "@tanstack/query-core": "5.101.0", "@tanstack/query-persist-client-core": "5.101.0" } }, "sha512-UAGbsIJe9vkV/rbFxUBOPH27Eu6K17KuVLfK1mSy8qoSUJ4qt6JKGMxA8NMUoowbPG0ZnTfRt1Y5SFsqfqlfcA=="], "@tanstack/react-pacer": ["@tanstack/react-pacer@0.19.4", "", { "dependencies": { "@tanstack/pacer": "0.18.0", "@tanstack/react-store": "^0.8.0" }, "peerDependencies": { "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-coj8ULAuR0qFpjAKD44gTgRuZyjxU6Xu+IX5MwwYvr4e61OtZcJshaExoOBKpCGde0Edb12jDnzzj2Im13Qm9Q=="], "@tanstack/react-query": ["@tanstack/react-query@5.100.14", "", { "dependencies": { "@tanstack/query-core": "5.100.14" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-oOr6aRdSFEwWhzxEkD/9ZcItM3+LjBSkeVmadWKwUssAHTsqd/7bOjWrX4AbvEkoEhgAxzN0Xk6H/aYzXiYBAw=="], - "@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.100.14", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.100.14" }, "peerDependencies": { "@tanstack/react-query": "^5.100.14", "react": "^18 || ^19" } }, "sha512-lQSnbJva85o7jGcJiIDrA8s3VGGx9zaBCgAljm0H1QcScU2iaDYnPuRLg/xI0k0dC45pgg9RTvpgJx5iVHRsjA=="], + "@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.101.0", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.101.0" }, "peerDependencies": { "@tanstack/react-query": "^5.101.0", "react": "^18 || ^19" } }, "sha512-AUcdBgz8V6sM9axzdqkVmWjYSOETkhr6yAZSBnEFyZT2jo6vkFq3UrpRuxGs6fmhKMWv8FA+ZJGcbaKPaoAElQ=="], "@tanstack/react-store": ["@tanstack/react-store@0.8.1", "", { "dependencies": { "@tanstack/store": "0.8.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-XItJt+rG8c5Wn/2L/bnxys85rBpm0BfMbhb4zmPVLXAKY9POrp1xd6IbU4PKoOI+jSEGc3vntPRfLGSgXfE2Ig=="], @@ -605,7 +594,7 @@ "@types/node": ["@types/node@18.19.130", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg=="], - "@types/react": ["@types/react@19.2.15", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q=="], + "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], "@types/react-test-renderer": ["@types/react-test-renderer@19.1.0", "", { "dependencies": { "@types/react": "*" } }, "sha512-XD0WZrHqjNrxA/MaR9O22w/RNidWR9YZmBdRGI7wcnWGrv/3dA8wKCJ8m63Sn+tLJhcjmuhOi629N66W6kgWzQ=="], @@ -649,7 +638,7 @@ "accepts": ["accepts@1.3.8", "", { "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" } }, "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw=="], - "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + "acorn": ["acorn@8.17.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg=="], "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], @@ -669,6 +658,8 @@ "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], + "anynum": ["anynum@1.0.0", "", {}, "sha512-xjR9/zBVnUOP6ztMIIgShjsxui80nQUQH+5xJnvrYLs+90bF25/KJqaAi8mk+B4RDtX1Nspi6fmp4YTEts8SfA=="], + "appdirsjs": ["appdirsjs@1.2.7", "", {}, "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw=="], "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], @@ -687,7 +678,7 @@ "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], - "axios": ["axios@1.16.1", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A=="], + "axios": ["axios@1.18.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw=="], "babel-plugin-polyfill-corejs2": ["babel-plugin-polyfill-corejs2@0.4.17", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-define-polyfill-provider": "^0.6.8", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w=="], @@ -703,17 +694,17 @@ "babel-plugin-transform-flow-enums": ["babel-plugin-transform-flow-enums@0.0.2", "", { "dependencies": { "@babel/plugin-syntax-flow": "^7.12.1" } }, "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ=="], - "babel-preset-expo": ["babel-preset-expo@56.0.13", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.28.6", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-plugin-codegen": "0.85.3", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.33.3", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^56.0.15", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-+CxxAQrN95N+/dF4AUJXNxEh5cEv4yhxb4CM5ijdc2OeIIw+hxzYh2OM1X7QHIm6hkT66H4vJCTT636yjJ8MnQ=="], + "babel-preset-expo": ["babel-preset-expo@56.0.15", "", { "dependencies": { "@babel/generator": "^7.20.5", "@babel/helper-module-imports": "^7.25.9", "@babel/plugin-proposal-decorators": "^7.12.9", "@babel/plugin-proposal-export-default-from": "^7.24.7", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-default-from": "^7.24.7", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-transform-async-generator-functions": "^7.25.4", "@babel/plugin-transform-async-to-generator": "^7.24.7", "@babel/plugin-transform-block-scoping": "^7.25.0", "@babel/plugin-transform-class-properties": "^7.25.4", "@babel/plugin-transform-class-static-block": "^7.27.1", "@babel/plugin-transform-classes": "^7.25.4", "@babel/plugin-transform-destructuring": "^7.24.8", "@babel/plugin-transform-export-namespace-from": "^7.25.9", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/plugin-transform-for-of": "^7.24.7", "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", "@babel/plugin-transform-modules-commonjs": "^7.24.8", "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", "@babel/plugin-transform-object-rest-spread": "^7.24.7", "@babel/plugin-transform-optional-catch-binding": "^7.24.7", "@babel/plugin-transform-optional-chaining": "^7.24.8", "@babel/plugin-transform-parameters": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-property-in-object": "^7.24.7", "@babel/plugin-transform-react-display-name": "^7.24.7", "@babel/plugin-transform-react-jsx": "^7.28.6", "@babel/plugin-transform-react-jsx-development": "^7.27.1", "@babel/plugin-transform-react-pure-annotations": "^7.27.1", "@babel/plugin-transform-runtime": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/preset-typescript": "^7.23.0", "@react-native/babel-plugin-codegen": "0.85.3", "babel-plugin-react-compiler": "^1.0.0", "babel-plugin-react-native-web": "~0.21.0", "babel-plugin-syntax-hermes-parser": "^0.33.3", "babel-plugin-transform-flow-enums": "^0.0.2", "debug": "^4.3.4" }, "peerDependencies": { "@babel/runtime": "^7.20.0", "expo": "*", "expo-widgets": "^56.0.18", "react-refresh": ">=0.14.0 <1.0.0" }, "optionalPeers": ["@babel/runtime", "expo", "expo-widgets"] }, "sha512-0MqbQoM6nBUbKvgu2xJ4VixZnUTGTq3HB2WwvOikdO4CiPxbQ+wGA25fOoHHSni5iEFW39wy6y1ookTWlq3wVw=="], "badgin": ["badgin@1.2.3", "", {}, "sha512-NQGA7LcfCpSzIbGRbkgjgdWkjy7HI+Th5VLxTJfW5EeaAf3fnS+xWQaQOCYiny+q6QSvxqoSO04vCx+4u++EJw=="], "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], - "barcode-detector": ["barcode-detector@3.1.3", "", { "dependencies": { "zxing-wasm": "3.0.3" } }, "sha512-omL3/x26oU9jlR0gUQcGdXIjQtMlrUGKF7xRFO1RwrQkRkRU7WLz0mgQEsdUtYBm2uX3JH+HQLrKlyTS/BxZRw=="], + "barcode-detector": ["barcode-detector@3.2.0", "", { "dependencies": { "zxing-wasm": "3.1.0" } }, "sha512-MrT5TT058ptG5YB157pHLfXKVpp0BKEfQBOb8QvzTbatzmLDu85JJ0Gd/sCYwbwdwStJvxsYflrSN6D6E4Ndyw=="], "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], - "baseline-browser-mapping": ["baseline-browser-mapping@2.10.32", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg=="], + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.37", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-girxaJ7WZssDOFhzCGZTDKoTa1gk6A1TbflaYTpykLJ4UU9Fz9kx1aREM8JCuoVHbL8X8T/mJg7w2oYSq72Oig=="], "big-integer": ["big-integer@1.6.52", "", {}, "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg=="], @@ -723,7 +714,7 @@ "bmp-js": ["bmp-js@0.1.0", "", {}, "sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw=="], - "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="], + "body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="], "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], @@ -759,7 +750,7 @@ "camelize": ["camelize@1.0.1", "", {}, "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ=="], - "caniuse-lite": ["caniuse-lite@1.0.30001793", "", {}, "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA=="], + "caniuse-lite": ["caniuse-lite@1.0.30001799", "", {}, "sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], @@ -805,13 +796,13 @@ "connect": ["connect@3.7.0", "", { "dependencies": { "debug": "2.6.9", "finalhandler": "1.1.2", "parseurl": "~1.3.3", "utils-merge": "1.0.1" } }, "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ=="], - "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + "content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "core-js-compat": ["core-js-compat@3.49.0", "", { "dependencies": { "browserslist": "^4.28.1" } }, "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA=="], - "cosmiconfig": ["cosmiconfig@9.0.1", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-hr4ihw+DBqcvrsEDioRO31Z17x71pUYoNe/4h6Z0wB72p7MU7/9gH8Q3s12NFhHPfYBBOV3qyfUxmr/Yn3shnQ=="], + "cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="], "cross-env": ["cross-env@10.1.0", "", { "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw=="], @@ -841,7 +832,7 @@ "dayjs": ["dayjs@1.11.21", "", {}, "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA=="], - "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], @@ -873,7 +864,7 @@ "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], - "dnssd-advertise": ["dnssd-advertise@1.1.4", "", {}, "sha512-AmGyK9WpNf06WeP5TjHZq/wNzP76OuEeaiTlKr9E/EEelYLczywUKoqRz+DPRq/ErssjT4lU+/W7wzJW+7K/ZA=="], + "dnssd-advertise": ["dnssd-advertise@1.1.6", "", {}, "sha512-Ndrrf6BMPalkQPd/zubL+4YghH2J9NspapQ09uDXwYbvOPkP0oaqf5CkcwJ0b50kS2O3ul6yVu+jz+RY62Cejg=="], "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], @@ -889,7 +880,7 @@ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], - "electron-to-chromium": ["electron-to-chromium@1.5.363", "", {}, "sha512-VjUKPyWzGnT1fujlkEGC/BvN70Hh70KXtAqcmniXviYlJC/ivcT+BWGPyxWVbJZLfvtKR6dqg1L7T7pgAMBtWA=="], + "electron-to-chromium": ["electron-to-chromium@1.5.374", "", {}, "sha512-HCF5i7izveksHSGqa7mhDh6tr3Uz9Dar2RAjwuh69bw3QGPVObjQIgLwQWeO/Rxp9/r0KdboKy9RbpQDl97fjg=="], "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], @@ -937,49 +928,49 @@ "expect": ["expect@29.7.0", "", { "dependencies": { "@jest/expect-utils": "^29.7.0", "jest-get-type": "^29.6.3", "jest-matcher-utils": "^29.7.0", "jest-message-util": "^29.7.0", "jest-util": "^29.7.0" } }, "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw=="], - "expo": ["expo@56.0.6", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "^56.1.12", "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.8", "@expo/devtools": "~56.0.2", "@expo/dom-webview": "~56.0.5", "@expo/fingerprint": "^0.19.3", "@expo/local-build-cache-provider": "^56.0.8", "@expo/log-box": "^56.0.12", "@expo/metro": "~56.0.0", "@expo/metro-config": "~56.0.13", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~56.0.13", "expo-asset": "~56.0.15", "expo-constants": "~56.0.16", "expo-file-system": "~56.0.7", "expo-font": "~56.0.5", "expo-keep-awake": "~56.0.3", "expo-modules-autolinking": "~56.0.14", "expo-modules-core": "~56.0.13", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/metro-runtime": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-web": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/metro-runtime", "react-dom", "react-native-web", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-zcFa/+6hGtzCUlcrGiusvzr/PIoNBAnjj4PlAFrvbAOZcVOj6c9Mp7lRSn9XYJk8Ok6pssQWt6dP4llJlKmYRQ=="], + "expo": ["expo@56.0.12", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@expo/cli": "^56.1.16", "@expo/config": "~56.0.9", "@expo/config-plugins": "~56.0.9", "@expo/devtools": "~56.0.2", "@expo/dom-webview": "~56.0.5", "@expo/fingerprint": "^0.19.4", "@expo/local-build-cache-provider": "^56.0.8", "@expo/log-box": "^56.0.13", "@expo/metro": "~56.0.0", "@expo/metro-config": "~56.0.14", "@ungap/structured-clone": "^1.3.0", "babel-preset-expo": "~56.0.15", "expo-asset": "~56.0.17", "expo-constants": "~56.0.18", "expo-file-system": "~56.0.8", "expo-font": "~56.0.7", "expo-keep-awake": "~56.0.3", "expo-modules-autolinking": "~56.0.16", "expo-modules-core": "~56.0.17", "pretty-format": "^29.7.0", "react-refresh": "^0.14.2", "whatwg-url-minimum": "^0.1.2" }, "peerDependencies": { "@expo/metro-runtime": "*", "react": "*", "react-dom": "*", "react-native": "*", "react-native-web": "*", "react-native-webview": "*" }, "optionalPeers": ["@expo/metro-runtime", "react-dom", "react-native-web", "react-native-webview"], "bin": { "expo": "bin/cli", "fingerprint": "bin/fingerprint", "expo-modules-autolinking": "bin/autolinking" } }, "sha512-FxgdI/Yqva6iJOThZIHfvxlKPxs4EC4uScUnEswwSArR/Fj9k430O13R590LcOQTsdNsjIs+GBHwjfoAY6vmAQ=="], "expo-application": ["expo-application@56.0.3", "", { "peerDependencies": { "expo": "*" } }, "sha512-DdGGPlMuM6cSTeKhbvh6OeLr2O/+EI5BHKYrD+Do8sJPYgLwzGrgESELfyjJCpEhFzT+TgKIdmLmWXhNUQnHiw=="], - "expo-asset": ["expo-asset@56.0.15", "", { "dependencies": { "@expo/image-utils": "^0.10.1", "expo-constants": "~56.0.16" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-BHGi2IAOPQTcOelkUdcz1WIknfCTRjkcpYHX1azjMwgYenrVC+J5qcqJGaC8eUOWLCRtkRJWGnmFQRYtLU1nUQ=="], + "expo-asset": ["expo-asset@56.0.17", "", { "dependencies": { "@expo/image-utils": "^0.10.1", "expo-constants": "~56.0.18" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-GFN5j+8SPkyv0nfsiFHewmdB/D0tL237TsBE/gSfFOFy/J3a52py7IulcSqkA3sQE/u/UlD5BmvP5ssS4//nUg=="], - "expo-audio": ["expo-audio@56.0.11", "", { "peerDependencies": { "expo": "*", "expo-asset": "*", "react": "*", "react-native": "*" } }, "sha512-naionxilr49IpEjmMqCj5gXHCSfOsgu3nZ/KXndexR05Tv6dET7dmespyZkcMrADJN07gA5hyqPUC5WqWuaFLw=="], + "expo-audio": ["expo-audio@56.0.12", "", { "peerDependencies": { "expo": "*", "expo-asset": "*", "react": "*", "react-native": "*" } }, "sha512-ne2UIO/HsQoBL9e+tGs5N9Sf3NyW5sJMm4sDkexbSJRc2IchLDG+9Msu/+l5N4RlZ8SiF42wRyWsh/Usg+SwOw=="], - "expo-background-task": ["expo-background-task@56.0.15", "", { "dependencies": { "expo-task-manager": "~56.0.15" }, "peerDependencies": { "expo": "*" } }, "sha512-ZBzLkKFmM5ZpJYl1D1kpmk6MomLbVx6LQbMX4GGLg8TSidvvtden0haIw4R5Rpkgzj3LOjvFMFli5a4kQA7VCA=="], + "expo-background-task": ["expo-background-task@56.0.19", "", { "dependencies": { "expo-task-manager": "~56.0.19" }, "peerDependencies": { "expo": "*" } }, "sha512-TuFqorlz4HXtWAwQGcg+/URXpBwjwNsAxdis/6m5mhtgBIVbX2gYYv/s6eIf8lh2cAI1zFkb+/bHHuC2aOAGGA=="], "expo-blur": ["expo-blur@56.0.3", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-KDDtrpWc2tYlm1WCPaOgBtv+YEGqe5ELheFPIgSNgHt28NQUDcfBcFsA9Us2StDh6osmSD6NbKxOt5bU6PcDbQ=="], "expo-brightness": ["expo-brightness@56.0.5", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-AkCGW+Lj8I4o2+Yjs1bzjIJz44cgNXfAN+pf01uDwmA1/1JTIy8x1eISvmz6d2r/1OhdyBZxeDkACNLVMDx5zA=="], - "expo-build-properties": ["expo-build-properties@56.0.15", "", { "dependencies": { "@expo/schema-utils": "^56.0.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-3OlfTnBE6BIFxchjXzb0OlgDcWw19fxhIzpIZqgcgzZUVjyn4gCrQuNcsfazVVddBypwkEzOVfwArPROIk4J7g=="], + "expo-build-properties": ["expo-build-properties@56.0.19", "", { "dependencies": { "@expo/schema-utils": "^56.0.0", "resolve-from": "^5.0.0", "semver": "^7.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-InoviXcxWosNp4cC7L3SWoiY99Xr2HdgN+LYHb6mUm/BBVxy1mIMrZR+3PJ2gwDZzW6EJNDz8ioASWGHBTmzpA=="], - "expo-camera": ["expo-camera@56.0.7", "", { "dependencies": { "barcode-detector": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-c8z+UheidFintQyP9XLEDP43aK4PS/o9+TFLW0zEOjdqkYCBgoWq6Mw/Ps62kjBeftFY7xrp5ZLITbenNvbTaw=="], + "expo-camera": ["expo-camera@56.0.8", "", { "dependencies": { "barcode-detector": "^3.0.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-UDOpUUMisFRmCv1XQV1MJCKGAH2CsIC1Rs6P9Bbc6JLVmbxEKAd5dK68y6cScOdWURxVfJ0PRcjYnSuc8ayyIQ=="], - "expo-constants": ["expo-constants@56.0.16", "", { "dependencies": { "@expo/env": "~2.3.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-6tsiN+gmTUPp/atyA+uY9Tg8VOdXdmb4s/3TVGolfn6A/oCAraw1pcPZX5XllyD+xUguxB6eBSFAT8494hZVMA=="], + "expo-constants": ["expo-constants@56.0.18", "", { "dependencies": { "@expo/env": "~2.3.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-8AMtbDGl/WVPnWlmbpGmvcdnNCy9E4PFnwdVwj600vljkMDPSxcAcjw8GVXEPk3PpZ+ngTqsrkltWyj0UKYAxw=="], "expo-crypto": ["expo-crypto@56.0.4", "", { "peerDependencies": { "expo": "*" } }, "sha512-fRNEhoXRXgAWBpe3/hq5X+KXTit3OZqdiAGts1YvNEUHQb+H5591mpPac0Yw+sZg9pXcrjRnzo5AxvZaENpc7g=="], - "expo-dev-client": ["expo-dev-client@56.0.16", "", { "dependencies": { "expo-dev-launcher": "~56.0.16", "expo-dev-menu": "~56.0.15", "expo-dev-menu-interface": "~56.0.0", "expo-manifests": "~56.0.4", "expo-updates-interface": "~56.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-mxmGA6YSP4KiMB4bREpriQ4K6EaS4tcm0eh1+LtAzgFCytq+Y4WxMfIvFe3B5kXlSpA0ohMLdAN0AUzU0xHGQg=="], + "expo-dev-client": ["expo-dev-client@56.0.20", "", { "dependencies": { "expo-dev-launcher": "~56.0.20", "expo-dev-menu": "~56.0.17", "expo-dev-menu-interface": "~56.0.0", "expo-manifests": "~56.0.4", "expo-updates-interface": "~56.0.1" }, "peerDependencies": { "expo": "*" } }, "sha512-KebW4r8HhIiRrPzs6ZqVhp/so8buyglAO1h4No0Ibr5C2XRnlIoGWCN4zC6rW7IsI3iKUXcofLAQV9OjoxjiwQ=="], - "expo-dev-launcher": ["expo-dev-launcher@56.0.16", "", { "dependencies": { "@expo/schema-utils": "^56.0.0", "expo-dev-menu": "~56.0.15", "expo-manifests": "~56.0.4" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-3t2PCX2lCKetKL8EgRRo2tzSlGh1zcuaWuwp3V0k4/3nuM7pztyImaR6Sm3HUyarDOofAIPX1hIIxnuAfk5cnw=="], + "expo-dev-launcher": ["expo-dev-launcher@56.0.20", "", { "dependencies": { "@expo/schema-utils": "^56.0.0", "expo-dev-menu": "~56.0.17", "expo-manifests": "~56.0.4" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-cTuC3GkPl9CTwO3CKnVmEm9qoQ0WairhwvTh6qMlg+zr/QU/tdiU++uDBX67hf9+FuxQOkWGp5khFNosT+0cIg=="], - "expo-dev-menu": ["expo-dev-menu@56.0.15", "", { "dependencies": { "expo-dev-menu-interface": "~56.0.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-FY6Y5sZkNXxPBGDgC51ZArOi8N7Y8wpXwanTClFO36IVMoVf7BBqhjW13KpDecvJONtEtaUeNIAt9C25PO8MOQ=="], + "expo-dev-menu": ["expo-dev-menu@56.0.17", "", { "dependencies": { "expo-dev-menu-interface": "~56.0.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-OofRkOOZnaDriSav3JDN4NP2lsLt2eOa/Ryptr5nMD62SwnFyK4R6n6PkPVaDU3LSsZqndAJHmN6inS+oziayQ=="], "expo-dev-menu-interface": ["expo-dev-menu-interface@56.0.1", "", { "peerDependencies": { "expo": "*" } }, "sha512-odATx0ZL/Kis10sKSBiKiGQxAB6coSi/KQtKcMhnQVNno6FkRh5/4e5BqcEvpq2rNMTiQp4ytNAQHtdwbPXvGA=="], "expo-device": ["expo-device@56.0.4", "", { "dependencies": { "ua-parser-js": "^0.7.33" }, "peerDependencies": { "expo": "*" } }, "sha512-ucVcGPkvBrl2QHuy7XcYex2Y6BETvJ6TREutZrwLGUDnlvbpKS8KfQoNZOpvkyo5Nmm9RrasYQ0CrXmBHho2mg=="], - "expo-doctor": ["expo-doctor@1.19.7", "", { "bin": { "expo-doctor": "bin/expo-doctor.js" } }, "sha512-pzn7QtCifRlvGIQz8k7kszeYFaI5Yn81WTHlk/20tmd3jwnXxPjlcdyhFSkuRtO2v4a9gA/6aUWVBOosfffj9w=="], + "expo-doctor": ["expo-doctor@1.19.9", "", { "bin": { "expo-doctor": "bin/expo-doctor.js" } }, "sha512-SJW5HxEDQ9f5QdFvrUwfbdJZ4HI0EAAxsrJqrHBFjKBum+uSOcEIZPLRibwNQLTHOwTO1TWNLiMlF9sDUBWeYw=="], - "expo-file-system": ["expo-file-system@56.0.7", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-dcKzo8ShPloM7jgfnMcJStgQebhP8owVjCkNI/aX6NMFV1CYB8bxKGMdnzJ3mXk5nfaiW+F/lSKr2UIJ02WAUA=="], + "expo-file-system": ["expo-file-system@56.0.8", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-NrH41/8snGIBSbYicwVLB4txPdgCATd7ZYhMAGS3YJZ9GbnduhlAoV4/YCbGayjrbpE9bJb/6wegPL/zmvRMnQ=="], - "expo-font": ["expo-font@56.0.5", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-WLoDu9hlEgPRKXJRR01HFLJ6Z2tFcORX/WFPRYBndmYc5kjQrFGH/j4BRaF3aBRPyYEAUXiUJybNLXkKCwEXQw=="], + "expo-font": ["expo-font@56.0.7", "", { "dependencies": { "fontfaceobserver": "^2.1.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-hpU/vRwPzsby9lPGkA4blDqLIIXYzoWnCZHr6PxvcWbY/uPObAiyhh6q+e0WYsB65SthK+PLH95jEnVag7fwEg=="], "expo-glass-effect": ["expo-glass-effect@56.0.4", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-xI9rXtDwi7RW82uAlfyaXO6+k21ApWJ2tHAWYqPr/FjfmZbKsgNJ4Q0iZzGPCwboqjTGxaRZ61SZxBl8hDt5iA=="], "expo-haptics": ["expo-haptics@56.0.3", "", { "peerDependencies": { "expo": "*" } }, "sha512-ycoahZJnR9tWAVh/0mJYxbETtHRYaWjiWS8cHlP6aDGU6Q6Y8rZ5NKsuBwWw6HR2Pe30mfVFgbF2HrBR6gtYmw=="], - "expo-image": ["expo-image@56.0.9", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-FifiRehXnMul5XeUVHWv+COHFUeCAdsYf5MiCPUBlhr4pRb0sxjA4/floi/TEDpATOIw6GqxbrC4FdZBoyrJmw=="], + "expo-image": ["expo-image@56.0.11", "", { "dependencies": { "sf-symbols-typescript": "^2.2.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-k2xwxGk14xi6zxmEGAU4rUTb1lK5qf0y0Qb8+Jaggnul0KaJJxcq9qvyDp9iyJBW35cp9isONAUnNtIiooZ/Pw=="], "expo-json-utils": ["expo-json-utils@56.0.0", "", {}, "sha512-lUqyv9aIGDbYTQ5Nux2FnH2/Dz0w5uJ8Pr080eS0StXi2jr5OmuMNErpzUnpfnYOU55xKotd4AHv68PfV/ludg=="], @@ -987,41 +978,41 @@ "expo-linear-gradient": ["expo-linear-gradient@56.0.4", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-KUp1dNSRtuMyiExhf6FJf5YUtmw2cRaPytl10HQi7isj5Yac38udmD55T2tglNYTZlvgT5+oflpyFoH15hmOcw=="], - "expo-linking": ["expo-linking@56.0.12", "", { "dependencies": { "expo-constants": "~56.0.16", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-EJ+YoazVqlrUXMAARo1iTExpqEGjuKJDGiE/P1K+A3m5hs+2Uf8F9ucqpq9k5dizeiaV2D8B9+uLvqMHFzGGsQ=="], + "expo-linking": ["expo-linking@56.0.14", "", { "dependencies": { "expo-constants": "~56.0.18", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-IvVQHWC+Cj4fK5qD3iEVYqpU2a4rLW0IpAAlGJ4MH+H1fyZiHh3eN6qg2WmoclOEPfYATSuEa+dQT6wfgVpXlQ=="], "expo-localization": ["expo-localization@56.0.6", "", { "dependencies": { "rtl-detect": "^1.0.2" }, "peerDependencies": { "expo": "*", "react": "*" } }, "sha512-zzBVoUFHCVNBywcxGsspoZeIXebihOo/AnmQYE4jMv8gHCSKlLNFT+ft+0+mWcZCMs9necvUs8S8TDonAu/xBA=="], - "expo-location": ["expo-location@56.0.14", "", { "dependencies": { "@expo/image-utils": "^0.10.1" }, "peerDependencies": { "expo": "*" } }, "sha512-k9p6mR11o5S0R4yUs3uWLJfnSk6XIB9UIgSYiNu2goGLWb2f0sazuZ0iYhuc2p2wIsdidhpL/51ZXjtZl5JCOg=="], + "expo-location": ["expo-location@56.0.18", "", { "dependencies": { "@expo/image-utils": "^0.10.1" }, "peerDependencies": { "expo": "*" } }, "sha512-6xP0UwGy8a7EEHAMeigYAp3HNo3yWHAg05tVPUfwrOWepWPpFXmjsfUBUxQdkpfpjddJ9r+f4PplxZqKI0LtjA=="], "expo-manifests": ["expo-manifests@56.0.4", "", { "dependencies": { "expo-json-utils": "~56.0.0" }, "peerDependencies": { "expo": "*" } }, "sha512-Fokawl2UkiExIF0bqGoblRFA8lYpROVD+EpvDwSW4LgqQyPwNua1gLSgHZjdl5GsVugfRMMWE3LHaibDyX93hw=="], - "expo-modules-autolinking": ["expo-modules-autolinking@56.0.14", "", { "dependencies": { "@expo/require-utils": "^56.1.3", "@expo/spawn-async": "^1.8.0", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-9ugtZkheNPYDkW4DZopY1rH2BCbUICaafUEPxRgbLDR5UNRF5K3cdHMIMEt8pxZPq2+eX4wCm+6pbSvdY/DPHg=="], + "expo-modules-autolinking": ["expo-modules-autolinking@56.0.16", "", { "dependencies": { "@expo/require-utils": "^56.1.3", "@expo/spawn-async": "^1.8.0", "chalk": "^4.1.0", "commander": "^7.2.0" }, "bin": { "expo-modules-autolinking": "bin/expo-modules-autolinking.js" } }, "sha512-9JnL4N46P8ubDpDIfWolDn7nxU2j1rY67xY/dNVuyH0m+HG+r/JI16VYtjIf4COpZtEuFo4D3h3MBeFzGucMnw=="], - "expo-modules-core": ["expo-modules-core@56.0.13", "", { "dependencies": { "@expo/expo-modules-macros-plugin": "~0.0.9", "expo-modules-jsi": "~56.0.7", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-3Hgpi9Q1O0XqoesQtgFY7qhfDsNA3bJtdCJotEqdE42+N8Zv/LJACbNgIyFN/XrnMDzfF5rozh0vNWaRT0/eXQ=="], + "expo-modules-core": ["expo-modules-core@56.0.17", "", { "dependencies": { "@expo/expo-modules-macros-plugin": "0.2.2", "expo-modules-jsi": "~56.0.10", "invariant": "^2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": "^0.7.4 || ^0.8.0" }, "optionalPeers": ["react-native-worklets"] }, "sha512-5J8whnT7Ccp+BrFClLmpF76omBqn95VZExroTm01Dgjm4vpty1Rb7U3we+ZUceNHtRd07Lw30u7FNfDgIhEbRQ=="], - "expo-modules-jsi": ["expo-modules-jsi@56.0.7", "", { "peerDependencies": { "react-native": "*" } }, "sha512-iBAj4Xeh/8HT201VVxFlmf+VBfmtQV1ZUoJdLQQENm0+j9gnD2QswZLJyNo3CmNNXl46esJeLR5lpGpYZts/zA=="], + "expo-modules-jsi": ["expo-modules-jsi@56.0.10", "", { "peerDependencies": { "react-native": "*" } }, "sha512-fHZcFpYO/o62GYa6fJyAQJZcAShzhoN0iMMDzbr7vD3ewET6e1vAlTonbEakN9F0VHEgBFJ4NREy87uwVcpCuA=="], - "expo-notifications": ["expo-notifications@56.0.14", "", { "dependencies": { "@expo/image-utils": "^0.10.1", "abort-controller": "^3.0.0", "badgin": "^1.1.5", "expo-application": "~56.0.3", "expo-constants": "~56.0.16" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-A+BDJYyBIkC17Bfqlrbf9A80npjOyoTbaSCydP2agfhVv+Ld7DuOYOJSApBmtzBZM0LvdUVX/pdrwjEp1ixmaw=="], + "expo-notifications": ["expo-notifications@56.0.18", "", { "dependencies": { "@expo/image-utils": "^0.10.1", "abort-controller": "^3.0.0", "badgin": "^1.1.5", "expo-application": "~56.0.3", "expo-constants": "~56.0.18" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-HHnrwyCLC5srFojcHYS2KskbNroy9o2fwPKdyhjrdjjrBu4sNRKm4LepcuZjDy98cZKEm89WIPW8O45vut8Rgw=="], - "expo-router": ["expo-router@56.2.7", "", { "dependencies": { "@expo/log-box": "^56.0.12", "@expo/metro-runtime": "^56.0.13", "@expo/schema-utils": "^56.0.0", "@expo/ui": "^56.0.14", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-native-masked-view/masked-view": "^0.3.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "client-only": "^0.0.1", "color": "^4.2.3", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^56.0.4", "expo-server": "^56.0.4", "expo-symbols": "^56.0.5", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-is": "^19.1.0", "react-native-drawer-layout": "^4.2.2", "react-native-screens": "^4.25.2", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "vaul": "^1.1.2" }, "peerDependencies": { "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^56.0.16", "expo-linking": "^56.0.12", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-T7MSugHfj6XDrVJG8dCkP5EEAWeCkPrkkxqKCqCRokXmBKTAiRGXsmPsgHzOXhr/5MxGDJXhj5ON19uWoCevDA=="], + "expo-router": ["expo-router@56.2.11", "", { "dependencies": { "@expo/log-box": "^56.0.13", "@expo/metro-runtime": "^56.0.15", "@expo/schema-utils": "^56.0.0", "@expo/ui": "^56.0.18", "@radix-ui/react-slot": "^1.2.0", "@radix-ui/react-tabs": "^1.1.12", "@react-native-masked-view/masked-view": "^0.3.2", "@testing-library/jest-dom": "^6.9.1", "@testing-library/user-event": "^14.6.1", "client-only": "^0.0.1", "color": "^4.2.3", "debug": "^4.3.4", "escape-string-regexp": "^4.0.0", "expo-glass-effect": "^56.0.4", "expo-server": "^56.0.5", "expo-symbols": "^56.0.6", "fast-deep-equal": "^3.1.3", "invariant": "^2.2.4", "nanoid": "^3.3.8", "query-string": "^7.1.3", "react-fast-compare": "^3.2.2", "react-is": "^19.1.0", "react-native-drawer-layout": "^4.2.2", "react-native-screens": "^4.25.2", "server-only": "^0.0.1", "sf-symbols-typescript": "^2.1.0", "shallowequal": "^1.1.0", "standard-navigation": "^0.0.5", "vaul": "^1.1.2" }, "peerDependencies": { "@testing-library/react-native": ">= 13.2.0", "expo": "*", "expo-constants": "^56.0.18", "expo-linking": "^56.0.14", "react": "*", "react-dom": "*", "react-native": "*", "react-native-gesture-handler": "*", "react-native-reanimated": "*", "react-native-safe-area-context": ">= 5.4.0", "react-native-web": "*", "react-server-dom-webpack": "~19.0.4 || ~19.1.5 || ~19.2.4" }, "optionalPeers": ["@testing-library/react-native", "react-dom", "react-native-gesture-handler", "react-native-reanimated", "react-native-web", "react-server-dom-webpack"] }, "sha512-08DBTrKv3QanOc9u1JNxSEChW9c/qNFbQ0dO28OLvufWWfdSRkSdHmh365D2FgoZg1qaOzZPCDuL3tM6nGSfkQ=="], "expo-screen-orientation": ["expo-screen-orientation@56.0.5", "", { "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-Puf4L/cgM8z45Z2fwZzJtlVGSk0ZM/l3gBqXm50bKTACmUk8P8fr7HVbDfs8reyoZuEKKFZJ0VlnKo5i6cSotQ=="], "expo-secure-store": ["expo-secure-store@56.0.4", "", { "peerDependencies": { "expo": "*" } }, "sha512-hjEi/gmpdFFJ9lYbdp3k3p/WchV7Gi0Qt8jt/m/0WJadqQrskafHAlDxbZkII1cN3Yd7zp9Lvkeq3UfGhSwirQ=="], - "expo-server": ["expo-server@56.0.4", "", {}, "sha512-4dJ57KuAwDl7eQGD6aG9kTzBIftWAfHH1+6Zxy7NcPCBrKYis3/H5enGUz1asH8HHhONXfJ5BdJqfEWAEAgWxA=="], + "expo-server": ["expo-server@56.0.5", "", {}, "sha512-SmM2p2g3Jrktpiazcst+OxhjSzOHXKAY4BPURHYHXvApzzoybMmrNF4IEZ8DKZ145BhSe4ydAmlEFCRTsdtgUQ=="], - "expo-sharing": ["expo-sharing@56.0.14", "", { "dependencies": { "@expo/config-plugins": "^56.0.8", "@expo/config-types": "^56.0.5", "@expo/plist": "^0.7.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-Hu7pm3U9vn9NFGBe5EUM6ct6wBhAc7Zgl5koOYpJnMvL6n85bkIA8sLvvxB6V+p4JRoh3TD6xXpOIr23qwsV2w=="], + "expo-sharing": ["expo-sharing@56.0.18", "", { "dependencies": { "@expo/config-plugins": "^56.0.9", "@expo/config-types": "^56.0.6", "@expo/plist": "^0.7.0" }, "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-45w4BWNFmdTczp+fJX6YfwJrn9sX+VeRWz2VWLhauygcCrym44HtVDXX5yVYPB9TW9ZesLcEI+CCrCBNWL7smQ=="], "expo-splash-screen": ["expo-splash-screen@56.0.10", "", { "dependencies": { "@expo/config-plugins": "~56.0.8", "@expo/image-utils": "^0.10.1", "xml2js": "0.6.0" }, "peerDependencies": { "expo": "*" } }, "sha512-vDIlo8hzt9HlCZQ0kSY66v83D1WEXOJbVMeyPDfXDu9tbDdPMNUyDpi4WGJXikAjxnAKfbt5Mv5NnEbxINy+VA=="], "expo-status-bar": ["expo-status-bar@56.0.4", "", { "peerDependencies": { "expo": "*", "react": "*", "react-native": "*" } }, "sha512-IGs/fDfkHXofy2ZQrGiXayhFK04HB85FZXorhcEhDZEcqASKgSqpak+HwUtAaR0MeTJwWyHNF7I6VmVbbp8EcA=="], - "expo-symbols": ["expo-symbols@56.0.5", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-RIukH0Xo80C7RU8qreipL2SPy2Py+Km8JFPbCmbPQpHkM3DW9Znlmg6VfhzbtUOlO5EuNSF0lAJ3l2VJi6qYrw=="], + "expo-symbols": ["expo-symbols@56.0.6", "", { "dependencies": { "@expo-google-fonts/material-symbols": "^0.4.1", "sf-symbols-typescript": "^2.0.0" }, "peerDependencies": { "expo": "*", "expo-font": "*", "react": "*", "react-native": "*" } }, "sha512-BrA81DjcNafdj7gXVhdrExb9LtUiSVyOf/NavyMmDAHgHMY1GqeR5cnn1PSAZeYKnSgQhee/H89XUpAxtog5hg=="], "expo-system-ui": ["expo-system-ui@56.0.5", "", { "dependencies": { "@react-native/normalize-colors": "0.85.3", "debug": "^4.3.2" }, "peerDependencies": { "expo": "*", "react-native": "*", "react-native-web": "*" }, "optionalPeers": ["react-native-web"] }, "sha512-n1MmnUArV4cc3gVed9fGtluPme00PE9axKVx+NHbKxHFMam5l4GcOI7PxbYKFNx8o7WA1LRD7eLW33agmZrxGg=="], - "expo-task-manager": ["expo-task-manager@56.0.15", "", { "dependencies": { "unimodules-app-loader": "~56.0.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-8vbKYocXJHv27++9AubVaEvVujTdt5Z10XddaxHAhWO60uw1Zom6yRjSAayRbZ5hNFA1c72KfA2vOETXZR9IGg=="], + "expo-task-manager": ["expo-task-manager@56.0.19", "", { "dependencies": { "unimodules-app-loader": "~56.0.0" }, "peerDependencies": { "expo": "*", "react-native": "*" } }, "sha512-eDeBR8vXlOAXBck29AzPl+tv4QlJus+cgkQ0TGOBqAlgRPWPWd7ebhqrhb0KRieUZIvzlycfcxjHR/+AiEiMHA=="], "expo-updates-interface": ["expo-updates-interface@56.0.2", "", { "peerDependencies": { "expo": "*" } }, "sha512-eWTwSZ9y8vrULG2oBn2TQSSIwBGSq/TxGJ3jY6tuVS2FWH/ASRIiKs3zkUZTRoC3ZuV2alz0mUClYV7nNrFx8g=="], @@ -1037,7 +1028,7 @@ "fast-xml-builder": ["fast-xml-builder@1.2.0", "", { "dependencies": { "path-expression-matcher": "^1.5.0", "xml-naming": "^0.1.0" } }, "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q=="], - "fast-xml-parser": ["fast-xml-parser@5.8.0", "", { "dependencies": { "@nodable/entities": "^2.1.0", "fast-xml-builder": "^1.2.0", "path-expression-matcher": "^1.5.0", "strnum": "^2.3.0", "xml-naming": "^0.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg=="], + "fast-xml-parser": ["fast-xml-parser@5.9.0", "", { "dependencies": { "@nodable/entities": "^2.2.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^1.0.1", "path-expression-matcher": "^1.5.0", "strnum": "^2.4.0", "xml-naming": "^0.1.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-duBuXbyIhEeNO4GjFuVqr0nF047oNwr18aum+zJyqo0MUG/n7Afgs3Qv3D6VN3ONedUKxiuFlPiMGIa0Z11chA=="], "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], @@ -1067,13 +1058,13 @@ "flow-enums-runtime": ["flow-enums-runtime@0.0.6", "", {}, "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw=="], - "follow-redirects": ["follow-redirects@1.16.0", "", {}, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], + "follow-redirects": ["follow-redirects@1.16.0", "", { "peerDependencies": { "debug": "*" }, "optionalPeers": ["debug"] }, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], "fontfaceobserver": ["fontfaceobserver@2.3.0", "", {}, "sha512-6FPvD/IVyT4ZlNe7Wcn5Fb/4ChigpucKYSvD6a+0iMoLn2inpo711eyIcKjmDtE5XNcgAkSH9uN/nfAeZzHEfg=="], "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + "form-data": ["form-data@4.0.6", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="], "fresh": ["fresh@0.5.2", "", {}, "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="], @@ -1117,7 +1108,7 @@ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], - "hasown": ["hasown@2.0.3", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg=="], + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], "hermes-compiler": ["hermes-compiler@250829098.0.10", "", {}, "sha512-TcRlZ0/TlyfJqquRFAWoyElVNnkdYRi/sEp4/Qy8/GYxjg8j2cS9D4MjuaQ+qimkmLN7AmO+44IznRf06mAr0w=="], @@ -1141,7 +1132,7 @@ "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], - "i18next": ["i18next@26.3.0", "", { "peerDependencies": { "typescript": "^5 || ^6" }, "optionalPeers": ["typescript"] }, "sha512-gHSgGpUXVmuqE2El1W61DmxeyeTlFfZgdJRWMo9jScAn5pu7TuTuiccb1zh3E2J9hEBVGJ23+96x0ieBhfuIHA=="], + "i18next": ["i18next@26.3.1", "", { "peerDependencies": { "typescript": "^5 || ^6" }, "optionalPeers": ["typescript"] }, "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ=="], "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], @@ -1185,6 +1176,8 @@ "is-unicode-supported": ["is-unicode-supported@0.1.0", "", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + "is-unsafe": ["is-unsafe@1.0.1", "", {}, "sha512-CLK2+VdgERgD96EYm5lUQssZYlRg2tkZnbsxZoacmSiRxiFJ4Nk4SzjCl+Ur+v3kXIY9dTIdb3IH22y1mZ56LA=="], + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], @@ -1213,7 +1206,7 @@ "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], - "joi": ["joi@17.13.3", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA=="], + "joi": ["joi@17.13.4", "", { "dependencies": { "@hapi/hoek": "^9.3.0", "@hapi/topo": "^5.1.0", "@sideway/address": "^4.1.5", "@sideway/formula": "^3.0.1", "@sideway/pinpoint": "^2.0.0" } }, "sha512-1RuuER6kmt8K8I3nIWvPZKi5RQCb568ZPyY4Pwjlua+yo+63ZTmIwxLZH0heBmiKN4uxjvCiarDrjaeH84xicQ=="], "jotai": ["jotai@2.20.0", "", { "peerDependencies": { "@babel/core": ">=7.0.0", "@babel/template": ">=7.0.0", "@types/react": ">=17.0.0", "react": ">=17.0.0" }, "optionalPeers": ["@babel/core", "@babel/template", "@types/react", "react"] }, "sha512-b5GAqgmXmXzB4WPaTH26ppk9Sl7AA9WSQX7yfdM+gJ1rFROiWcVbi97gFuN/yVCojOcbcvop2sfLL+fjxW0JVg=="], @@ -1221,7 +1214,7 @@ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], - "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="], + "js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="], "jsc-safe-url": ["jsc-safe-url@0.2.4", "", {}, "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q=="], @@ -1243,7 +1236,7 @@ "lan-network": ["lan-network@0.2.1", "", { "bin": { "lan-network": "dist/lan-network-cli.js" } }, "sha512-ONPnazC96VKDntab9j9JKwIWhZ4ZUceB4A9Epu4Ssg0hYFmtHZSeQ+n15nIwTFmcBUKtExOer8WTJ4GF9MO64A=="], - "launch-editor": ["launch-editor@2.13.2", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.3" } }, "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg=="], + "launch-editor": ["launch-editor@2.14.1", "", { "dependencies": { "picocolors": "^1.1.1", "shell-quote": "^1.8.4" } }, "sha512-QWBrQsMpH7gPr965dsKD/3cKWiNoTjpATQf++Xq63N6sKRGMwlVXz41O1IZTMfZQgBctD/K5Zt06+/I6pP6+HA=="], "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], @@ -1369,10 +1362,6 @@ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], - "msgpackr": ["msgpackr@2.0.2", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-c5hYOXFbP79Slh6Dzd2wzk+jnV7mX1UxfMYtilnY1NmalXPqG8DGb5cYCMBrW4AsH3zekBBZd4QrKz9NhtvYLQ=="], - - "msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="], - "multitars": ["multitars@1.0.0", "", {}, "sha512-H/J4fMLedtudftaYMOg7ajzLYgT3/rwbWVJbqr/iUgB8DQztn38ys5HOqI1CzSxx8QhXXwOOnnBvd4v3jG5+Mg=="], "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], @@ -1389,11 +1378,9 @@ "node-forge": ["node-forge@1.4.0", "", {}, "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ=="], - "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], - "node-int64": ["node-int64@0.4.0", "", {}, "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="], - "node-releases": ["node-releases@2.0.46", "", {}, "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ=="], + "node-releases": ["node-releases@2.0.47", "", {}, "sha512-Uzmd6LXpouKo8EUK68IjH4+E01w/hXyV3R3g/geCJo+rXLNfh1xucB+LOzYEOQPSiUK3h/xZf0cQGcSsmyL2Og=="], "node-stream-zip": ["node-stream-zip@1.15.0", "", {}, "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw=="], @@ -1493,7 +1480,7 @@ "postcss-nested": ["postcss-nested@5.0.6", "", { "dependencies": { "postcss-selector-parser": "^6.0.6" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA=="], - "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], + "postcss-selector-parser": ["postcss-selector-parser@6.1.4", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ=="], "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], @@ -1541,7 +1528,7 @@ "react-i18next": ["react-i18next@17.0.8", "", { "dependencies": { "@babel/runtime": "^7.29.2", "html-parse-stringify": "^3.0.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "i18next": ">= 26.2.0", "react": ">= 16.8.0", "react-dom": "*", "react-native": "*", "typescript": "^5 || ^6" }, "optionalPeers": ["react-dom", "react-native", "typescript"] }, "sha512-0ooKbGLU8JXhe1zwpQUWIeXSgLPOfwJmgheWRIUpcoA0CpyabpGhayjdG+/eA5esC1AQ8h2jWpXjJfzQzeDOCw=="], - "react-is": ["react-is@19.2.6", "", {}, "sha512-XjBR15BhXuylgWGuslhDKqlSayuqvqBX91BP8pauG8kd1zY8kotkNWbXksTCNRarse4kuGbe2kIY05ARtwNIvw=="], + "react-is": ["react-is@19.2.7", "", {}, "sha512-kZFnouyVv7eP/Phmrlo9FK+zcAdriZJvzxXHF1Sl1P377WSGe2G/JxVolhTrB/jeV47lKImhNUsijjHAAbcl/A=="], "react-native": ["react-native-tvos@0.85.3-0", "", { "dependencies": { "@react-native-tvos/virtualized-lists": "0.85.3-0", "@react-native/assets-registry": "0.85.3", "@react-native/codegen": "0.85.3", "@react-native/community-cli-plugin": "0.85.3", "@react-native/gradle-plugin": "0.85.3", "@react-native/js-polyfills": "0.85.3", "@react-native/normalize-colors": "0.85.3", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-plugin-syntax-hermes-parser": "0.33.3", "base64-js": "^1.5.1", "commander": "^12.0.0", "flow-enums-runtime": "^0.0.6", "hermes-compiler": "250829098.0.10", "invariant": "^2.2.4", "memoize-one": "^5.0.0", "metro-runtime": "^0.84.3", "metro-source-map": "^0.84.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.1.5", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.27.0", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "tinyglobby": "^0.2.15", "whatwg-fetch": "^3.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "peerDependencies": { "@react-native/jest-preset": "0.85.3", "@types/react": "^19.1.1", "react": "^19.2.3" }, "optionalPeers": ["@react-native/jest-preset", "@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-Q9gUndppXbGEiYlQ8eudkdH7rDXdY+KM74Btd5xqMvXHgo7ZXdwI1hKvStmI47KmTaDn0NOmcRl2yBwHfc5+5A=="], @@ -1559,7 +1546,7 @@ "react-native-draggable-flatlist": ["react-native-draggable-flatlist@4.0.3", "", { "dependencies": { "@babel/preset-typescript": "^7.17.12" }, "peerDependencies": { "react-native": ">=0.64.0", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=2.8.0" } }, "sha512-2F4x5BFieWdGq9SetD2nSAR7s7oQCSgNllYgERRXXtNfSOuAGAVbDb/3H3lP0y5f7rEyNwabKorZAD/SyyNbDw=="], - "react-native-drawer-layout": ["react-native-drawer-layout@4.2.4", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-l1Le5HcVidobnJm8xqFZo46Rs8FDHdxbTZhkjxpNSRgU+QMoQXilOfzTHAeNjEGiKVGgIs9cW3ctXeHqgp5jJg=="], + "react-native-drawer-layout": ["react-native-drawer-layout@4.2.5", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-gesture-handler": ">= 2.0.0", "react-native-reanimated": ">= 2.0.0" } }, "sha512-Yl82uLkXjXuq7222hWGIDsq5A6R/bsCeCEgdIxQUxAEHf00oRdDnRByLx3Fsij3qwtmYNPGrHV1NH8G8hbCbLQ=="], "react-native-edge-to-edge": ["react-native-edge-to-edge@1.8.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-bhvsKqeX9PGkY9wBUk9vni/tJNJdKtLPbs/j3e/3CdV4JmUWfTXYYoL+4Hc8Wmej+5eJxkc8KOFa454ruFWBCA=="], @@ -1597,9 +1584,9 @@ "react-native-tab-view": ["react-native-tab-view@4.3.0", "", { "dependencies": { "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0" } }, "sha512-qPMF75uz/7+MuVG2g+YETdGMzlWZnhC6iI4h/7EBbwIBwNBIBi2z4OA6KhY3IOOBwGHXEIz5IyA6doDqifYBHg=="], - "react-native-text-ticker": ["react-native-text-ticker@1.15.0", "", {}, "sha512-d/uK+PIOhsYMy1r8h825iq/nADiHsabz3WMbRJSnkpQYn+K9aykUAXRRhu8ZbTAzk4CgnUWajJEFxS5ZDygsdg=="], + "react-native-text-ticker": ["react-native-text-ticker@1.16.0", "", {}, "sha512-UHZcIrXzNQ3CnGSA6d5foR9weqSCEk5w+eJGnUf5OQkKbuq/xtt1ZaNVnsgcG5+3f9EnRrNCt52/a46LXVKGGw=="], - "react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#33a3ecd", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-33a3ecd"], + "react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#33a3ecd", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-33a3ecd", "sha512-vfkld2jUj7EPkAjIc/Vbx4Q4MtOOLmYtCYCE2dWJsyLnPqgj1f0xVzBxbeVP7dfT+eSh4KIXfdxESXaHgrXIlw=="], "react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="], @@ -1643,7 +1630,7 @@ "regjsgen": ["regjsgen@0.8.0", "", {}, "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q=="], - "regjsparser": ["regjsparser@0.13.1", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw=="], + "regjsparser": ["regjsparser@0.13.2", "", { "dependencies": { "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ=="], "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], @@ -1701,7 +1688,7 @@ "shell-quote": ["shell-quote@1.8.4", "", {}, "sha512-VsC6n6vz1ihYYyZZwX7YZSF5l5x36ca17OC+a69h94YqB7X6XLwf+5MOgynYir2SLFUbl8gIYvBo8K8RoNQ6bQ=="], - "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], @@ -1739,6 +1726,8 @@ "stacktrace-parser": ["stacktrace-parser@0.1.11", "", { "dependencies": { "type-fest": "^0.7.1" } }, "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg=="], + "standard-navigation": ["standard-navigation@0.0.7", "", {}, "sha512-NCGLCNyuXrFOkGHxdNZFnpsehGtiq1oXbPhKl7ZuxFO5J//H2evqqOchmD4YwEUJnkjO4kH9Xp4hQX6hdAYCKQ=="], + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], "stream-buffers": ["stream-buffers@2.2.0", "", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="], @@ -1759,7 +1748,7 @@ "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], - "strnum": ["strnum@2.3.0", "", {}, "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q=="], + "strnum": ["strnum@2.4.0", "", { "dependencies": { "anynum": "^1.0.0" } }, "sha512-sHrVyWWdq28RbhjuJdZsA1SnGRJV6NiXbk6AXBxDOsgAcA+lmpUZCYjOdLBxkXMwis6RRe7dlZt4VlIWFVzkmg=="], "strtok3": ["strtok3@6.3.0", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^4.1.0" } }, "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw=="], @@ -1795,9 +1784,9 @@ "tinycolor2": ["tinycolor2@1.6.0", "", {}, "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="], - "tinyexec": ["tinyexec@1.2.2", "", {}, "sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g=="], + "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="], - "tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="], + "tinyglobby": ["tinyglobby@0.2.17", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g=="], "tmp": ["tmp@0.2.7", "", {}, "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw=="], @@ -1823,7 +1812,7 @@ "type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="], - "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], "ua-parser-js": ["ua-parser-js@0.7.41", "", { "bin": { "ua-parser-js": "script/cli.js" } }, "sha512-O3oYyCMPYgNNHuO7Jjk3uacJWZF8loBgwrfd/5LE/HyZ3lUIOdniQ7DNXJcIgZbwioZxk0fLfI4EVnetdiX5jg=="], @@ -1919,7 +1908,7 @@ "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], - "zxing-wasm": ["zxing-wasm@3.0.3", "", { "dependencies": { "@types/emscripten": "^1.41.5", "type-fest": "^5.6.0" } }, "sha512-DdOn/G5F+qvZELWeO5ZFFwcN611TfMybxPV0LUUoutUmiH2t47MZSB7gLV9O9YLhvudBdnzQNAoFOu4Xz8eOrQ=="], + "zxing-wasm": ["zxing-wasm@3.1.0", "", { "dependencies": { "@types/emscripten": "^1.41.5", "type-fest": "^5.7.0" } }, "sha512-5+3V1wPRx4gvbeLH2jB7n2cKrYJ1q4i3QgjnBUtrDPeqxJSi6BdzKJg4y6aF6bgW8zfntnYJyrkqFMevDhL2NA=="], "@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="], @@ -1935,7 +1924,7 @@ "@expo/cli/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="], - "@expo/cli/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@expo/cli/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@expo/cli/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], @@ -1947,13 +1936,13 @@ "@expo/config/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "@expo/config/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@expo/config/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@expo/config-plugins/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="], "@expo/config-plugins/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "@expo/config-plugins/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@expo/config-plugins/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@expo/devcert/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], @@ -1963,13 +1952,11 @@ "@expo/fingerprint/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "@expo/fingerprint/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@expo/fingerprint/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@expo/image-utils/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="], - "@expo/image-utils/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], - - "@expo/metro-config/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], + "@expo/image-utils/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@expo/metro-config/getenv": ["getenv@2.0.0", "", {}, "sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ=="], @@ -1977,42 +1964,38 @@ "@expo/package-manager/ora": ["ora@3.4.0", "", { "dependencies": { "chalk": "^2.4.2", "cli-cursor": "^2.1.0", "cli-spinners": "^2.0.0", "log-symbols": "^2.2.0", "strip-ansi": "^5.2.0", "wcwidth": "^1.0.1" } }, "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg=="], - "@expo/prebuild-config/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@expo/prebuild-config/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], - "@expo/require-utils/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], - - "@jest/types/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], + "@expo/ws-tunnel/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], "@jimp/png/pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], - "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + "@react-native-community/cli/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], - "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - - "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], - - "@react-native-community/cli/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], - - "@react-native-community/cli-doctor/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@react-native-community/cli-doctor/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "@react-native-community/cli-server-api/open": ["open@6.4.0", "", { "dependencies": { "is-wsl": "^1.1.0" } }, "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg=="], "@react-native-community/cli-server-api/ws": ["ws@6.2.4", "", { "dependencies": { "async-limiter": "~1.0.0" } }, "sha512-PNIUUyLI5YpkJZj60YBzX1o0ByQ4ovvfmq9N/Kig/PAYbVlGyz4R6G0SEWrD0O9acc0sT2+IdMBVLFv8FSi0Nw=="], - "@react-native-community/cli-tools/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@react-native-community/cli-tools/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], - "@react-native/babel-preset/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.86.0", "", { "dependencies": { "@babel/traverse": "^7.29.0", "@react-native/codegen": "0.86.0" } }, "sha512-qdsABWNW7uTll90l4Vh03gjeyu3WVDi2CyiiyvYGMRDcoYbjbQi6df3BMAm9lQI2yslZ1T14LlDDAsgTwNxplA=="], - "@react-native/codegen/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], + "@react-native/babel-preset/babel-plugin-syntax-hermes-parser": ["babel-plugin-syntax-hermes-parser@0.36.0", "", { "dependencies": { "hermes-parser": "0.36.0" } }, "sha512-LhD0xdoedDw7ansQgXbB2DADLZIK/LRXuWNBPuVzMc5S2WK5GyT89tCM+cQzxFGO0mGyLK6D5TrVOJJzAoDy8Q=="], - "@react-native/community-cli-plugin/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "@react-native/community-cli-plugin/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], - "@react-native/metro-babel-transformer/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], + "@react-native/metro-babel-transformer/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="], + + "@react-native/metro-config/@react-native/js-polyfills": ["@react-native/js-polyfills@0.86.0", "", {}, "sha512-zYy/Cjd1VTnZ2iCNaG9bDF9C3l2ntESiPRscjIlI5FKugu6aeTwsDSv1aI8Bc4Kp3vEdoVg+UQhLAhE4svREaQ=="], "@react-navigation/elements/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], "@react-navigation/material-top-tabs/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + "@tanstack/react-query/@tanstack/query-core": ["@tanstack/query-core@5.100.14", "", {}, "sha512-5X41dGpxgeaHISCRW2oYwcSycZeULZzAunaudXT9ov1KOTj9xwt0CH6hbwqP1/z74ZWF7rYFnDpyYH07XFcZew=="], + "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], @@ -2035,14 +2018,12 @@ "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "chrome-launcher/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], - - "chromium-edge-launcher/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], - "cli-truncate/string-width": ["string-width@8.2.1", "", { "dependencies": { "get-east-asian-width": "^1.5.0", "strip-ansi": "^7.1.2" } }, "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA=="], "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + "compressible/mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + "compression/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], "connect/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2051,12 +2032,14 @@ "error-ex/is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], - "expo-build-properties/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "expo-build-properties/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "expo-modules-autolinking/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="], "expo-router/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + "expo-router/standard-navigation": ["standard-navigation@0.0.5", "", {}, "sha512-YAmzwAiiQVocZxO/VGPFiQHcu5pKiz09QIGC0MK6aRMoa3E0QkoTQgcqJr7ZZ3OMiNhu4DkaGElFI5htjOIDbw=="], + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "fbjs/promise": ["promise@7.3.1", "", { "dependencies": { "asap": "~2.0.3" } }, "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg=="], @@ -2083,12 +2066,8 @@ "jest-message-util/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], - "jest-util/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], - "jest-util/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], - "jest-worker/@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="], - "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], "lighthouse-logger/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2103,8 +2082,6 @@ "logkitty/yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], - "metro/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], - "metro/accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], "metro/ci-info": ["ci-info@2.0.0", "", {}, "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ=="], @@ -2113,29 +2090,23 @@ "metro/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], - "metro-babel-transformer/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], - "metro-babel-transformer/hermes-parser": ["hermes-parser@0.35.0", "", { "dependencies": { "hermes-estree": "0.35.0" } }, "sha512-9JLjeHxBx8T4CAsydZR49PNZUaix+WpQJwu9p2010lu+7Kwl6D/7wYFFJxoz+aXkaaClp9Zfg6W6/zVlSJORaA=="], "metro-cache/https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], - "metro-transform-plugins/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], - - "metro-transform-worker/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], - "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "nativewind/@babel/types": ["@babel/types@7.19.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.18.10", "@babel/helper-validator-identifier": "^7.18.6", "to-fast-properties": "^2.0.0" } }, "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA=="], "nativewind/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], - "npm-package-arg/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "npm-package-arg/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "parse-png/pngjs": ["pngjs@3.4.0", "", {}, "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="], "patch-package/fs-extra": ["fs-extra@10.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], - "patch-package/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "patch-package/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "path-scurry/lru-cache": ["lru-cache@11.5.1", "", {}, "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A=="], @@ -2155,17 +2126,17 @@ "react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], - "react-native/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "react-native/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "react-native-drawer-layout/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], - "react-native-reanimated/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "react-native-reanimated/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "react-native-web/@react-native/normalize-colors": ["@react-native/normalize-colors@0.74.89", "", {}, "sha512-qoMMXddVKVhZ8PA1AbUCk83trpd6N+1nF2A6k1i6LsQObyS92fELuk8kU/lQs6M7BsMHwqyLCpQJ1uFgNvIQXg=="], "react-native-web/memoize-one": ["memoize-one@6.0.0", "", {}, "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="], - "react-native-worklets/semver": ["semver@7.8.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg=="], + "react-native-worklets/semver": ["semver@7.8.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA=="], "readable-web-to-node-stream/readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], @@ -2193,8 +2164,6 @@ "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], - "type-is/mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], "whatwg-url/webidl-conversions": ["webidl-conversions@3.0.1", "", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], @@ -2207,7 +2176,7 @@ "xml2js/xmlbuilder": ["xmlbuilder@11.0.1", "", {}, "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="], - "zxing-wasm/type-fest": ["type-fest@5.6.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-8ZiHFm91orbSAe2PSAiSVBVko18pbhbiB3U9GglSzF/zCGkR+rxpHx6sEMCUm4kxY4LjDIUGgCfUMtwfZfjfUA=="], + "zxing-wasm/type-fest": ["type-fest@5.7.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg=="], "@expo/cli/ora/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="], @@ -2227,10 +2196,14 @@ "@expo/package-manager/ora/strip-ansi": ["strip-ansi@5.2.0", "", { "dependencies": { "ansi-regex": "^4.1.0" } }, "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA=="], - "@jest/types/@types/node/undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - "@react-native-community/cli-server-api/open/is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen": ["@react-native/codegen@0.86.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/parser": "^7.29.0", "hermes-parser": "0.36.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "tinyglobby": "^0.2.15", "yargs": "^17.6.2" } }, "sha512-uTs9DBo3+/lUqinsGZK0FKJRBVClrwMXoZToaDxE1Q2SL2e55vs2GwyZfIKzPl5uJnbu4PfFMIp0/mLXLWUMuA=="], + + "@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="], + + "@react-native/metro-babel-transformer/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="], + "@react-navigation/elements/color/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], "@react-navigation/elements/color/color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], @@ -2249,10 +2222,6 @@ "chalk/ansi-styles/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], - "chrome-launcher/@types/node/undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - - "chromium-edge-launcher/@types/node/undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], "cliui/wrap-ansi/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], @@ -2267,10 +2236,6 @@ "finalhandler/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "jest-util/@types/node/undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - - "jest-worker/@types/node/undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], - "lighthouse-logger/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "log-update/cli-cursor/restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], @@ -2351,6 +2316,10 @@ "@expo/package-manager/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser": ["hermes-parser@0.36.0", "", { "dependencies": { "hermes-estree": "0.36.0" } }, "sha512-GdpwMmH5x6IpC1cijvcvYnlPB60Mh6kTSF/NFdYV/j56gYdi+0RIakYs+eqOV+bbO0SW7mgVVGSsTJxyPQfo3w=="], + + "@react-native/babel-preset/babel-plugin-syntax-hermes-parser/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="], + "@react-navigation/elements/color/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], "@react-navigation/elements/color/color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], @@ -2407,6 +2376,8 @@ "@expo/package-manager/ora/cli-cursor/restore-cursor/onetime": ["onetime@2.0.1", "", { "dependencies": { "mimic-fn": "^1.0.0" } }, "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ=="], + "@react-native/babel-preset/@react-native/babel-plugin-codegen/@react-native/codegen/hermes-parser/hermes-estree": ["hermes-estree@0.36.0", "", {}, "sha512-A1+8zn5oss2CFP7pKsOaxorQG6FNIz1WU1VDqruLPPZl3LVgeE2C5xfFg8Ow6/Ow4mSslLLtYP1J3n38eKyW9w=="], + "ansi-fragments/slice-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="], "cliui/wrap-ansi/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], diff --git a/components/ContextMenu.tv.ts b/components/ContextMenu.tv.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/components/ExampleGlobalModalUsage.tsx b/components/ExampleGlobalModalUsage.tsx deleted file mode 100644 index ccebb823..00000000 --- a/components/ExampleGlobalModalUsage.tsx +++ /dev/null @@ -1,203 +0,0 @@ -/** - * Example Usage of Global Modal - * - * This file demonstrates how to use the global modal system from anywhere in your app. - * You can delete this file after understanding how it works. - */ - -import { Ionicons } from "@expo/vector-icons"; -import { TouchableOpacity, View } from "react-native"; -import { Text } from "@/components/common/Text"; -import { useGlobalModal } from "@/providers/GlobalModalProvider"; - -/** - * Example 1: Simple Content Modal - */ -export const SimpleModalExample = () => { - const { showModal } = useGlobalModal(); - - const handleOpenModal = () => { - showModal( - - Simple Modal - - This is a simple modal with just some text content. - - - Swipe down or tap outside to close. - - , - ); - }; - - return ( - - Open Simple Modal - - ); -}; - -/** - * Example 2: Modal with Custom Snap Points - */ -export const CustomSnapPointsExample = () => { - const { showModal } = useGlobalModal(); - - const handleOpenModal = () => { - showModal( - - - Custom Snap Points - - - This modal has custom snap points (25%, 50%, 90%). - - - - Try dragging the modal to different heights! - - - , - { - snapPoints: ["25%", "50%", "90%"], - enableDynamicSizing: false, - }, - ); - }; - - return ( - - Custom Snap Points - - ); -}; - -/** - * Example 3: Complex Component in Modal - */ -const SettingsModalContent = () => { - const { hideModal } = useGlobalModal(); - - const settings = [ - { - id: 1, - title: "Notifications", - icon: "notifications-outline" as const, - enabled: true, - }, - { id: 2, title: "Dark Mode", icon: "moon-outline" as const, enabled: true }, - { - id: 3, - title: "Auto-play", - icon: "play-outline" as const, - enabled: false, - }, - ]; - - return ( - - Settings - - {settings.map((setting, index) => ( - - - - {setting.title} - - - - - - ))} - - - Close - - - ); -}; - -export const ComplexModalExample = () => { - const { showModal } = useGlobalModal(); - - const handleOpenModal = () => { - showModal(); - }; - - return ( - - Complex Component - - ); -}; - -/** - * Example 4: Modal Triggered from Function (e.g., API response) - */ -export const useShowSuccessModal = () => { - const { showModal } = useGlobalModal(); - - return (message: string) => { - showModal( - - - - - Success! - {message} - , - ); - }; -}; - -/** - * Main Demo Component - */ -export const GlobalModalDemo = () => { - const showSuccess = useShowSuccessModal(); - - return ( - - - Global Modal Examples - - - - - - - showSuccess("Operation completed successfully!")} - className='bg-orange-600 px-4 py-2 rounded-lg' - > - Show Success Modal - - - ); -}; diff --git a/components/SaveAccountModal.tsx b/components/SaveAccountModal.tsx index 42615c7d..81508ade 100644 --- a/components/SaveAccountModal.tsx +++ b/components/SaveAccountModal.tsx @@ -69,17 +69,23 @@ export const SaveAccountModal: React.FC = ({ [isAndroid], ); + const isPresentedRef = useRef(false); + useEffect(() => { if (visible) { bottomSheetModalRef.current?.present(); - } else { + } else if (isPresentedRef.current) { bottomSheetModalRef.current?.dismiss(); + isPresentedRef.current = false; } }, [visible]); const handleSheetChanges = useCallback( (index: number) => { - if (index === -1) { + if (index >= 0) { + isPresentedRef.current = true; + } else if (index === -1 && isPresentedRef.current) { + isPresentedRef.current = false; resetState(); onClose(); } diff --git a/components/TrackSheet.tsx b/components/TrackSheet.tsx index 57e4a029..52735f6f 100644 --- a/components/TrackSheet.tsx +++ b/components/TrackSheet.tsx @@ -26,7 +26,7 @@ export const TrackSheet: React.FC = ({ const streams = useMemo( () => source?.MediaStreams?.filter((x) => x.Type === streamType), - [source], + [source, streamType], ); const selectedSteam = useMemo( diff --git a/components/common/LargePoster.tsx b/components/common/LargePoster.tsx deleted file mode 100644 index ab3b16fb..00000000 --- a/components/common/LargePoster.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Image } from "expo-image"; -import { View } from "react-native"; - -export const LargePoster: React.FC<{ url?: string | null }> = ({ url }) => { - if (!url) - return ( - - - - ); - - return ( - - - - ); -}; diff --git a/components/common/VerticalSkeleton.tsx b/components/common/VerticalSkeleton.tsx deleted file mode 100644 index 02a8a256..00000000 --- a/components/common/VerticalSkeleton.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import { View, type ViewProps } from "react-native"; - -interface Props extends ViewProps { - index: number; -} - -export const VerticalSkeleton: React.FC = ({ index, ...props }) => { - return ( - - - - - - - ); -}; diff --git a/components/library/LibraryItemCard.tsx b/components/library/LibraryItemCard.tsx index 09de500d..c84364ce 100644 --- a/components/library/LibraryItemCard.tsx +++ b/components/library/LibraryItemCard.tsx @@ -51,7 +51,7 @@ export const LibraryItemCard: React.FC = ({ library, ...props }) => { api, item: library, }), - [library], + [api, library], ); const itemType = useMemo(() => { diff --git a/components/login/TVPasswordEntryModal.tsx b/components/login/TVPasswordEntryModal.tsx index 596bb610..7db1671e 100644 --- a/components/login/TVPasswordEntryModal.tsx +++ b/components/login/TVPasswordEntryModal.tsx @@ -280,7 +280,7 @@ export const TVPasswordEntryModal: React.FC = ({ diff --git a/components/navigation/TabBarIcon.tsx b/components/navigation/TabBarIcon.tsx deleted file mode 100644 index a28bba84..00000000 --- a/components/navigation/TabBarIcon.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/ - -import type { IconProps } from "@expo/vector-icons/build/createIconSet"; -import Ionicons from "@expo/vector-icons/Ionicons"; -import type { ComponentProps } from "react"; - -export function TabBarIcon({ - style, - ...rest -}: IconProps["name"]>) { - return ; -} diff --git a/components/posters/EpisodePoster.tsx b/components/posters/EpisodePoster.tsx deleted file mode 100644 index af42989b..00000000 --- a/components/posters/EpisodePoster.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; -import { Image } from "expo-image"; -import { useAtom } from "jotai"; -import { useMemo, useState } from "react"; -import { View } from "react-native"; -import { WatchedIndicator } from "@/components/WatchedIndicator"; -import { apiAtom } from "@/providers/JellyfinProvider"; - -type MoviePosterProps = { - item: BaseItemDto; - showProgress?: boolean; -}; - -export const EpisodePoster: React.FC = ({ - item, - showProgress = false, -}) => { - const [api] = useAtom(apiAtom); - - const url = useMemo(() => { - if (item.Type === "Episode") { - return `${api?.basePath}/Items/${item.ParentBackdropItemId}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ParentThumbImageTag}`; - } - }, [item]); - - const [progress, _setProgress] = useState( - item.UserData?.PlayedPercentage || 0, - ); - - const blurhash = useMemo(() => { - const key = item.ImageTags?.Primary as string; - return item.ImageBlurHashes?.Primary?.[key]; - }, [item]); - - return ( - - - - {showProgress && progress > 0 && ( - - )} - - ); -}; diff --git a/components/posters/ParentPoster.tsx b/components/posters/ParentPoster.tsx deleted file mode 100644 index 47b62e4c..00000000 --- a/components/posters/ParentPoster.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Image } from "expo-image"; -import { useAtom } from "jotai"; -import { useMemo } from "react"; -import { View } from "react-native"; -import { apiAtom } from "@/providers/JellyfinProvider"; - -type PosterProps = { - id?: string; - showProgress?: boolean; -}; - -const ParentPoster: React.FC = ({ id }) => { - const [api] = useAtom(apiAtom); - - const url = useMemo( - () => `${api?.basePath}/Items/${id}/Images/Primary`, - [id], - ); - - if (!url || !id) - return ( - - ); - - return ( - - - - ); -}; - -export default ParentPoster; diff --git a/components/settings/Dashboard.tsx b/components/settings/Dashboard.tsx deleted file mode 100644 index d41de008..00000000 --- a/components/settings/Dashboard.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import { useTranslation } from "react-i18next"; -import { View } from "react-native"; -import useRouter from "@/hooks/useAppRouter"; -import { useSessions, type useSessionsProps } from "@/hooks/useSessions"; -import { useSettings } from "@/utils/atoms/settings"; -import { ListGroup } from "../list/ListGroup"; -import { ListItem } from "../list/ListItem"; - -export const Dashboard = () => { - const { settings } = useSettings(); - const { sessions = [] } = useSessions({} as useSessionsProps); - const router = useRouter(); - - const { t } = useTranslation(); - - if (!settings) return null; - return ( - - - router.push("/settings/dashboard/sessions")} - title={t("home.settings.dashboard.sessions_title")} - showArrow - /> - - - ); -}; diff --git a/components/settings/DownloadSettings.tsx b/components/settings/DownloadSettings.tsx deleted file mode 100644 index 3a0017ac..00000000 --- a/components/settings/DownloadSettings.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function DownloadSettings() { - return null; -} diff --git a/components/settings/DownloadSettings.tv.tsx b/components/settings/DownloadSettings.tv.tsx deleted file mode 100644 index 3a0017ac..00000000 --- a/components/settings/DownloadSettings.tv.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export default function DownloadSettings() { - return null; -} diff --git a/components/settings/Jellyseerr.tsx b/components/settings/Jellyseerr.tsx index 470d40a2..436b46c4 100644 --- a/components/settings/Jellyseerr.tsx +++ b/components/settings/Jellyseerr.tsx @@ -115,9 +115,6 @@ export const JellyseerrSettings = () => { ) : ( - - {t("home.settings.plugins.jellyseerr.jellyseerr_warning")} - {t("home.settings.plugins.jellyseerr.server_url")} diff --git a/components/settings/UserInfo.tsx b/components/settings/UserInfo.tsx index 56b6413d..9c55293d 100644 --- a/components/settings/UserInfo.tsx +++ b/components/settings/UserInfo.tsx @@ -1,8 +1,8 @@ -import * as Application from "expo-application"; import { useAtom } from "jotai"; import { useTranslation } from "react-i18next"; import { View, type ViewProps } from "react-native"; import { apiAtom, userAtom } from "@/providers/JellyfinProvider"; +import { getVersionInfo } from "@/utils/version"; import { ListGroup } from "../list/ListGroup"; import { ListItem } from "../list/ListItem"; @@ -13,10 +13,9 @@ export const UserInfo: React.FC = ({ ...props }) => { const [user] = useAtom(userAtom); const { t } = useTranslation(); - const version = - Application?.nativeApplicationVersion || - Application?.nativeBuildVersion || - "N/A"; + // Graduated build identifier β€” see utils/version.ts: + // dev β†’ "0.54.1 Β· branch Β· commit", develop/CI β†’ "0.54.1 Β· commit Β· #run", production β†’ "0.54.1". + const { display: version } = getVersionInfo(); return ( diff --git a/constants/Languages.ts b/constants/Languages.ts deleted file mode 100644 index 8014e380..00000000 --- a/constants/Languages.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { DefaultLanguageOption } from "@/utils/atoms/settings"; - -export const LANGUAGES: DefaultLanguageOption[] = [ - { label: "English", value: "eng" }, - { label: "Spanish", value: "spa" }, - { label: "Chinese (Mandarin)", value: "cmn" }, - { label: "Hindi", value: "hin" }, - { label: "Arabic", value: "ara" }, - { label: "French", value: "fra" }, - { label: "Russian", value: "rus" }, - { label: "Portuguese", value: "por" }, - { label: "Japanese", value: "jpn" }, - { label: "German", value: "deu" }, - { label: "Italian", value: "ita" }, - { label: "Korean", value: "kor" }, - { label: "Turkish", value: "tur" }, - { label: "Dutch", value: "nld" }, - { label: "Polish", value: "pol" }, - { label: "Vietnamese", value: "vie" }, - { label: "Thai", value: "tha" }, - { label: "Indonesian", value: "ind" }, - { label: "Greek", value: "ell" }, - { label: "Swedish", value: "swe" }, - { label: "Danish", value: "dan" }, - { label: "Norwegian", value: "nor" }, - { label: "Finnish", value: "fin" }, - { label: "Czech", value: "ces" }, - { label: "Hungarian", value: "hun" }, - { label: "Romanian", value: "ron" }, - { label: "Ukrainian", value: "ukr" }, - { label: "Hebrew", value: "heb" }, - { label: "Bengali", value: "ben" }, - { label: "Punjabi", value: "pan" }, - { label: "Tagalog", value: "tgl" }, - { label: "Swahili", value: "swa" }, - { label: "Malay", value: "msa" }, - { label: "Persian", value: "fas" }, - { label: "Urdu", value: "urd" }, -]; diff --git a/eas.json b/eas.json index 966881ce..23e28e82 100644 --- a/eas.json +++ b/eas.json @@ -52,7 +52,7 @@ } }, "production": { - "bun": "1.3.5", + "bun": "1.3.14", "environment": "production", "autoIncrement": true, "android": { @@ -64,7 +64,7 @@ } }, "production-apk": { - "bun": "1.3.5", + "bun": "1.3.14", "environment": "production", "autoIncrement": true, "android": { @@ -74,7 +74,7 @@ } }, "production-apk-tv": { - "bun": "1.3.5", + "bun": "1.3.14", "environment": "production", "autoIncrement": true, "android": { @@ -87,7 +87,7 @@ } }, "production_tv": { - "bun": "1.3.5", + "bun": "1.3.14", "environment": "production", "autoIncrement": true, "env": { @@ -97,6 +97,14 @@ "credentialsSource": "local", "config": "ios-production.yml" } + }, + "ci": { + "extends": "production", + "autoIncrement": false + }, + "ci_tv": { + "extends": "production_tv", + "autoIncrement": false } }, "submit": { diff --git a/hooks/useControlsVisibility.ts b/hooks/useControlsVisibility.ts deleted file mode 100644 index caca0d84..00000000 --- a/hooks/useControlsVisibility.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { useCallback, useEffect, useRef } from "react"; -import { useSharedValue } from "react-native-reanimated"; - -export const useControlsVisibility = (timeout = 3000) => { - const opacity = useSharedValue(1); - - const hideControlsTimerRef = useRef | null>( - null, - ); - - const showControls = useCallback(() => { - opacity.value = 1; - if (hideControlsTimerRef.current) { - clearTimeout(hideControlsTimerRef.current); - } - hideControlsTimerRef.current = setTimeout(() => { - opacity.value = 0; - }, timeout); - }, [timeout]); - - const hideControls = useCallback(() => { - opacity.value = 0; - if (hideControlsTimerRef.current) { - clearTimeout(hideControlsTimerRef.current); - } - }, []); - - useEffect(() => { - return () => { - if (hideControlsTimerRef.current) { - clearTimeout(hideControlsTimerRef.current); - } - }; - }, []); - - return { opacity, showControls, hideControls }; -}; diff --git a/hooks/useDownloadedFileOpener.ts b/hooks/useDownloadedFileOpener.ts deleted file mode 100644 index 845161a1..00000000 --- a/hooks/useDownloadedFileOpener.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; -import { useCallback } from "react"; -import useRouter from "@/hooks/useAppRouter"; -import { usePlaySettings } from "@/providers/PlaySettingsProvider"; -import { writeToLog } from "@/utils/log"; - -export const useDownloadedFileOpener = () => { - const router = useRouter(); - const { setPlayUrl, setOfflineSettings } = usePlaySettings(); - - const openFile = useCallback( - async (item: BaseItemDto) => { - if (!item.Id) { - writeToLog("ERROR", "Attempted to open a file without an ID."); - console.error("Attempted to open a file without an ID."); - return; - } - const queryParams = new URLSearchParams({ - itemId: item.Id, - offline: "true", - playbackPosition: - item.UserData?.PlaybackPositionTicks?.toString() ?? "0", - }); - try { - router.push(`/player/direct-player?${queryParams.toString()}`); - } catch (error) { - writeToLog("ERROR", "Error opening file", error); - console.error("Error opening file:", error); - } - }, - [setOfflineSettings, setPlayUrl, router], - ); - - return { openFile }; -}; diff --git a/hooks/useImageColors.ts b/hooks/useImageColors.ts deleted file mode 100644 index 4d8a0136..00000000 --- a/hooks/useImageColors.ts +++ /dev/null @@ -1,120 +0,0 @@ -import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client"; -import { useAtom, useAtomValue } from "jotai"; -import { useEffect, useMemo } from "react"; -import { Platform } from "react-native"; -import type * as ImageColorsType from "react-native-image-colors"; -import { apiAtom } from "@/providers/JellyfinProvider"; - -// Conditionally import react-native-image-colors only on non-TV platforms -const ImageColors = Platform.isTV - ? null - : (require("react-native-image-colors") as typeof ImageColorsType); - -import { - adjustToNearBlack, - calculateTextColor, - isCloseToBlack, - itemThemeColorAtom, -} from "@/utils/atoms/primaryColor"; -import { getItemImage } from "@/utils/getItemImage"; -import { storage } from "@/utils/mmkv"; - -/** - * Custom hook to extract and manage image colors for a given item. - * - * @param item - The BaseItemDto object representing the item. - * @param disabled - A boolean flag to disable color extraction. - * - */ -export const useImageColors = ({ - item, - url, - disabled, -}: { - item?: BaseItemDto | null; - url?: string | null; - disabled?: boolean; -}) => { - const api = useAtomValue(apiAtom); - const [, setPrimaryColor] = useAtom(itemThemeColorAtom); - - const isTv = Platform.isTV; - - const source = useMemo(() => { - if (!api) return; - if (url) return { uri: url }; - if (item) - return getItemImage({ - item, - api, - variant: "Primary", - quality: 80, - width: 300, - }); - return null; - }, [api, item, url]); - - useEffect(() => { - if (isTv) return; - if (disabled) return; - if (source?.uri) { - const _primary = storage.getString(`${source.uri}-primary`); - const _text = storage.getString(`${source.uri}-text`); - - if (_primary && _text) { - setPrimaryColor({ - primary: _primary, - text: _text, - }); - return; - } - - // Extract colors from the image - if (!ImageColors?.getColors) return; - - ImageColors.getColors(source.uri, { - fallback: "#fff", - cache: false, - }) - .then((colors: ImageColorsType.ImageColorsResult) => { - let primary = "#fff"; - let text = "#000"; - let backup = "#fff"; - - // Select the appropriate color based on the platform - if (colors.platform === "android") { - primary = colors.dominant; - backup = colors.vibrant; - } else if (colors.platform === "ios") { - primary = colors.detail; - backup = colors.primary; - } - - // Adjust the primary color if it's too close to black - if (primary && isCloseToBlack(primary)) { - if (backup && !isCloseToBlack(backup)) primary = backup; - primary = adjustToNearBlack(primary); - } - - // Calculate the text color based on the primary color - if (primary) text = calculateTextColor(primary); - - setPrimaryColor({ - primary, - text, - }); - - // Cache the colors in storage - if (source.uri && primary) { - storage.set(`${source.uri}-primary`, primary); - storage.set(`${source.uri}-text`, text); - } - }) - .catch((error: any) => { - console.error("Error getting colors", error); - }); - } - }, [isTv, source?.uri, setPrimaryColor, disabled]); - - if (isTv) return; -}; diff --git a/hooks/useWifiSSID.ts b/hooks/useWifiSSID.ts index 2b442a58..de0e2828 100644 --- a/hooks/useWifiSSID.ts +++ b/hooks/useWifiSSID.ts @@ -53,7 +53,6 @@ export function useWifiSSID(): UseWifiSSIDReturn { const fetchSSID = useCallback(async () => { if (Platform.isTV) return; const result = await getSSID(); - console.log("[WiFi Debug] Native module SSID:", result); setSSID(result); }, []); diff --git a/modules/wifi-ssid/index.ts b/modules/wifi-ssid/index.ts index 71bfbcfb..00d2bf83 100644 --- a/modules/wifi-ssid/index.ts +++ b/modules/wifi-ssid/index.ts @@ -15,7 +15,6 @@ const WifiSsidModule = */ export async function getSSID(): Promise { if (!WifiSsidModule) { - console.log("[WifiSsid] Module not available on this platform"); return null; } diff --git a/package.json b/package.json index ccabd2f4..0c4715d3 100644 --- a/package.json +++ b/package.json @@ -22,15 +22,17 @@ "lint": "biome check --write --unsafe --max-diagnostics 1000", "format": "biome format --write .", "doctor": "expo-doctor", - "test": "bun run typecheck && bun run lint && bun run format && bun run doctor", + "i18n:check": "bun scripts/check-i18n-keys.mjs", + "i18n:fix-unused": "bun scripts/check-i18n-keys.mjs --fix-unused", + "test": "bun run typecheck && bun run lint && bun run format && bun run i18n:check && bun run doctor", "postinstall": "patch-package" }, "dependencies": { "@bottom-tabs/react-navigation": "1.2.0", "@douglowder/expo-av-route-picker-view": "^0.0.5", - "@expo/metro-runtime": "~56.0.13", + "@expo/metro-runtime": "~56.0.15", "@expo/react-native-action-sheet": "^4.1.1", - "@expo/ui": "~56.0.14", + "@expo/ui": "~56.0.17", "@expo/vector-icons": "^15.0.3", "@gorhom/bottom-sheet": "5.2.14", "@jellyfin/sdk": "^0.13.0", @@ -43,35 +45,35 @@ "@tanstack/react-query": "5.100.14", "@tanstack/react-query-persist-client": "^5.100.14", "axios": "^1.7.9", - "expo": "~56.0.6", + "expo": "~56.0.11", "expo-application": "~56.0.3", - "expo-asset": "~56.0.15", - "expo-audio": "~56.0.11", - "expo-background-task": "~56.0.15", + "expo-asset": "~56.0.17", + "expo-audio": "~56.0.12", + "expo-background-task": "~56.0.18", "expo-blur": "~56.0.3", "expo-brightness": "~56.0.5", - "expo-build-properties": "~56.0.15", - "expo-camera": "~56.0.7", - "expo-constants": "~56.0.16", + "expo-build-properties": "~56.0.18", + "expo-camera": "~56.0.8", + "expo-constants": "~56.0.18", "expo-crypto": "~56.0.4", - "expo-dev-client": "~56.0.16", + "expo-dev-client": "~56.0.20", "expo-device": "~56.0.4", - "expo-font": "~56.0.5", + "expo-font": "~56.0.6", "expo-haptics": "~56.0.3", - "expo-image": "~56.0.9", + "expo-image": "~56.0.11", "expo-linear-gradient": "~56.0.4", - "expo-linking": "~56.0.12", + "expo-linking": "~56.0.14", "expo-localization": "~56.0.6", - "expo-location": "~56.0.14", - "expo-notifications": "~56.0.14", - "expo-router": "~56.2.7", + "expo-location": "~56.0.17", + "expo-notifications": "~56.0.17", + "expo-router": "~56.2.10", "expo-screen-orientation": "~56.0.5", "expo-secure-store": "~56.0.4", - "expo-sharing": "~56.0.14", + "expo-sharing": "~56.0.17", "expo-splash-screen": "~56.0.10", "expo-status-bar": "~56.0.4", "expo-system-ui": "~56.0.5", - "expo-task-manager": "~56.0.15", + "expo-task-manager": "~56.0.18", "expo-web-browser": "~56.0.5", "i18next": "^26.3.0", "jotai": "2.20.0", @@ -126,14 +128,15 @@ "@react-native-tvos/config-tv": "0.1.6", "@types/jest": "29.5.14", "@types/lodash": "4.17.24", + "@types/node": "^18.19.130", "@types/react": "~19.2.10", "@types/react-test-renderer": "19.1.0", "cross-env": "10.1.0", - "expo-doctor": "1.19.7", + "expo-doctor": "1.19.9", "husky": "9.1.7", "lint-staged": "17.0.5", "react-test-renderer": "19.2.3", - "typescript": "5.9.3" + "typescript": "6.0.3" }, "expo": { "doctor": { @@ -141,6 +144,7 @@ "exclude": [ "react-native-google-cast", "react-native-udp", + "react-native-track-player", "@jellyfin/sdk" ], "listUnknownPackages": false diff --git a/providers/Downloads/hooks/useDownloadEventHandlers.ts b/providers/Downloads/hooks/useDownloadEventHandlers.ts index ebf8b116..0bc8c352 100644 --- a/providers/Downloads/hooks/useDownloadEventHandlers.ts +++ b/providers/Downloads/hooks/useDownloadEventHandlers.ts @@ -142,31 +142,12 @@ export function useDownloadEventHandlers({ } else { // Transcoding - estimate from bitrate const process = processes.find((p) => p.id === processId); - console.log( - `[DPL] Transcoding detected, looking for process ${processId}, found:`, - process ? "yes" : "no", - ); - if (process) { - console.log(`[DPL] Process bitrate:`, { - key: process.maxBitrate.key, - value: process.maxBitrate.value, - runTimeTicks: process.item.RunTimeTicks, - }); - if (process.maxBitrate.value && process.item.RunTimeTicks) { - const { estimateDownloadSize } = require("@/utils/download"); - estimatedTotalBytes = estimateDownloadSize( - process.maxBitrate.value, - process.item.RunTimeTicks, - ); - console.log( - `[DPL] Calculated estimatedTotalBytes:`, - estimatedTotalBytes, - ); - } else { - console.log( - `[DPL] Cannot estimate size - bitrate.value or RunTimeTicks missing`, - ); - } + if (process?.maxBitrate.value && process.item.RunTimeTicks) { + const { estimateDownloadSize } = require("@/utils/download"); + estimatedTotalBytes = estimateDownloadSize( + process.maxBitrate.value, + process.item.RunTimeTicks, + ); } } diff --git a/providers/JellyfinProvider.tsx b/providers/JellyfinProvider.tsx index 185c306c..52647bde 100644 --- a/providers/JellyfinProvider.tsx +++ b/providers/JellyfinProvider.tsx @@ -40,6 +40,7 @@ import { } from "@/utils/secureCredentials"; import { store } from "@/utils/store"; import { clearTVDiscoverySafely } from "@/utils/tvDiscovery/sync"; +import { APP_VERSION } from "@/utils/version"; interface Server { address: string; @@ -53,7 +54,7 @@ const initialApi = (() => { const id = getOrSetDeviceId(); const deviceName = getDeviceNameSync(); const jellyfinInstance = new Jellyfin({ - clientInfo: { name: "Streamyfin", version: "0.54.1" }, + clientInfo: { name: "Streamyfin", version: APP_VERSION }, deviceInfo: { name: deviceName, id, @@ -135,7 +136,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ const id = getOrSetDeviceId(); const deviceName = getDeviceNameSync(); return new Jellyfin({ - clientInfo: { name: "Streamyfin", version: "0.54.1" }, + clientInfo: { name: "Streamyfin", version: APP_VERSION }, deviceInfo: { name: deviceName, id, @@ -169,7 +170,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ return { authorization: `MediaBrowser Client="Streamyfin", Device=${ Platform.OS === "android" ? "Android" : "iOS" - }, DeviceId="${deviceId}", Version="0.54.1"`, + }, DeviceId="${deviceId}", Version="${APP_VERSION}"`, }; }, [deviceId]); diff --git a/providers/WebSocketProvider.tsx b/providers/WebSocketProvider.tsx index ed9db754..c704d373 100644 --- a/providers/WebSocketProvider.tsx +++ b/providers/WebSocketProvider.tsx @@ -1,4 +1,5 @@ import { getSessionApi } from "@jellyfin/sdk/lib/utils/api"; +import { router } from "expo-router"; import { useAtomValue } from "jotai"; import { createContext, @@ -11,7 +12,6 @@ import { useState, } from "react"; import { AppState, type AppStateStatus } from "react-native"; -import useRouter from "@/hooks/useAppRouter"; import { useNetworkAwareQueryClient } from "@/hooks/useNetworkAwareQueryClient"; import { apiAtom, getOrSetDeviceId } from "@/providers/JellyfinProvider"; import { useNetworkStatus } from "@/providers/NetworkStatusProvider"; @@ -28,6 +28,20 @@ const LIBRARY_CHANGE_QUERY_KEYS = [ ["episodes"], ] as const; +// Query keys that depend on per-user playback state (resume position, played +// status, favorites) and should be refreshed when the server reports a +// `UserDataChanged`. Scoped to the progression-based sections so finishing an +// episode does not pointlessly refetch "recently added" or suggestions. +const USER_DATA_CHANGE_QUERY_KEYS = [ + ["home", "continueAndNextUp"], + ["home", "resumeItems"], + ["home", "nextUp-all"], + ["home", "heroItems"], + ["resumeItems"], + ["nextUp-all"], + ["nextUp"], +] as const; + interface WebSocketMessage { MessageType: string; Data: any; @@ -38,10 +52,30 @@ interface WebSocketProviderProps { children: ReactNode; } +/** + * Handler invoked for every message of a given `MessageType`. Receives the + * message `Data` payload and the full message. + */ +type WebSocketMessageHandler = (data: any, message: WebSocketMessage) => void; + interface WebSocketContextType { ws: WebSocket | null; isConnected: boolean; + /** + * @deprecated Prefer `subscribe`. `lastMessage` only keeps the most recent + * message, so bursts arriving in the same tick are coalesced and lost. Kept + * for `useWebsockets` (GeneralCommand handling) until it is migrated. + */ lastMessage: WebSocketMessage | null; + /** + * Subscribe to a given message type. The handler is called synchronously for + * every matching message (no coalescing, unlike `lastMessage`). Returns an + * unsubscribe function to call on cleanup. + */ + subscribe: ( + messageType: string, + handler: WebSocketMessageHandler, + ) => () => void; sendMessage: (message: any) => void; clearLastMessage: () => void; } @@ -54,7 +88,6 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { const [ws, setWs] = useState(null); const [isConnected, setIsConnected] = useState(false); const [lastMessage, setLastMessage] = useState(null); - const router = useRouter(); const queryClient = useNetworkAwareQueryClient(); const deviceId = useMemo(() => { return getOrSetDeviceId(); @@ -63,8 +96,76 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { const libraryChangeDebounceRef = useRef | null>( null, ); + const userDataChangeDebounceRef = useRef | null>(null); + // Handle for the onerror backoff timer. Tracked so a reconnect triggered by + // another path (foreground, network reconnect, effect re-run) can cancel a + // pending one β€” an untracked timer would later open a second socket. + const reconnectTimeoutRef = useRef | null>( + null, + ); + + // Pub/sub registry: messageType -> set of handlers. Stored in a ref so + // subscribing/dispatching never triggers a re-render. + const listenersRef = useRef>>( + new Map(), + ); + + const subscribe = useCallback( + (messageType: string, handler: WebSocketMessageHandler) => { + const listeners = listenersRef.current; + let handlers = listeners.get(messageType); + if (!handlers) { + handlers = new Set(); + listeners.set(messageType, handlers); + } + handlers.add(handler); + return () => { + handlers?.delete(handler); + // Only drop the map entry if it still points at THIS set. After an + // unsubscribe + re-subscribe for the same type, a stale second call to + // this cleanup would otherwise delete the new subscribers' set and + // silently stop delivering their messages. + if ( + handlers && + handlers.size === 0 && + listeners.get(messageType) === handlers + ) { + listeners.delete(messageType); + } + }; + }, + [], + ); + + const dispatchMessage = useCallback((message: WebSocketMessage) => { + const handlers = listenersRef.current.get(message.MessageType); + if (!handlers || handlers.size === 0) return; + // Copy to tolerate handlers that unsubscribe during dispatch. + for (const handler of [...handlers]) { + // Isolate each handler so one throwing subscriber can't abort the rest + // (and isn't misreported as a parse failure by the outer onmessage catch). + try { + handler(message.Data, message); + } catch (error) { + console.error( + `Error handling WebSocket message type "${message.MessageType}":`, + error, + ); + } + } + }, []); const connectWebSocket = useCallback(() => { + // Cancel any reconnect queued by a previous onerror before opening a new + // socket, so we never end up with two live sockets β€” each would double the + // message fan-out and double-invalidate queries. + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + reconnectTimeoutRef.current = null; + } + if (!deviceId || !api?.accessToken || !isNetworkConnected) { return; } @@ -85,6 +186,10 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { newWebSocket.onopen = () => { setIsConnected(true); reconnectAttemptsRef.current = 0; + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + reconnectTimeoutRef.current = null; + } keepAliveInterval = setInterval(() => { if (newWebSocket.readyState === WebSocket.OPEN) { newWebSocket.send(JSON.stringify({ MessageType: "KeepAlive" })); @@ -96,9 +201,15 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { // Don't log errors - this is expected when offline or server unreachable setIsConnected(false); + // Replace any still-pending reconnect so only one is ever queued; the + // previously untracked handle could leak and open a second socket. + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + } if (reconnectAttemptsRef.current < maxReconnectAttempts) { reconnectAttemptsRef.current++; - setTimeout(() => { + reconnectTimeoutRef.current = setTimeout(() => { + reconnectTimeoutRef.current = null; connectWebSocket(); }, reconnectDelay); } @@ -113,7 +224,10 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { newWebSocket.onmessage = (e) => { try { const message = JSON.parse(e.data); - setLastMessage(message); // Store the last message in context + // Legacy single-slot state, still consumed by useWebsockets. + setLastMessage(message); + // Pub/sub: deliver to every subscriber without coalescing. + dispatchMessage(message); } catch (error) { console.error("Error parsing WebSocket message:", error); } @@ -124,9 +238,13 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { if (keepAliveInterval) { clearInterval(keepAliveInterval); } + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + reconnectTimeoutRef.current = null; + } newWebSocket.close(); }; - }, [api, deviceId, isNetworkConnected]); + }, [api, deviceId, isNetworkConnected, dispatchMessage]); const handleLibraryChanged = useCallback( (data: any) => { @@ -157,47 +275,80 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { [queryClient], ); - useEffect(() => { - if (!lastMessage) { - return; - } - if (lastMessage.MessageType === "Play") { - handlePlayCommand(lastMessage.Data); - } else if (lastMessage.MessageType === "LibraryChanged") { - handleLibraryChanged(lastMessage.Data); - } - }, [lastMessage, router, handleLibraryChanged]); + const handleUserDataChanged = useCallback( + (data: any) => { + // Jellyfin sends UserDataChanged when playback position, played status + // or favorites change (e.g. finishing an episode). Only the + // progression-based home sections care about it. + if (!((data?.UserDataList?.length ?? 0) > 0)) { + return; + } + + // Finishing an item can emit several UserDataChanged messages, so + // debounce to invalidate the affected sections only once. + if (userDataChangeDebounceRef.current) { + clearTimeout(userDataChangeDebounceRef.current); + } + userDataChangeDebounceRef.current = setTimeout(() => { + for (const queryKey of USER_DATA_CHANGE_QUERY_KEYS) { + queryClient.invalidateQueries({ queryKey: [...queryKey] }); + } + }, 800); + }, + [queryClient], + ); + + // Refresh library-dependent queries when the server reports a change. + useEffect( + () => subscribe("LibraryChanged", handleLibraryChanged), + [subscribe, handleLibraryChanged], + ); + + // Refresh "Continue Watching" / "Next Up" when playback state changes. + useEffect( + () => subscribe("UserDataChanged", handleUserDataChanged), + [subscribe, handleUserDataChanged], + ); useEffect(() => { return () => { if (libraryChangeDebounceRef.current) { clearTimeout(libraryChangeDebounceRef.current); } + if (userDataChangeDebounceRef.current) { + clearTimeout(userDataChangeDebounceRef.current); + } + if (reconnectTimeoutRef.current) { + clearTimeout(reconnectTimeoutRef.current); + } }; }, []); - const handlePlayCommand = useCallback( - (data: any) => { - if (!data?.ItemIds?.length) { - return; - } + const handlePlayCommand = useCallback((data: any) => { + if (!data?.ItemIds?.length) { + return; + } - const itemId = data.ItemIds[0]; + const itemId = data.ItemIds[0]; - router.push({ - pathname: "/(auth)/player/direct-player", - params: { - itemId: itemId, - playCommand: data.PlayCommand || "PlayNow", - audioIndex: data.AudioStreamIndex?.toString(), - subtitleIndex: data.SubtitleStreamIndex?.toString(), - mediaSourceId: data.MediaSourceId || "", - bitrateValue: "", - offline: "false", - }, - }); - }, - [router], + router.push({ + pathname: "/(auth)/player/direct-player", + params: { + itemId: itemId, + playCommand: data.PlayCommand || "PlayNow", + audioIndex: data.AudioStreamIndex?.toString(), + subtitleIndex: data.SubtitleStreamIndex?.toString(), + mediaSourceId: data.MediaSourceId || "", + bitrateValue: "", + offline: "false", + }, + }); + }, []); + + // Server-initiated "Play me this item" remote command. + useEffect( + () => subscribe("Play", handlePlayCommand), + [subscribe, handlePlayCommand], ); useEffect(() => { @@ -267,7 +418,14 @@ export const WebSocketProvider = ({ children }: WebSocketProviderProps) => { }, []); return ( {children} diff --git a/scripts/check-i18n-keys.mjs b/scripts/check-i18n-keys.mjs new file mode 100644 index 00000000..0e20e462 --- /dev/null +++ b/scripts/check-i18n-keys.mjs @@ -0,0 +1,273 @@ +#!/usr/bin/env bun +/** + * i18n key checker for Streamyfin. + * + * Detects: + * - MISSING keys: a static `t("a.b.c")` / `i18nKey="a.b.c"` referenced in the code + * that does not exist in the source locale (translations/en.json). These are bugs β€” + * the app renders the raw key. Always fails CI. + * - UNUSED (dead) keys: a key in the source locale that is referenced nowhere in the + * code, neither statically nor via a detected dynamic prefix (`t(`a.b.${x}`)`). + * These are dead weight that also clutter every locale on Crowdin. + * + * Dynamic usage is handled conservatively: + * - `t(`prefix.${x}`)` -> every key starting with `prefix.` is considered used. + * - `t(`${x}`)` -> fully dynamic, reported for manual review, never used to + * whitelist keys (in Streamyfin these are user-defined section + * titles, not translation keys). + * - Edge cases the static scan cannot see can be allow-listed in the config file. + * + * Usage: + * bun scripts/check-i18n-keys.mjs # report + exit 1 on missing OR unused + * bun scripts/check-i18n-keys.mjs --unused=warn # exit 1 only on missing; unused = warning + * bun scripts/check-i18n-keys.mjs --unused=off # ignore unused entirely + * bun scripts/check-i18n-keys.mjs --json # machine-readable output + * bun scripts/check-i18n-keys.mjs --fix-unused # remove dead keys from en.json (Crowdin syncs the rest) + */ + +import { + existsSync, + readdirSync, + readFileSync, + statSync, + writeFileSync, +} from "node:fs"; +import { extname, join, relative } from "node:path"; + +const ROOT = process.cwd(); +const args = process.argv.slice(2); +const flag = (name, def) => { + const a = args.find((x) => x === `--${name}` || x.startsWith(`--${name}=`)); + if (!a) return def; + const [, v] = a.split("="); + return v === undefined ? true : v; +}; +const UNUSED_MODE = String(flag("unused", "error")); // error | warn | off +const JSON_OUT = !!flag("json", false); +const FIX_UNUSED = !!flag("fix-unused", false); + +// ---- config ---- +const CONFIG_PATH = join(ROOT, "scripts", "i18n-keys.config.json"); +const DEFAULT_CONFIG = { + localesDir: "translations", + sourceLocale: "en", + // Scan the whole repo by default so keys referenced outside the obvious dirs + // (e.g. packages/, key constants in utils/atoms) are not wrongly flagged as dead. + srcDirs: ["."], + srcExtensions: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"], + excludeDirs: [ + "node_modules", + "ios", + "android", + ".expo", + ".git", + "dist", + "build", + "translations", + "scripts", + ], + // Keys (or glob-ish prefixes ending with .* or *) known to be used dynamically / externally. + ignoreUnused: [], +}; +const config = existsSync(CONFIG_PATH) + ? { ...DEFAULT_CONFIG, ...JSON.parse(readFileSync(CONFIG_PATH, "utf8")) } + : DEFAULT_CONFIG; + +// ---- helpers ---- +const flatten = (obj, prefix = "", out = {}) => { + for (const [k, v] of Object.entries(obj)) { + const key = prefix ? `${prefix}.${k}` : k; + if (v && typeof v === "object" && !Array.isArray(v)) flatten(v, key, out); + else out[key] = v; + } + return out; +}; + +const globMatch = (key, pattern) => { + if (pattern.endsWith(".*")) + return key === pattern.slice(0, -2) || key.startsWith(pattern.slice(0, -1)); + if (pattern.endsWith("*")) return key.startsWith(pattern.slice(0, -1)); + return key === pattern; +}; + +const walk = (dir, files = []) => { + let entries; + try { + entries = readdirSync(dir); + } catch { + return files; + } + for (const name of entries) { + const full = join(dir, name); + let st; + try { + st = statSync(full); + } catch { + continue; + } + if (st.isDirectory()) { + if (config.excludeDirs.includes(name)) continue; + walk(full, files); + } else if (config.srcExtensions.includes(extname(name))) { + files.push(full); + } + } + return files; +}; + +// ---- load source keys ---- +const sourcePath = join(ROOT, config.localesDir, `${config.sourceLocale}.json`); +const sourceKeys = Object.keys( + flatten(JSON.parse(readFileSync(sourcePath, "utf8"))), +); +const sourceKeySet = new Set(sourceKeys); + +// ---- scan code ---- +const STATIC_RE = /\bt\(\s*(['"])((?:\\.|(?!\1).)+?)\1/g; // t("a.b") / t('a.b') +const TPL_STATIC_RE = /\bt\(\s*`([^`$]+)`/g; // t(`a.b`) no interpolation +const TPL_DYN_RE = /\bt\(\s*`([^`$]*)\$\{/g; // t(`a.b.${x}`) -> prefix "a.b." +const I18NKEY_RE = /\bi18nKey\s*=\s*(?:\{\s*)?(['"])((?:\\.|(?!\1).)+?)\1/g; // +const KEY_SHAPE = /^[A-Za-z0-9_]+(\.[A-Za-z0-9_]+)+$/; // dotted key, e.g. home.x.y + +const usedStatic = new Set(); // keys passed to t(...) / i18nKey β€” used for MISSING detection +const dynamicPrefixes = new Set(); +const fullyDynamic = []; // { file, line } +let codeBlob = ""; // all (comment-stripped) source text β€” searched for delimited key literals + +// Strip comments so keys mentioned in comments (e.g. `// t("old.key")`) are not counted as +// usage. Block comments and JSX {/* */} are blanked (preserving newlines for line numbers); +// line comments are only stripped when `//` follows start/whitespace/punctuation, which keeps +// `://` inside string URLs intact. +const stripComments = (src) => + src + .replace(/\/\*[\s\S]*?\*\//g, (m) => m.replace(/[^\n]/g, " ")) + .replace(/(^|[\s;{}()[\],=>])\/\/[^\n]*/g, (_m, p) => p); + +const files = config.srcDirs.flatMap((d) => + walk(join(ROOT, d === "." ? "" : d) || ROOT), +); +for (const file of files) { + const text = readFileSync(file, "utf8"); + const clean = stripComments(text); + codeBlob += `\n${clean}`; + for (const m of clean.matchAll(STATIC_RE)) usedStatic.add(m[2]); + for (const m of clean.matchAll(TPL_STATIC_RE)) usedStatic.add(m[1]); + for (const m of clean.matchAll(I18NKEY_RE)) usedStatic.add(m[2]); + for (const m of clean.matchAll(TPL_DYN_RE)) { + const prefix = m[1]; + if (prefix?.includes(".")) dynamicPrefixes.add(prefix); + else { + const idx = clean.slice(0, m.index).split("\n").length; + fullyDynamic.push({ file: relative(ROOT, file), line: idx }); + } + } +} + +const prefixList = [...dynamicPrefixes]; +// A key counts as used if its EXACT delimited literal ("k" / 'k' / `k`) appears anywhere in +// the code (covers t("k"), , and keys stored as bare string constants in +// arrays/config then resolved via t(variable)), or it is reached via a dynamic prefix, or +// explicitly allow-listed. Delimited search avoids substring false-matches (e.g. a.b vs a.b_c). +const literalUsed = (key) => + codeBlob.includes(`"${key}"`) || + codeBlob.includes(`'${key}'`) || + codeBlob.includes(`\`${key}\``); +const isUsed = (key) => + literalUsed(key) || + prefixList.some((p) => key.startsWith(p)) || + config.ignoreUnused.some((g) => globMatch(key, g)); + +// ---- compute ---- +const unused = sourceKeys.filter((k) => !isUsed(k)).sort(); +// Static references are always validated, even under a dynamic prefix: a dynamic prefix only +// affects the UNUSED calculation, never MISSING. +const missing = [...usedStatic] + .filter((k) => KEY_SHAPE.test(k) && !sourceKeySet.has(k)) + .sort(); +// Known limitation: only keys seen in a static t("…") / i18nKey="…" / t(`…`) call are +// validated for MISSING. A key stored as a bare string constant and resolved via t(variable) +// counts as USED (via literalUsed β†’ not flagged unused) but its existence in en.json is not +// checked here β€” static analysis can't resolve which key a runtime variable holds. Streamyfin +// keys are static literals in practice; revisit if dynamic key constants become common. + +// ---- optional fix: strip dead keys from the source locale (en.json) ---- +const removeKey = (obj, parts) => { + const [head, ...rest] = parts; + if (!(head in obj)) return; + if (rest.length === 0) { + delete obj[head]; + return; + } + removeKey(obj[head], rest); + if ( + obj[head] && + typeof obj[head] === "object" && + Object.keys(obj[head]).length === 0 + ) + delete obj[head]; +}; +if (FIX_UNUSED && unused.length) { + // Only edit the SOURCE locale (en.json). Crowdin owns the target locales and removes + // the keys from them automatically on the next sync once they disappear from the source. + const data = JSON.parse(readFileSync(sourcePath, "utf8")); + for (const key of unused) removeKey(data, key.split(".")); + writeFileSync(sourcePath, `${JSON.stringify(data, null, 2)}\n`); + console.log( + `🧹 Removed ${unused.length} dead key(s) from ${config.sourceLocale}.json (Crowdin will sync the other locales).`, + ); +} + +// ---- report ---- +if (JSON_OUT) { + console.log( + JSON.stringify( + { + sourceKeys: sourceKeys.length, + missing, + unused, + dynamicPrefixes: prefixList, + fullyDynamic, + }, + null, + 2, + ), + ); +} else { + console.log( + `πŸ”‘ i18n key check β€” source: ${relative(ROOT, sourcePath)} (${sourceKeys.length} keys), scanned ${files.length} files`, + ); + if (prefixList.length) + console.log( + ` dynamic prefixes treated as used: ${prefixList.map((p) => `${p}*`).join(", ")}`, + ); + if (fullyDynamic.length) + console.log( + ` ⚠️ ${fullyDynamic.length} fully-dynamic t(\`\${…}\`) call(s) (not key-based, manual review): ${fullyDynamic.map((d) => `${d.file}:${d.line}`).join(", ")}`, + ); + + if (missing.length) { + console.log( + `\n❌ MISSING keys (used in code, absent from ${config.sourceLocale}.json) β€” ${missing.length}:`, + ); + for (const k of missing) console.log(` - ${k}`); + } else console.log("\nβœ… No missing keys."); + + if (UNUSED_MODE !== "off") { + if (unused.length) { + console.log( + `\n${UNUSED_MODE === "error" ? "❌" : "⚠️ "} UNUSED keys (in ${config.sourceLocale}.json, referenced nowhere) β€” ${unused.length}:`, + ); + for (const k of unused) console.log(` - ${k}`); + console.log( + `\n β†’ remove with: bun scripts/check-i18n-keys.mjs --fix-unused`, + ); + console.log( + ` β†’ or allow-list a dynamic key in scripts/i18n-keys.config.json ("ignoreUnused").`, + ); + } else console.log("\nβœ… No unused keys."); + } +} + +const fail = + missing.length > 0 || (UNUSED_MODE === "error" && unused.length > 0); +process.exit(fail ? 1 : 0); diff --git a/scripts/i18n-keys.config.json b/scripts/i18n-keys.config.json new file mode 100644 index 00000000..c5196d82 --- /dev/null +++ b/scripts/i18n-keys.config.json @@ -0,0 +1,46 @@ +{ + "localesDir": "translations", + "sourceLocale": "en", + "srcDirs": [ + "app", + "components", + "hooks", + "providers", + "utils", + "modules", + "packages", + "constants" + ], + "srcExtensions": [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"], + "excludeDirs": [ + "node_modules", + "ios", + "android", + ".expo", + ".git", + "dist", + "build", + "translations" + ], + "_ignoreUnusedNote": "Keys present in en.json but referenced by no t() call β€” allow-listed so the unused-key cleanup keeps them. Two kinds: (1) ORPHANS of features that already exist but render hardcoded strings or use other keys β€” watchlists.* (add/remove, handled by WatchlistSheet via hooks), pin.* (confirm step of the existing PIN setup flow), player.* (in-player subtitle search, swipe-down hint, stop-playback confirm); these should be wired to the live UI or removed in a follow-up i18n pass, not assumed to be future work. (2) GENUINELY PLANNED, tracked by issues: home.settings.other.show_large_home_carousel (#1702 media-bar), home.settings.logs.delete_all_logs (#1703 iOS logs fix), home.suggested_episodes (#1704).", + "ignoreUnused": [ + "watchlists.add_to_watchlist", + "watchlists.remove_from_watchlist", + "watchlists.create_one_first", + "watchlists.no_compatible_watchlists", + "pin.confirm_pin", + "pin.pins_dont_match", + "player.search_subtitles", + "player.subtitle_search", + "player.subtitle_download_hint", + "player.subtitle_tracks", + "player.using_jellyfin_server", + "player.swipe_down_settings", + "player.stopPlayback", + "player.stopPlayingTitle", + "player.stopPlayingConfirm", + "home.settings.other.show_large_home_carousel", + "home.settings.logs.delete_all_logs", + "home.suggested_episodes" + ] +} diff --git a/scripts/ios/build-ios.ts b/scripts/ios/build-ios.ts index 33110507..f5592ae3 100644 --- a/scripts/ios/build-ios.ts +++ b/scripts/ios/build-ios.ts @@ -302,7 +302,7 @@ function parseArgs(argv: string[]): BuildOptions { if (!configArg) { throw new Error("--configuration requires an argument"); } - options.configuration = (configArg as "Debug" | "Release") || "Debug"; + options.configuration = configArg as "Debug" | "Release"; break; } case "--device": @@ -997,10 +997,6 @@ async function waitForSimulatorBoot( } } catch { // Simulator not found or not booted yet, continue polling - if (pollIntervalMs > 1000) { - // Only log if we've been waiting a while to avoid spam - // console.warn("Simulator polling failed, retrying..."); - } } // Wait before next poll diff --git a/scripts/typecheck.js b/scripts/typecheck.js index ea1f4bea..81a2c9bc 100644 --- a/scripts/typecheck.js +++ b/scripts/typecheck.js @@ -140,7 +140,16 @@ function runTypeCheck() { const extraArgs = process.argv.slice(2); // Prefer local TypeScript binary when available - const runnerArgs = ["-p", "tsconfig.json", "--noEmit", ...extraArgs]; + // --pretty false: TS 6 enables pretty output even when piped, which breaks + // the line-based error parser below + const runnerArgs = [ + "-p", + "tsconfig.json", + "--noEmit", + "--pretty", + "false", + ...extraArgs, + ]; let execArgs = null; try { const tscBin = require.resolve("typescript/bin/tsc"); diff --git a/scripts/update-issue-form.mjs b/scripts/update-issue-form.mjs new file mode 100644 index 00000000..d7bc8192 --- /dev/null +++ b/scripts/update-issue-form.mjs @@ -0,0 +1,122 @@ +#!/usr/bin/env bun +/** + * Populates the "Streamyfin Version" dropdown in the issue report form with the + * latest GitHub releases. Run by the "Update Issue Form Versions" workflow on + * release events + a weekly cron (and manually via workflow_dispatch). + * + * Source: published, non-draft, non-prerelease GitHub releases, newest first. + * Non-version sentinels (e.g. "older", "TestFlight/Development build") are + * preserved at the end of the list. + * + * Usage: + * bun scripts/update-issue-form.mjs # rewrite the form in place + * ISSUE_FORM_LIMIT=8 bun scripts/update-issue-form.mjs + * bun scripts/update-issue-form.mjs --dry-run # print the new options, don't write + * + * Env: GITHUB_REPOSITORY (owner/repo), GH_TOKEN/GITHUB_TOKEN (for gh, provided in CI). + */ + +import { execFileSync } from "node:child_process"; +import { + appendFileSync, + readFileSync as read, + writeFileSync as write, +} from "node:fs"; + +const FORM = ".github/ISSUE_TEMPLATE/issue_report.yml"; +const DROPDOWN_ID = "version"; // the `id:` of the dropdown to populate +const parsedLimit = Number.parseInt(process.env.ISSUE_FORM_LIMIT ?? "", 10); +const LIMIT = + Number.isInteger(parsedLimit) && parsedLimit > 0 ? parsedLimit : 5; +const REPO = process.env.GITHUB_REPOSITORY || "streamyfin/streamyfin"; +const DRY = process.argv.includes("--dry-run"); + +// Matches "0.54.1" and prerelease/beta tags like "0.54.0-beta.1". +const isVersion = (s) => /^\d+\.\d+/.test(s.trim()); + +// 1. Fetch the latest published releases (newest first) β€” drafts and prereleases +// aren't a full release users run, so they don't belong in the dropdown. +const raw = execFileSync( + "gh", + [ + "release", + "list", + "--repo", + REPO, + "--exclude-drafts", + "--exclude-pre-releases", + "--limit", + String(LIMIT), + "--json", + "tagName", + "--jq", + ".[].tagName", + ], + // Bounded timeout so a stuck gh process fails the job fast instead of + // holding the workflow open until the job-level timeout. + { encoding: "utf8", timeout: 30_000 }, +); +const seen = new Set(); +const versions = []; +for (const tag of raw.split("\n")) { + if (!tag) continue; + const ver = tag.trim().replace(/^v/, ""); + if (!isVersion(ver) || seen.has(ver)) continue; + seen.add(ver); + versions.push(ver); +} + +if (!versions.length) { + console.error("No release versions found β€” leaving the form untouched."); + process.exit(1); +} + +// 2. rewrite the dropdown options, preserving non-version sentinels +// (e.g. "older", "TestFlight/Development build") at the end of the list. +const lines = read(FORM, "utf8").split("\n"); +const idIdx = lines.findIndex((l) => + l.match(new RegExp(`^\\s*id:\\s*${DROPDOWN_ID}\\s*$`)), +); +if (idIdx === -1) + throw new Error(`dropdown id: ${DROPDOWN_ID} not found in ${FORM}`); +const optIdx = lines.findIndex( + (l, i) => i > idIdx && /^\s*options:\s*$/.test(l), +); +if (optIdx === -1) + throw new Error(`options: not found after id: ${DROPDOWN_ID}`); + +const itemIndent = lines[optIdx].match(/^\s*/)[0] + " "; // options items are nested one level deeper +let end = optIdx + 1; +const sentinels = []; +while (end < lines.length && /^\s*-\s+/.test(lines[end])) { + const val = lines[end].replace(/^\s*-\s+/, ""); + if (!isVersion(val)) sentinels.push(val); + end++; +} + +const newOptions = [...versions, ...sentinels].map( + (v) => `${itemIndent}- ${v}`, +); +const updated = [ + ...lines.slice(0, optIdx + 1), + ...newOptions, + ...lines.slice(end), +].join("\n"); + +console.log( + `Versions: ${versions.join(", ")}${sentinels.length ? ` | kept: ${sentinels.join(", ")}` : ""}`, +); +if (DRY) { + console.log("--dry-run: not writing."); +} else { + write(FORM, updated); + console.log(`Updated ${FORM}.`); +} + +// Expose the resulting list for the workflow (PR description). +if (process.env.GITHUB_OUTPUT) { + appendFileSync( + process.env.GITHUB_OUTPUT, + `versions=${versions.join(", ")}\n`, + ); +} diff --git a/translations/en.json b/translations/en.json index 581e82c4..3c4271b1 100644 --- a/translations/en.json +++ b/translations/en.json @@ -108,7 +108,7 @@ "features_description": "Streamyfin has a bunch of features and integrates with a wide array of software, which you can find in the settings menu. These include:", "jellyseerr_feature_description": "Connect to your Seerr instance and request movies directly in the app.", "downloads_feature_title": "Downloads", - "downloads_feature_description": "Download movies and series to watch offline. Use either the default method or install the optimize server to download files in the background.", + "downloads_feature_description": "Download movies and series to watch offline.", "chromecast_feature_description": "Cast movies and series to your Chromecast devices.", "centralised_settings_plugin_title": "Centralised Settings plugin", "centralised_settings_plugin_description": "Configure settings from a centralised location on your Jellyfin server. All client settings for all users will be synced automatically.", @@ -261,43 +261,6 @@ "None": "None", "OnlyForced": "Only forced" }, - "text_color": "Text color", - "background_color": "Background color", - "outline_color": "Outline color", - "outline_thickness": "Outline thickness", - "background_opacity": "Background opacity", - "outline_opacity": "Outline opacity", - "bold_text": "Bold text", - "colors": { - "Black": "Black", - "Gray": "Gray", - "Silver": "Silver", - "White": "White", - "Maroon": "Maroon", - "Red": "Red", - "Fuchsia": "Fuchsia", - "Yellow": "Yellow", - "Olive": "Olive", - "Green": "Green", - "Teal": "Teal", - "Lime": "Lime", - "Purple": "Purple", - "Navy": "Navy", - "Blue": "Blue", - "Aqua": "Aqua" - }, - "thickness": { - "None": "None", - "Thin": "Thin", - "Normal": "Normal", - "Thick": "Thick" - }, - "subtitle_color": "Subtitle color", - "subtitle_background_color": "Background color", - "subtitle_font": "Subtitle font", - "ksplayer_title": "KSPlayer settings", - "hardware_decode": "Hardware decoding", - "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.", "opensubtitles_title": "OpenSubtitles", "opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.", "opensubtitles_api_key": "API key", @@ -315,25 +278,6 @@ "bottom": "Bottom" } }, - "vlc_subtitles": { - "title": "VLC subtitle settings", - "hint": "Customize subtitle appearance for the VLC player. Changes take effect on next playback.", - "text_color": "Text color", - "background_color": "Background color", - "background_opacity": "Background opacity", - "outline_color": "Outline color", - "outline_opacity": "Outline opacity", - "outline_thickness": "Outline thickness", - "bold": "Bold text", - "margin": "Bottom margin" - }, - "video_player": { - "title": "Video player", - "video_player": "Video player", - "video_player_description": "Choose which video player to use on iOS.", - "ksplayer": "KSPlayer", - "vlc": "VLC" - }, "other": { "other_title": "Other", "video_orientation": "Video orientation", @@ -351,11 +295,6 @@ "UNKNOWN": "Unknown" }, "safe_area_in_controls": "Safe area in controls", - "video_player": "Video player", - "video_players": { - "VLC_3": "VLC 3", - "VLC_4": "VLC 4 (Experimental + PiP)" - }, "show_custom_menu_links": "Show custom menu links", "show_large_home_carousel": "Show large home carousel (beta)", "hide_libraries": "Hide libraries", @@ -367,9 +306,6 @@ "max_auto_play_episode_count": "Max auto-play episode count", "disabled": "Disabled" }, - "downloads": { - "downloads_title": "Downloads" - }, "music": { "title": "Music", "playback_title": "Playback", @@ -384,7 +320,6 @@ "plugins": { "plugins_title": "Plugins", "jellyseerr": { - "jellyseerr_warning": "This integration is in its early stages. Expect things to change.", "server_url": "Server URL", "server_url_hint": "Example: http(s)://your-host.url\n(add port if required)", "server_url_placeholder": "Seerr URL", @@ -413,23 +348,18 @@ "read_more_about_marlin": "Read more about Marlin.", "save_button": "Save", "toasts": { - "saved": "Saved", - "refreshed": "Settings refreshed from server" - }, - "refresh_from_server": "Refresh settings from server" + "saved": "Saved" + } }, "streamystats": { - "enable_streamystats": "Enable Streamystats", "disable_streamystats": "Disable Streamystats", "enable_search": "Use for search", "url": "URL", "server_url_placeholder": "http(s)://streamystats.example.com", "streamystats_search_hint": "Enter the URL for your Streamystats server. The URL should include http or https and optionally the port.", "read_more_about_streamystats": "Read more about Streamystats.", - "save_button": "Save", "save": "Save", "features_title": "Features", - "home_sections_title": "Home sections", "enable_movie_recommendations": "Movie recommendations", "enable_series_recommendations": "Series recommendations", "enable_promoted_watchlists": "Promoted watchlists", @@ -445,8 +375,7 @@ "refresh_from_server": "Refresh settings from server" }, "kefinTweaks": { - "watchlist_enabler": "Enable watchlist integration", - "watchlist_button": "Toggle watchlist integration" + "watchlist_enabler": "Enable watchlist integration" } }, "storage": { @@ -457,7 +386,6 @@ "delete_all_downloaded_files": "Delete all downloaded files", "music_cache_title": "Music cache", "music_cache_description": "Automatically cache songs as you listen for smoother playback and offline support", - "enable_music_cache": "Enable music cache", "clear_music_cache": "Clear music cache", "music_cache_size": "{{size}} cached", "music_cache_cleared": "Music cache cleared", @@ -467,8 +395,6 @@ "clear_all_cache": "Clear all cache", "clear_all_cache_confirm": "Clear all cache?", "clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.", - "clear_all_cache_success": "Cache cleared", - "clear_all_cache_success_desc": "All cache has been cleared successfully.", "clear_all_cache_error_desc": "An error occurred while clearing the cache." }, "intro": { @@ -490,15 +416,12 @@ "system": "System" }, "toasts": { - "error_deleting_files": "Error deleting files", - "background_downloads_enabled": "Background downloads enabled", - "background_downloads_disabled": "Background downloads disabled" + "error_deleting_files": "Error deleting files" }, "security": { "title": "Security", "inactivity_timeout": { "title": "Inactivity timeout", - "description": "Auto logout after inactivity", "disabled": "Disabled", "1_minute": "1 minute", "5_minutes": "5 minutes", @@ -518,10 +441,7 @@ "downloads_title": "Downloads", "series": "Series", "movies": "Movies", - "queue": "Queue", "other_media": "Other media", - "queue_hint": "Queue and downloads will be lost on app restart", - "no_items_in_queue": "No items in queue", "no_downloaded_items": "No downloaded items", "delete_all_movies_button": "Delete all movies", "delete_all_series_button": "Delete all series", @@ -546,13 +466,8 @@ "failed_to_delete_all_series": "Failed to delete all series", "deleted_media_successfully": "Deleted other media successfully!", "failed_to_delete_media": "Failed to delete other media", - "download_deleted": "Download deleted", "download_cancelled": "Download cancelled", "could_not_delete_download": "Could not delete download", - "download_paused": "Download paused", - "could_not_pause_download": "Could not pause download", - "download_resumed": "Download resumed", - "could_not_resume_download": "Could not resume download", "download_completed": "Download completed", "download_failed": "Download failed", "download_failed_for_item": "Download failed for {{item}} - {{error}}", @@ -562,10 +477,7 @@ "item_already_downloading": "{{item}} is already downloading", "all_files_deleted": "All downloads deleted successfully", "files_deleted_by_type": "{{count}} {{type}} deleted", - "all_files_folders_and_jobs_deleted_successfully": "All files, folders, and jobs deleted successfully", - "failed_to_clean_cache_directory": "Failed to clean cache directory", "could_not_get_download_url_for_item": "Could not get download URL for {{itemName}}", - "go_to_downloads": "Go to Downloads", "file_deleted": "{{item}} deleted" } } @@ -583,16 +495,17 @@ "none": "None", "track": "Track", "cancel": "Cancel", - "stop": "Stop", "delete": "Delete", "ok": "OK", "remove": "Remove", - "next": "Next", "back": "Back", "continue": "Continue", "verifying": "Verifying...", "login": "Login", - "refresh": "Refresh" + "episodes": "Episodes", + "movies": "Movies", + "loading": "Loading…", + "seeAll": "See all" }, "search": { "search": "Search...", @@ -691,10 +604,6 @@ "could_not_create_stream_for_chromecast": "Could not create a stream for Chromecast", "message_from_server": "Message from server: {{message}}", "next_episode": "Next episode", - "refresh_tracks": "Refresh tracks", - "audio_tracks": "Audio tracks:", - "playback_state": "Playback state:", - "index": "Index:", "continue_watching": "Continue watching", "go_back": "Go back", "downloaded_file_title": "You have this file downloaded", @@ -723,7 +632,8 @@ "stopPlayback": "Stop playback", "stopPlayingTitle": "Stop playing \"{{title}}\"?", "stopPlayingConfirm": "Are you sure you want to stop playback?", - "downloaded": "Downloaded" + "downloaded": "Downloaded", + "missing_parameters": "Missing playback parameters" }, "chapters": { "title": "Chapters", @@ -761,7 +671,6 @@ "show_more": "Show more", "show_less": "Show less", "left": "left", - "more_info": "More info", "director": "Director", "cast": "Cast", "technical_details": "Technical details", @@ -784,7 +693,8 @@ "resume_playback": "Resume playback", "resume_playback_description": "Do you want to continue where you left off or start from the beginning?", "play_from_start": "Play from start", - "continue_from": "Continue from {{time}}" + "continue_from": "Continue from {{time}}", + "no_data_available": "No data available" }, "live_tv": { "next": "Next", @@ -888,13 +798,9 @@ "playlists": "Playlists", "tracks": "Songs" }, - "filters": { - "all": "All" - }, "recently_added": "Recently added", "recently_played": "Recently played", "frequently_played": "Frequently played", - "explore": "Explore", "top_tracks": "Top songs", "play": "Play", "shuffle": "Shuffle", @@ -1028,7 +934,6 @@ "pairing": { "pair_with_phone": "Pair with phone", "pair_with_phone_title": "Log in on TV", - "pair_with_phone_description": "Scan the QR code displayed on your TV to log in", "waiting_for_phone": "Waiting for phone...", "scan_with_phone": "Scan with the Streamyfin app on your phone", "logging_in": "Logging in...", diff --git a/tsconfig.json b/tsconfig.json index 69354e8d..ecd844cd 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,6 +7,8 @@ "paths": { "@/*": ["./*"] }, + // TS 6.0: "types" now defaults to [] (no auto-inclusion of node_modules/@types) + "types": ["node", "jest"], "incremental": true, "tsBuildInfoFile": ".tsbuildinfo", "skipLibCheck": true, diff --git a/utils/bToMb.ts b/utils/bToMb.ts deleted file mode 100644 index 79b7caf4..00000000 --- a/utils/bToMb.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Convert bits to megabits or gigabits - * - * Return nice looking string - * If under 1000Mb, return XXXMB, else return X.XGB - */ - -export function convertBitsToMegabitsOrGigabits(bits?: number | null): string { - if (!bits) return "0MB"; - - const megabits = bits / 1000000; - - if (megabits < 1000) { - return `${Math.round(megabits)}MB`; - } - const gigabits = megabits / 1000; - return `${gigabits.toFixed(1)}GB`; -} diff --git a/utils/collectionTypeToItemType.ts b/utils/collectionTypeToItemType.ts deleted file mode 100644 index 0889b8d6..00000000 --- a/utils/collectionTypeToItemType.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { - BaseItemKind, - CollectionType, -} from "@jellyfin/sdk/lib/generated-client"; - -/** - * Converts a ColletionType to a BaseItemKind (also called ItemType) - * - * CollectionTypes - * readonly Unknown: "unknown"; - readonly Movies: "movies"; - readonly Tvshows: "tvshows"; - readonly Trailers: "trailers"; - readonly Homevideos: "homevideos"; - readonly Boxsets: "boxsets"; - readonly Books: "books"; - readonly Photos: "photos"; - readonly Livetv: "livetv"; - readonly Playlists: "playlists"; - readonly Folders: "folders"; - */ -export const colletionTypeToItemType = ( - collectionType?: CollectionType | null, -): BaseItemKind | undefined => { - if (!collectionType) return undefined; - - switch (collectionType) { - case CollectionType.Movies: - return BaseItemKind.Movie; - case CollectionType.Tvshows: - return BaseItemKind.Series; - case CollectionType.Homevideos: - return BaseItemKind.Video; - case CollectionType.Books: - return BaseItemKind.Book; - case CollectionType.Playlists: - return BaseItemKind.Playlist; - case CollectionType.Folders: - return BaseItemKind.Folder; - case CollectionType.Photos: - return BaseItemKind.Photo; - case CollectionType.Trailers: - return BaseItemKind.Trailer; - } - - return undefined; -}; diff --git a/utils/hls/parseM3U8ForSubtitles.ts b/utils/hls/parseM3U8ForSubtitles.ts deleted file mode 100644 index 5e0ad382..00000000 --- a/utils/hls/parseM3U8ForSubtitles.ts +++ /dev/null @@ -1,56 +0,0 @@ -import axios from "axios"; - -export interface SubtitleTrack { - index: number; - name: string; - uri: string; - language: string; - default: boolean; - forced: boolean; - autoSelect: boolean; -} - -export async function parseM3U8ForSubtitles( - url: string, -): Promise { - try { - const response = await axios.get(url, { responseType: "text" }); - const lines = response.data.split(/\r?\n/); - const subtitleTracks: SubtitleTrack[] = []; - let index = 0; - - lines.forEach((line: string) => { - if (line.startsWith("#EXT-X-MEDIA:TYPE=SUBTITLES")) { - const attributes = parseAttributes(line); - const track: SubtitleTrack = { - index: index++, - name: attributes.NAME || "", - uri: attributes.URI || "", - language: attributes.LANGUAGE || "", - default: attributes.DEFAULT === "YES", - forced: attributes.FORCED === "YES", - autoSelect: attributes.AUTOSELECT === "YES", - }; - subtitleTracks.push(track); - } - }); - - return subtitleTracks; - } catch (error) { - console.error("Failed to fetch or parse the M3U8 file:", error); - throw error; - } -} - -function parseAttributes(line: string): { [key: string]: string } { - const attributes: { [key: string]: string } = {}; - const regex = /([A-Z-]+)=(?:"([^"]*)"|([^,]*))/g; - - for (const match of line.matchAll(regex)) { - const key = match[1]; - const value = match[2] ?? match[3]; // quoted or unquoted - attributes[key] = value; - } - - return attributes; -} diff --git a/utils/jellyfin/session/capabilities.ts b/utils/jellyfin/session/capabilities.ts deleted file mode 100644 index 4e4f2074..00000000 --- a/utils/jellyfin/session/capabilities.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { Api } from "@jellyfin/sdk"; -import type { AxiosResponse } from "axios"; -import type { Settings } from "../../atoms/settings"; -import { generateDeviceProfile } from "../../profiles/native"; -import { getAuthHeaders } from "../jellyfin"; - -interface PostCapabilitiesParams { - api: Api | null | undefined; - itemId: string | null | undefined; - sessionId: string | null | undefined; - deviceProfile: Settings["deviceProfile"]; -} - -/** - * Marks a media item as not played for a specific user. - * - * @param params - The parameters for marking an item as not played - * @returns A promise that resolves to true if the operation was successful, false otherwise - */ -export const postCapabilities = async ({ - api, - itemId, - sessionId, -}: PostCapabilitiesParams): Promise => { - if (!api || !itemId || !sessionId) { - throw new Error("Missing parameters for marking item as not played"); - } - - try { - const d = api.axiosInstance.post( - `${api.basePath}/Sessions/Capabilities/Full`, - { - playableMediaTypes: ["Audio", "Video"], - supportedCommands: [ - "PlayState", - "Play", - "ToggleFullscreen", - "DisplayMessage", - "Mute", - "Unmute", - "SetVolume", - "ToggleMute", - ], - supportsMediaControl: true, - id: sessionId, - DeviceProfile: generateDeviceProfile(), - }, - { - headers: getAuthHeaders(api), - }, - ); - return d; - } catch (_error) { - throw new Error("Failed to mark as not played"); - } -}; diff --git a/utils/jellyfin/tvshows/nextUp.ts b/utils/jellyfin/tvshows/nextUp.ts deleted file mode 100644 index 414a47a7..00000000 --- a/utils/jellyfin/tvshows/nextUp.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { Api } from "@jellyfin/sdk"; -import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; -import { getAuthHeaders } from "../jellyfin"; - -interface NextUpParams { - itemId?: string | null; - userId?: string | null; - api?: Api | null; -} - -/** - * Fetches the next up episodes for a series or all series for a user. - * - * @param params - The parameters for fetching next up episodes - * @returns A promise that resolves to an array of BaseItemDto representing the next up episodes - */ -export const nextUp = async ({ - itemId, - userId, - api, -}: NextUpParams): Promise => { - if (!userId || !api) { - console.error("Invalid parameters for nextUp: missing userId or api"); - return []; - } - - try { - const response = await api.axiosInstance.get<{ Items: BaseItemDto[] }>( - `${api.basePath}/Shows/NextUp`, - { - params: { - SeriesId: itemId || undefined, - UserId: userId, - Fields: "MediaSourceCount", - }, - headers: getAuthHeaders(api), - }, - ); - - return response.data.Items; - } catch (_error) { - return []; - } -}; diff --git a/utils/jellyfin/user-library/getItemById.ts b/utils/jellyfin/user-library/getItemById.ts deleted file mode 100644 index 261733b6..00000000 --- a/utils/jellyfin/user-library/getItemById.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { Api } from "@jellyfin/sdk"; -import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; -import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api"; - -/** - * Retrieves an item by its ID from the API. - * - * @param api - The Jellyfin API instance. - * @param itemId - The ID of the item to retrieve. - * @returns The item object or undefined if no item matches the ID. - */ -export const getItemById = async ( - api?: Api | null | undefined, - itemId?: string | null | undefined, -): Promise => { - if (!api || !itemId) { - return undefined; - } - - try { - const itemData = await getUserLibraryApi(api).getItem({ itemId }); - - const item = itemData.data; - if (!item) { - console.error("No items found with the specified ID:", itemId); - return undefined; - } - - return item; - } catch (error) { - console.error("Failed to retrieve the item:", error); - throw new Error(`Failed to retrieve the item due to an error: ${error}`); - } -}; diff --git a/utils/log.tsx b/utils/log.tsx index c633ec69..7dc1d53a 100644 --- a/utils/log.tsx +++ b/utils/log.tsx @@ -72,21 +72,6 @@ export const readFromLog = (): LogEntry[] => { return logs ? JSON.parse(logs) : []; }; -export const clearLogs = () => { - storage.remove("logs"); -}; - -export const dumpDownloadDiagnostics = (extra: any = {}) => { - const diagnostics = { - timestamp: new Date().toISOString(), - processes: extra?.processes || [], - nativeTasks: extra?.nativeTasks || [], - focusedProcess: extra?.focusedProcess || null, - }; - writeDebugLog("Download diagnostics", diagnostics); - return diagnostics; -}; - export function useLog() { const context = useContext(LogContext); if (context === null) { diff --git a/utils/secondsToTicks.ts b/utils/secondsToTicks.ts deleted file mode 100644 index df13813e..00000000 --- a/utils/secondsToTicks.ts +++ /dev/null @@ -1,5 +0,0 @@ -// seconds to ticks util - -export function secondsToTicks(seconds: number): number { - return seconds * 10000000; -} diff --git a/utils/secureCredentials.ts b/utils/secureCredentials.ts index bb5f7713..3aad1535 100644 --- a/utils/secureCredentials.ts +++ b/utils/secureCredentials.ts @@ -203,27 +203,6 @@ export async function hasAccountCredential( return stored !== null; } -/** - * Delete all credentials for all accounts on all servers. - */ -export async function clearAllCredentials(): Promise { - const previousServers = getPreviousServers(); - - for (const server of previousServers) { - for (const account of server.accounts) { - const key = credentialKey(server.address, account.userId); - await SecureStore.deleteItemAsync(key); - } - } - - // Clear all accounts from servers - const clearedServers = previousServers.map((server) => ({ - ...server, - accounts: [], - })); - storage.set("previousServers", JSON.stringify(clearedServers)); -} - /** * Add or update an account in a server's accounts list. */ diff --git a/utils/version.ts b/utils/version.ts new file mode 100644 index 00000000..812665c4 --- /dev/null +++ b/utils/version.ts @@ -0,0 +1,94 @@ +import * as Application from "expo-application"; +import Constants from "expo-constants"; + +/** Raw marketing version (app.json `version`), e.g. "0.54.1". Exposed so the Jellyfin + * clientInfo auto-tracks the app version instead of a hardcoded string. */ +export const APP_VERSION = Application.nativeApplicationVersion ?? "unknown"; + +/** Build metadata injected at build time by `app.config.js` into `extra.build`. */ +export interface BuildMeta { + commit?: string | null; + branch?: string | null; + profile?: string | null; + runNumber?: string | null; + builtAt?: string | null; +} + +export interface VersionInfo { + /** Marketing version (CFBundleShortVersionString / android versionName), e.g. "0.54.1". */ + version: string | null; + /** Build number (CFBundleVersion / versionCode), e.g. "42". */ + build: string | null; + /** Short git commit the build was made from, e.g. "a1b2c3d". */ + commit: string | null; + /** Git branch the build was made from, e.g. "develop". */ + branch: string | null; + /** EAS build profile, e.g. "production", "ci", "preview", or null for local. */ + profile: string | null; + /** GitHub Actions run number the build came from, e.g. "2098". Null outside CI. */ + runNumber: string | null; + isDev: boolean; + isProduction: boolean; + /** Graduated label for the Settings "App version" row (see tiering below). */ + display: string; +} + +/** + * Resolve a graduated version string for Settings. + * + * Tiering (most β†’ least detailed): + * - dev / local build β†’ `version Β· branch Β· commit` (full context for debugging) + * - develop / CI / preview β†’ `version Β· commit Β· #run` (pin the exact source; the + * Actions run number maps the build to its run β€” artifacts + logs β€” without + * Expo access) + * - production (store / TestFlight) β†’ `version` (build number intentionally + * not shown: TestFlight already displays it to testers, and the commit pins the + * binary better) + */ +export function getVersionInfo(): VersionInfo { + // Read native/config values defensively β€” a version string must never crash Settings + // (e.g. a dev build whose native expo-constants is out of sync with the JS). + const read = (fn: () => T): T | null => { + try { + return fn() ?? null; + } catch { + return null; + } + }; + + const version = read(() => Application.nativeApplicationVersion); + const build = read(() => Application.nativeBuildVersion); + const meta = (read(() => Constants.expoConfig?.extra?.build) ?? + {}) as BuildMeta; + const commit = meta.commit ?? null; + const branch = meta.branch ?? null; + const profile = meta.profile ?? null; + const runNumber = meta.runNumber ?? null; + const isDev = __DEV__ === true; + const isProduction = + typeof profile === "string" && profile.startsWith("production"); + + let display: string; + if (isDev) { + display = [version ?? "dev", branch, commit].filter(Boolean).join(" Β· "); + } else if (isProduction) { + display = version ?? build ?? "N/A"; + } else { + display = + [version, commit, runNumber && `#${runNumber}`] + .filter(Boolean) + .join(" Β· ") || "N/A"; + } + + return { + version, + build, + commit, + branch, + profile, + runNumber, + isDev, + isProduction, + display, + }; +}