From ce00aeb5f1bb6689400d14adce724f79c206079b Mon Sep 17 00:00:00 2001 From: Gauvain <68083474+Gauvino@users.noreply.github.com> Date: Mon, 2 Jun 2025 13:14:20 +0200 Subject: [PATCH] feat(ci/cd): Add Android builds and quality checks (#694) --- .../actions/spell-check-this/dictionary.txt | 142 ++++++++++++++++++ .github/spell-check.json | 13 ++ .github/workflows/build-android.yml | 80 ++++++++++ .../{build-ios.yaml => build-ios.yml} | 58 +++++-- .github/workflows/check-lockfile.yml | 47 ++++++ .github/workflows/check_spelling.yaml | 66 ++++++++ .github/workflows/ci-codeql.yml | 43 ++++++ .github/workflows/conflict.yml | 24 +++ .github/workflows/lint-pr.yaml | 41 ----- .github/workflows/lint.yaml | 28 ---- .github/workflows/linting.yml | 104 +++++++++++++ .github/workflows/main.yml | 39 ----- .github/workflows/notification.yaml | 18 --- .github/workflows/notification.yml | 24 +++ .github/workflows/stale.yml | 49 ++++++ .gitignore | 3 - bun.lock | 79 ++++------ package.json | 14 +- renovate.json | 48 ++++++ 19 files changed, 728 insertions(+), 192 deletions(-) create mode 100644 .github/actions/spell-check-this/dictionary.txt create mode 100644 .github/spell-check.json create mode 100644 .github/workflows/build-android.yml rename .github/workflows/{build-ios.yaml => build-ios.yml} (50%) create mode 100644 .github/workflows/check-lockfile.yml create mode 100644 .github/workflows/check_spelling.yaml create mode 100644 .github/workflows/ci-codeql.yml create mode 100644 .github/workflows/conflict.yml delete mode 100644 .github/workflows/lint-pr.yaml delete mode 100644 .github/workflows/lint.yaml create mode 100644 .github/workflows/linting.yml delete mode 100644 .github/workflows/main.yml delete mode 100644 .github/workflows/notification.yaml create mode 100644 .github/workflows/notification.yml create mode 100644 .github/workflows/stale.yml create mode 100644 renovate.json diff --git a/.github/actions/spell-check-this/dictionary.txt b/.github/actions/spell-check-this/dictionary.txt new file mode 100644 index 00000000..cb29bc02 --- /dev/null +++ b/.github/actions/spell-check-this/dictionary.txt @@ -0,0 +1,142 @@ +Streamyfin +Jellyfin +TVOS +Expo +submodule-reload +prebuild +bun +biome +Gradle +APK +AAB +Android +iOS +React +ReactDOM +ReactNative +TypeScript +JavaScript +NodeJS +Yarn +npm +Babel +Husky +Jest +Lodash +Zod +Axios +i18next +Jotai +TailwindCSS +NativeWind +Zeego +Shopify +FlashList +MMKV +Podfile +CocoaPods +async +backend +boolean +callback +config +const +dequeue +endpoint +frontend +getter +initializer +middleware +namespace +nullable +param +params +preload +reducer +refactor +runtime +singleton +slug +submodule +thunk +token +utils +uuid +webpack +API +CLI +CPU +DB +DEV +ENV +ID +JSON +OS +PR +SHA +UI +URL +UTF +UUID +VSCode +XML +GitHub +GitLab +Bitbucket +Apple +Google +PlayStore +AppStore +Xcode +FlatList +ScrollView +TouchableOpacity +ViewPager +SafeArea +Navigator +NavigatorIOS +Drawer +BottomSheet +TabView +Reanimated +GestureHandler +ContextMenu +WebView +ProgressBar +Carousel +Slider +VolumeManager +EdgeToEdge +CircularProgress +VisibilitySensor +BackgroundDownloader +NetInfo +ActionSheet +MaterialTopTabs +BottomTabs +ReactQuery +DeviceInfo +ImageColors +LinearGradient +Localization +Notifications +ScreenOrientation +Sensors +Sharing +SplashScreen +StatusBar +SystemUI +TaskManager +Updates +WebBrowser +TODO +FIXME +README +Changelog +Docs +Docstring +Linter +Formatter +Prettier +ESLint +Stylelint \ No newline at end of file diff --git a/.github/spell-check.json b/.github/spell-check.json new file mode 100644 index 00000000..38a8301c --- /dev/null +++ b/.github/spell-check.json @@ -0,0 +1,13 @@ +{ + "ignore_files": [ + "**/node_modules/**", + "**/bun.lockb", + "**/android/**", + "**/ios/**", + "**/*.apk", + "**/*.aab", + "**/*.ipa", + ".github/actions/spell-check-this/dictionary.txt", + ".github/spell-check.json" + ] +} diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 00000000..c2c8df63 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,80 @@ +name: ๐Ÿค– Android APK Build + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_dispatch: + pull_request: + branches: [develop, master] + push: + branches: [develop, master] + +jobs: + build: + runs-on: ubuntu-24.04 + name: ๐Ÿ—๏ธ Build Android APK + permissions: + contents: read + + steps: + - name: ๐Ÿ“ฅ Checkout code + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + show-progress: false + submodules: recursive + fetch-depth: 0 + + - name: ๐Ÿž Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + with: + # @todo: update to 1.x once this is fixed: https://github.com/streamyfin/streamyfin/pull/690#discussion_r2089749689 + bun-version: '1.2.13' + + - name: โ˜• Setup JDK + uses: actions/setup-java@v4.7.1 + with: + distribution: 'zulu' + java-version: '17' + + - name: ๐Ÿ’พ Cache Bun dependencies + uses: actions/cache@v4 + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun-cache- + + - name: ๐Ÿ“ฆ Install dependencies + run: | + bun install --frozen-lockfile + bun run submodule-reload + + - name: ๐Ÿ’พ Cache Android dependencies + uses: actions/cache@v4 + with: + path: | + android/.gradle + key: ${{ runner.os }}-android-deps-${{ hashFiles('android/**/build.gradle') }} + restore-keys: | + ${{ runner.os }}-android-deps- + + - name: ๐Ÿ› ๏ธ Generate project files + run: bun run prebuild + + - name: ๐Ÿš€ Build APK via Bun + run: bun run build:android:local + + - name: ๐Ÿ“… Set date tag + run: echo "DATE_TAG=$(date +%d-%m-%Y_%H-%M-%S)" >> $GITHUB_ENV + + - name: ๐Ÿ“ค Upload APK artifact + uses: actions/upload-artifact@v4.6.2 + with: + name: streamyfin-apk-${{ github.sha }}-${{ env.DATE_TAG }} + path: | + android/app/build/outputs/apk/release/*.apk + android/app/build/outputs/bundle/release/*.aab + retention-days: 7 diff --git a/.github/workflows/build-ios.yaml b/.github/workflows/build-ios.yml similarity index 50% rename from .github/workflows/build-ios.yaml rename to .github/workflows/build-ios.yml index 354ecb00..f5d00a25 100644 --- a/.github/workflows/build-ios.yaml +++ b/.github/workflows/build-ios.yml @@ -1,25 +1,51 @@ -name: Automatic Build and Deploy +name: ๐Ÿค– iOS IPA Build + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true on: workflow_dispatch: - push: - branches: - - main +# push: +# branches: [develop] jobs: build: runs-on: macos-15 - name: Build IOS + name: ๐Ÿ—๏ธ Build iOS IPA + permissions: + contents: read + steps: - - uses: actions/checkout@v2 - name: Check out repository - - uses: oven-sh/setup-bun@v2 + - name: ๐Ÿ“ฅ Check out repository + uses: actions/checkout@v4.2.2 with: - bun-version: latest - - run: | + ref: ${{ github.event.pull_request.head.sha || github.sha }} + show-progress: false + submodules: recursive + fetch-depth: 0 + + - name: ๐Ÿž Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + with: + # @todo: update to 1.x once this is fixed: https://github.com/streamyfin/streamyfin/pull/690#discussion_r2089749689 + bun-version: '1.2.13' + + - name: ๐Ÿ’พ Cache Bun dependencies + uses: actions/cache@v4 + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun-cache- + + - name: ๐Ÿ“ฆ Install & Prepare + run: | bun i && bun run submodule-reload npx expo prebuild - - uses: sparkfabrik/ios-build-action@v2.3.0 + + - name: ๐Ÿ—๏ธ Build iOS app + uses: sparkfabrik/ios-build-action@v2.3.2 with: upload-to-testflight: false increment-build-number: false @@ -47,3 +73,13 @@ jobs: #fastlane-env: stage ios-app-id: com.stetsed.teststreamyfin output-path: build-${{ github.sha }}.ipa + + - name: ๐Ÿ“… Set date tag + run: echo "DATE_TAG=$(date +%d-%m-%Y_%H-%M-%S)" >> $GITHUB_ENV + + - name: ๐Ÿ“ค Upload IPA artifact + uses: actions/upload-artifact@v4.6.2 + with: + name: streamyfin-ipa-${{ github.sha }}-${{ env.DATE_TAG }} + path: build-*.ipa + retention-days: 7 diff --git a/.github/workflows/check-lockfile.yml b/.github/workflows/check-lockfile.yml new file mode 100644 index 00000000..4af3a94d --- /dev/null +++ b/.github/workflows/check-lockfile.yml @@ -0,0 +1,47 @@ +name: ๐Ÿ”’ Lockfile Consistency Check + +on: + pull_request: + branches: [develop, master] + push: + branches: [develop, master] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + check-lockfile: + name: ๐Ÿ” Check bun.lock and package.json consistency + runs-on: ubuntu-24.04 + permissions: + contents: read + + steps: + - name: ๐Ÿ“ฅ Checkout repository + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + show-progress: false + submodules: recursive + fetch-depth: 0 + + - name: ๐Ÿž Setup Bun + uses: oven-sh/setup-bun@v2.0.2 + # @todo: update to 1.x once this is fixed: https://github.com/streamyfin/streamyfin/pull/690#discussion_r2089749689 + with: + bun-version: '1.2.13' + + - name: ๐Ÿ’พ Cache Bun dependencies + uses: actions/cache@v4.2.3 + with: + path: | + ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} + + - name: ๐Ÿ›ก๏ธ Verify lockfile consistency + run: | + set -euxo pipefail + echo "โžก๏ธ Checking for discrepancies between bun.lock and package.json..." + bun install --frozen-lockfile --dry-run --ignore-scripts + echo "โœ… Lockfile is consistent with package.json!" diff --git a/.github/workflows/check_spelling.yaml b/.github/workflows/check_spelling.yaml new file mode 100644 index 00000000..54435c53 --- /dev/null +++ b/.github/workflows/check_spelling.yaml @@ -0,0 +1,66 @@ +name: ๐Ÿ“ Check Spelling + +on: + push: + branches: + - develop + - master + pull_request_target: + branches: + - develop + - master + types: + - 'opened' + - 'reopened' + - 'synchronize' + +jobs: + spelling: + name: ๐Ÿ”Ž Spelling Check + permissions: + contents: read + pull-requests: read + actions: read + outputs: + followup: ${{ steps.spelling.outputs.followup }} + runs-on: ubuntu-24.04 + concurrency: + group: spelling-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + + steps: + - name: ๐Ÿ“ฅ Checkout repository + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + show-progress: false + submodules: recursive + fetch-depth: 0 + + - name: ๐Ÿช„ Run Spelling Checker + id: spelling + uses: check-spelling/check-spelling@main + with: + checkout: true + check_file_names: 1 + spell_check_this: check-spelling/spell-check-this@prerelease + post_comment: 0 + warnings: bad-regex,deprecated-feature,noisy-file + extra_dictionaries: | + cspell:software-terms/dict/softwareTerms.txt + local:.github/actions/spell-check-this/dictionary.txt + + comment-pr: + name: ๐Ÿ’ฌ Report (PR) + runs-on: ubuntu-24.04 + needs: spelling + permissions: + pull-requests: write + if: (success() || failure()) && needs.spelling.outputs.followup + steps: + - name: ๐Ÿ’ฌ Post Spelling Report + uses: check-spelling/check-spelling@main + with: + checkout: true + spell_check_this: check-spelling/spell-check-this@prerelease + task: ${{ needs.spelling.outputs.followup }} diff --git a/.github/workflows/ci-codeql.yml b/.github/workflows/ci-codeql.yml new file mode 100644 index 00000000..ebf9ead1 --- /dev/null +++ b/.github/workflows/ci-codeql.yml @@ -0,0 +1,43 @@ +name: ๐Ÿ›ก๏ธ CodeQL Analysis + +on: + push: + branches: [master, develop] + pull_request: + branches: [master, develop] + schedule: + - cron: '24 2 * * *' + + +jobs: + analyze: + name: ๐Ÿ”Ž Analyze with CodeQL + runs-on: ubuntu-24.04 + permissions: + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript-typescript' ] + + steps: + - name: ๐Ÿ“ฅ Checkout repository + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + show-progress: false + fetch-depth: 0 + + - name: ๐Ÿ Initialize CodeQL + uses: github/codeql-action/init@v3.28.17 + with: + languages: ${{ matrix.language }} + queries: +security-extended,security-and-quality + + - name: ๐Ÿ› ๏ธ Autobuild + uses: github/codeql-action/autobuild@v3.28.17 + + - name: ๐Ÿงช Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3.28.1 diff --git a/.github/workflows/conflict.yml b/.github/workflows/conflict.yml new file mode 100644 index 00000000..6b2aa663 --- /dev/null +++ b/.github/workflows/conflict.yml @@ -0,0 +1,24 @@ +name: ๐Ÿท๏ธ๐Ÿ”€Merge Conflict Labeler + +on: + push: + branches: [develop] + pull_request_target: + branches: [develop] + types: [synchronize] + +jobs: + label: + name: ๐Ÿท๏ธ Labeling Merge Conflicts + runs-on: ubuntu-24.04 + if: ${{ github.repository == 'streamyfin/streamyfin' }} + permissions: + contents: read + pull-requests: write + steps: + - name: ๐Ÿšฉ Apply merge conflict label + uses: eps1lon/actions-label-merge-conflict@v3.0.3 + with: + dirtyLabel: 'merge conflict' + commentOnDirty: 'This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged.' + repoToken: '${{ secrets.GITHUB_TOKEN }}' diff --git a/.github/workflows/lint-pr.yaml b/.github/workflows/lint-pr.yaml deleted file mode 100644 index 68e2bd8e..00000000 --- a/.github/workflows/lint-pr.yaml +++ /dev/null @@ -1,41 +0,0 @@ -name: "Lint PR" - -on: - pull_request_target: - types: - - opened - - edited - - synchronize - - reopened - -permissions: - pull-requests: write - -jobs: - main: - name: Validate PR title - runs-on: ubuntu-latest - steps: - - uses: amannn/action-semantic-pull-request@v5 - id: lint_pr_title - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: marocchino/sticky-pull-request-comment@v2 - if: always() && (steps.lint_pr_title.outputs.error_message != null) - with: - header: pr-title-lint-error - message: | - Hey there and thank you for opening this pull request! ๐Ÿ‘‹๐Ÿผ - - We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. - - Details: - - ``` - ${{ steps.lint_pr_title.outputs.error_message }} - ``` - - if: ${{ steps.lint_pr_title.outputs.error_message == null }} - uses: marocchino/sticky-pull-request-comment@v2 - with: - header: pr-title-lint-error - delete: true \ No newline at end of file diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml deleted file mode 100644 index d63811e7..00000000 --- a/.github/workflows/lint.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Lint - -on: - pull_request: - branches: [ develop, master ] - -jobs: - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: '20.x' - - - name: Setup Bun - uses: oven-sh/setup-bun@v1 - with: - bun-version: latest - - - name: Install dependencies - run: bun install - - - name: Run linting checks - run: bun run check diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml new file mode 100644 index 00000000..601fc6d6 --- /dev/null +++ b/.github/workflows/linting.yml @@ -0,0 +1,104 @@ +name: ๐Ÿšฆ Security & Quality Gate + +on: + pull_request_target: + types: [opened, edited, synchronize, reopened] + branches: [develop, master] + workflow_dispatch: + +permissions: + contents: read + +jobs: + validate_pr_title: + name: "๐Ÿ“ Validate PR Title" + runs-on: ubuntu-24.04 + permissions: + pull-requests: write + contents: read + steps: + - uses: amannn/action-semantic-pull-request@v5.5.3 + id: lint_pr_title + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: marocchino/sticky-pull-request-comment@v2.9.2 + if: always() && (steps.lint_pr_title.outputs.error_message != null) + with: + header: pr-title-lint-error + message: | + Hey there and thank you for opening this pull request! ๐Ÿ‘‹๐Ÿผ + We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/). + + **Error details:** + ``` + ${{ steps.lint_pr_title.outputs.error_message }} + ``` + + - if: ${{ steps.lint_pr_title.outputs.error_message == null }} + uses: marocchino/sticky-pull-request-comment@v2.9.2 + with: + header: pr-title-lint-error + delete: true + + dependency-review: + name: ๐Ÿ” Vulnerable Dependencies + runs-on: ubuntu-24.04 + permissions: + contents: read + steps: + - name: Checkout Repository + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 + + - name: Dependency Review + uses: actions/dependency-review-action@v4.7.1 + with: + fail-on-severity: high + deny-licenses: GPL-3.0, AGPL-3.0 + base-ref: ${{ github.event.pull_request.base.sha || 'develop' }} + head-ref: ${{ github.event.pull_request.head.sha || github.ref }} + + code_quality: + name: "๐Ÿ” Lint & Test (${{ matrix.command }})" + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + command: + - "lint" + - "check" + steps: + - name: "๐Ÿ“ฅ Checkout PR code" + uses: actions/checkout@v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha }} + submodules: recursive + fetch-depth: 0 + + - name: "๐ŸŸข Setup Node.js" + uses: actions/setup-node@v4.4.0 + with: + node-version: '20.x' + cache: bun + + - name: "๐Ÿž Setup Bun" + uses: oven-sh/setup-bun@v2.0.2 + with: + # @todo: update to 1.x once this is fixed: https://github.com/streamyfin/streamyfin/pull/690#discussion_r2089749689 + bun-version: '1.2.13' + + - name: ๐Ÿ’พ Cache Bun dependencies + uses: actions/cache@v4.2.3 + with: + path: | + ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} + + - name: "๐Ÿ“ฆ Install dependencies" + run: bun install --frozen-lockfile + + - name: "๐Ÿšจ Run ${{ matrix.command }}" + run: bun run ${{ matrix.command }} diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 474eef39..00000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Handle Stale Issues -on: - schedule: - - cron: "30 1 * * *" # Runs at 1:30 UTC every day - -jobs: - stale: - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - - steps: - - uses: actions/stale@v9 - with: - # Issue specific settings - days-before-issue-stale: 90 - days-before-issue-close: 7 - stale-issue-label: "stale" - stale-issue-message: | - This issue has been automatically marked as stale because it has had no activity in the last 30 days. - - If this issue is still relevant, please leave a comment to keep it open. - Otherwise, it will be closed in 7 days if no further activity occurs. - - Thank you for your contributions! - close-issue-message: | - This issue has been automatically closed because it has been inactive for 7 days since being marked as stale. - - If you believe this issue is still relevant, please feel free to reopen it and add a comment explaining the current status. - - # Pull request settings (disabled) - days-before-pr-stale: -1 - days-before-pr-close: -1 - - # Other settings - repo-token: ${{ secrets.GITHUB_TOKEN }} - operations-per-run: 100 - exempt-issue-labels: "Roadmap v1,help needed,enhancement" diff --git a/.github/workflows/notification.yaml b/.github/workflows/notification.yaml deleted file mode 100644 index 00cab601..00000000 --- a/.github/workflows/notification.yaml +++ /dev/null @@ -1,18 +0,0 @@ -name: Discord Pull Request Notification - -on: - pull_request: - types: [opened, reopened] - -jobs: - notify: - runs-on: ubuntu-latest - steps: - - uses: joelwmale/webhook-action@master - with: - url: ${{ secrets.DISCORD_WEBHOOK_URL }} - body: | - { - "content": "New Pull Request: ${{ github.event.pull_request.title }}\nBy: ${{ github.event.pull_request.user.login }}\n\n${{ github.event.pull_request.html_url }}", - "avatar_url": "https://avatars.githubusercontent.com/u/193271640" - } diff --git a/.github/workflows/notification.yml b/.github/workflows/notification.yml new file mode 100644 index 00000000..2b882073 --- /dev/null +++ b/.github/workflows/notification.yml @@ -0,0 +1,24 @@ +name: ๐Ÿ›Ž๏ธ Discord Pull Request Notification + +on: + pull_request: + types: [opened, reopened] + branches: [develop] + +jobs: + notify: + runs-on: ubuntu-24.04 + steps: + - name: ๐Ÿ›Ž๏ธ Notify Discord + uses: Ilshidur/action-discord@0.3.2 + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL }} + DISCORD_AVATAR: https://avatars.githubusercontent.com/u/193271640 + with: + args: | + ๐Ÿ“ข New Pull Request in **${{ github.repository }}** + **Title:** ${{ github.event.pull_request.title }} + **By:** ${{ github.event.pull_request.user.login }} + **Branch:** ${{ github.event.pull_request.head.ref }} + **Description:** ${{ github.event.pull_request.body }} + ๐Ÿ”— ${{ github.event.pull_request.html_url }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 00000000..ec7177cd --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,49 @@ +name: ๐Ÿ•’ Handle Stale Issues + +on: + schedule: + # Runs daily at 1:30 AM UTC (3:30 AM CEST - France time) + - cron: "30 1 * * *" + +jobs: + stale-issues: + name: ๐Ÿ—‘๏ธ Cleanup Stale Issues + runs-on: ubuntu-24.04 + permissions: + issues: write + pull-requests: write + + steps: + - name: ๐Ÿ”„ Mark/Close Stale Issues + uses: actions/stale@v9.1.0 + with: + # Global settings + repo-token: ${{ secrets.GITHUB_TOKEN }} + operations-per-run: 500 # Increase if you have >1000 issues + log-level: debug + + # Issue configuration + days-before-issue-stale: 90 + days-before-issue-close: 7 + stale-issue-label: "stale" + exempt-issue-labels: "Roadmap v1,help needed,enhancement" + + # Notifications messages + stale-issue-message: | + โณ This issue has been automatically marked as **stale** because it has had no activity for 90 days. + + **Next steps:** + - If this is still relevant, add a comment to keep it open + - Otherwise, it will be closed in 7 days + + Thank you for your contributions! ๐Ÿ™Œ + + close-issue-message: | + ๐Ÿšฎ This issue has been automatically closed due to inactivity (7 days since being marked stale). + + **Need to reopen?** + Click "Reopen" and add a comment explaining why this should stay open. + + # Disable PR handling + days-before-pr-stale: -1 + days-before-pr-close: -1 diff --git a/.gitignore b/.gitignore index d5a950b9..288bf0db 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ npm-debug.* web-build/ modules/vlc-player/android/build modules/vlc-player/android/.gradle -bun.lockb # macOS .DS_Store @@ -20,9 +19,7 @@ expo-env.d.ts Streamyfin.app -build-* *.mp4 -build-* Streamyfin.app package-lock.json diff --git a/bun.lock b/bun.lock index f149db9f..eab6319e 100644 --- a/bun.lock +++ b/bun.lock @@ -57,7 +57,7 @@ "react": "18.3.1", "react-dom": "18.3.1", "react-i18next": "^15.4.0", - "react-native": "npm:react-native-tvos@~0.77.0-0", + "react-native": "npm:react-native-tvos@~0.77.2-0", "react-native-awesome-slider": "^2.9.0", "react-native-bottom-tabs": "0.8.6", "react-native-circular-progress": "^1.4.1", @@ -107,6 +107,7 @@ "@types/react-native-vector-icons": "^6.4.18", "@types/react-test-renderer": "^19.0.0", "@types/uuid": "^10.0.0", + "cross-env": "^7.0.3", "husky": "^9.1.7", "lint-staged": "^15.5.0", "postinstall-postinstall": "^2.1.0", @@ -624,27 +625,27 @@ "@react-native-tvos/config-tv": ["@react-native-tvos/config-tv@0.1.1", "", { "dependencies": { "getenv": "^1.0.0" }, "peerDependencies": { "expo": "^52" } }, "sha512-Le/5wGElcNarDcoafCbvk/HMxcG3s0/468xXMWqAsOtBhGAdGtyXtjWEgp/uEr4GgZJlEIdM3ZqiuB8P7p8sjw=="], - "@react-native-tvos/virtualized-lists": ["@react-native-tvos/virtualized-lists@0.77.0-0", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^18.2.6", "react": "*", "react-native-tvos": "*" }, "optionalPeers": ["@types/react"] }, "sha512-em0PMjOD8XQvlygbFoNT4R76rSIRxekZ9TL6EbTIC/kJUDrSPB3W9RafA6n6p4OLoWgEF7MIJ9W+zfibdiVXbw=="], + "@react-native-tvos/virtualized-lists": ["@react-native-tvos/virtualized-lists@0.77.2-0", "", { "dependencies": { "invariant": "^2.2.4", "nullthrows": "^1.1.1" }, "peerDependencies": { "@types/react": "^18.2.6", "react": "*", "react-native": "*" }, "optionalPeers": ["@types/react"] }, "sha512-9l51YsjgrUv6f3Q8bmQPIPRuID6gLfc29CjLLQ3+RIeHFF1xzT/xwOp0+s7JMhDdZOZ5mcn9RiN7BbmcPej08A=="], - "@react-native/assets-registry": ["@react-native/assets-registry@0.77.0", "", {}, "sha512-Ms4tYYAMScgINAXIhE4riCFJPPL/yltughHS950l0VP5sm5glbimn9n7RFn9Tc8cipX74/ddbk19+ydK2iDMmA=="], + "@react-native/assets-registry": ["@react-native/assets-registry@0.77.2", "", {}, "sha512-AcEhFjndzBWVVhaHaASk36vhA83iDVkQbFYb0D0vATzjuJ67vhhHVLae0+JtHl5jhghotUFDg4Vj/1QbZNDyyQ=="], "@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.76.7", "", { "dependencies": { "@react-native/codegen": "0.76.7" } }, "sha512-+8H4DXJREM4l/pwLF/wSVMRzVhzhGDix5jLezNrMD9J1U1AMfV2aSkWA1XuqR7pjPs/Vqf6TaPL7vJMZ4LU05Q=="], "@react-native/babel-preset": ["@react-native/babel-preset@0.76.7", "", { "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-arrow-functions": "^7.24.7", "@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-computed-properties": "^7.24.7", "@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-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@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-numeric-separator": "^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.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-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.76.7", "babel-plugin-syntax-hermes-parser": "^0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-/c5DYZ6y8tyg+g8tgXKndDT7mWnGmkZ9F+T3qNDfoE3Qh7ucrNeC2XWvU9h5pk8eRtj9l4SzF4aO1phzwoibyg=="], - "@react-native/codegen": ["@react-native/codegen@0.77.0", "", { "dependencies": { "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "jscodeshift": "^17.0.0", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/preset-env": "^7.1.6" } }, "sha512-rE9lXx41ZjvE8cG7e62y/yGqzUpxnSvJ6me6axiX+aDewmI4ZrddvRGYyxCnawxy5dIBHSnrpZse3P87/4Lm7w=="], + "@react-native/codegen": ["@react-native/codegen@0.77.2", "", { "dependencies": { "@babel/parser": "^7.25.3", "glob": "^7.1.1", "hermes-parser": "0.25.1", "invariant": "^2.2.4", "jscodeshift": "^17.0.0", "nullthrows": "^1.1.1", "yargs": "^17.6.2" }, "peerDependencies": { "@babel/preset-env": "^7.1.6" } }, "sha512-uJSGm9Sp9K5XAhb17cty6iOc2lZpORQKMpS61/B3gYwe9LNz9TJpcfq1L2+3Mv6lppqsulOH9+fslapo0OTfSQ=="], - "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.77.0", "", { "dependencies": { "@react-native/dev-middleware": "0.77.0", "@react-native/metro-babel-transformer": "0.77.0", "chalk": "^4.0.0", "debug": "^2.2.0", "invariant": "^2.2.4", "metro": "^0.81.0", "metro-config": "^0.81.0", "metro-core": "^0.81.0", "readline": "^1.3.0", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli-server-api": "*" }, "optionalPeers": ["@react-native-community/cli-server-api"] }, "sha512-GRshwhCHhtupa3yyCbel14SlQligV8ffNYN5L1f8HCo2SeGPsBDNjhj2U+JTrMPnoqpwowPGvkCwyqwqYff4MQ=="], + "@react-native/community-cli-plugin": ["@react-native/community-cli-plugin@0.77.2", "", { "dependencies": { "@react-native/dev-middleware": "0.77.2", "@react-native/metro-babel-transformer": "0.77.2", "chalk": "^4.0.0", "debug": "^2.2.0", "invariant": "^2.2.4", "metro": "^0.81.3", "metro-config": "^0.81.3", "metro-core": "^0.81.3", "readline": "^1.3.0", "semver": "^7.1.3" }, "peerDependencies": { "@react-native-community/cli": "*" }, "optionalPeers": ["@react-native-community/cli"] }, "sha512-Dc93eXHhzhnRy+vF3wOdM8C4dplLpT7ItpUpYrDeA1ffHUImwWpcupB6vpX9+l3UaaJ1cPfdxTjB2d1ACVKOaA=="], "@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.76.7", "", {}, "sha512-89ZtZXt7ZxE94i7T94qzZMhp4Gfcpr/QVpGqEaejAxZD+gvDCH21cYSF+/Rz2ttBazm0rk5MZ0mFqb0Iqp1jmw=="], "@react-native/dev-middleware": ["@react-native/dev-middleware@0.76.7", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.76.7", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^2.2.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", "serve-static": "^1.13.1", "ws": "^6.2.3" } }, "sha512-Jsw8g9DyLPnR9yHEGuT09yHZ7M88/GL9CtU9WmyChlBwdXSeE3AmRqLegsV3XcgULQ1fqdemokaOZ/MwLYkjdA=="], - "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.77.0", "", {}, "sha512-rmfh93jzbndSq7kihYHUQ/EGHTP8CCd3GDCmg5SbxSOHAaAYx2HZ28ZG7AVcGUsWeXp+e/90zGIyfOzDRx0Zaw=="], + "@react-native/gradle-plugin": ["@react-native/gradle-plugin@0.77.2", "", {}, "sha512-M3kU6xnn/06CGdezd31wn64v/BuKdw19K3GjOcRe1L+zKYEeezRovEVgzCNsXLcNtXUfJvmrIN4uYnqmgrJGfg=="], - "@react-native/js-polyfills": ["@react-native/js-polyfills@0.77.0", "", {}, "sha512-kHFcMJVkGb3ptj3yg1soUsMHATqal4dh0QTGAbYihngJ6zy+TnP65J3GJq4UlwqFE9K1RZkeCmTwlmyPFHOGvA=="], + "@react-native/js-polyfills": ["@react-native/js-polyfills@0.77.2", "", {}, "sha512-qwKeYqRANL8CKzeVWOdhRZJ7LBqqoiXR+cb5yGwVKQxqesrx5Y7gYyq6GP1zRMnhv9iQAY7Rwub8TvDxi2YP6Q=="], - "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.77.0", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.77.0", "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" } }, "sha512-19GfvhBRKCU3UDWwCnDR4QjIzz3B2ZuwhnxMRwfAgPxz7QY9uKour9RGmBAVUk1Wxi/SP7dLEvWnmnuBO39e2A=="], + "@react-native/metro-babel-transformer": ["@react-native/metro-babel-transformer@0.77.2", "", { "dependencies": { "@babel/core": "^7.25.2", "@react-native/babel-preset": "0.77.2", "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" } }, "sha512-vSG1/d5peUo50aqaBbNnVGE5QxQTSY3j0OWmixfJqiX11wwO3tR2niKxH8OjB3WuSsROgJzosMe9kMsQJQ3ONA=="], "@react-native/normalize-colors": ["@react-native/normalize-colors@0.76.7", "", {}, "sha512-ST1xxBuYVIXPdD81dR6+tzIgso7m3pa9+6rOBXTh5Xm7KEEFik7tnQX+GydXYMp3wr1gagJjragdXkPnxK6WNg=="], @@ -984,6 +985,8 @@ "cosmiconfig": ["cosmiconfig@9.0.0", "", { "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-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg=="], + "cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], + "cross-fetch": ["cross-fetch@3.2.0", "", { "dependencies": { "node-fetch": "^2.7.0" } }, "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -1574,33 +1577,33 @@ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], - "metro": ["metro@0.81.1", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.25.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.81.1", "metro-cache": "0.81.1", "metro-cache-key": "0.81.1", "metro-config": "0.81.1", "metro-core": "0.81.1", "metro-file-map": "0.81.1", "metro-resolver": "0.81.1", "metro-runtime": "0.81.1", "metro-source-map": "0.81.1", "metro-symbolicate": "0.81.1", "metro-transform-plugins": "0.81.1", "metro-transform-worker": "0.81.1", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-fqRu4fg8ONW7VfqWFMGgKAcOuMzyoQah2azv9Y3VyFXAmG+AoTU6YIFWqAADESCGVWuWEIvxTJhMf3jxU6jwjA=="], + "metro": ["metro@0.81.5", "", { "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "@babel/types": "^7.25.2", "accepts": "^1.3.7", "chalk": "^4.0.0", "ci-info": "^2.0.0", "connect": "^3.6.5", "debug": "^2.2.0", "error-stack-parser": "^2.0.6", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "hermes-parser": "0.25.1", "image-size": "^1.0.2", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "jsc-safe-url": "^0.2.2", "lodash.throttle": "^4.1.1", "metro-babel-transformer": "0.81.5", "metro-cache": "0.81.5", "metro-cache-key": "0.81.5", "metro-config": "0.81.5", "metro-core": "0.81.5", "metro-file-map": "0.81.5", "metro-resolver": "0.81.5", "metro-runtime": "0.81.5", "metro-source-map": "0.81.5", "metro-symbolicate": "0.81.5", "metro-transform-plugins": "0.81.5", "metro-transform-worker": "0.81.5", "mime-types": "^2.1.27", "nullthrows": "^1.1.1", "serialize-error": "^2.1.0", "source-map": "^0.5.6", "throat": "^5.0.0", "ws": "^7.5.10", "yargs": "^17.6.2" }, "bin": { "metro": "src/cli.js" } }, "sha512-YpFF0DDDpDVygeca2mAn7K0+us+XKmiGk4rIYMz/CRdjFoCGqAei/IQSpV0UrGfQbToSugpMQeQJveaWSH88Hg=="], - "metro-babel-transformer": ["metro-babel-transformer@0.81.1", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" } }, "sha512-JECKDrQaUnDmj0x/Q/c8c5YwsatVx38Lu+BfCwX9fR8bWipAzkvJocBpq5rOAJRDXRgDcPv2VO4Q4nFYrpYNQg=="], + "metro-babel-transformer": ["metro-babel-transformer@0.81.5", "", { "dependencies": { "@babel/core": "^7.25.2", "flow-enums-runtime": "^0.0.6", "hermes-parser": "0.25.1", "nullthrows": "^1.1.1" } }, "sha512-oKCQuajU5srm+ZdDcFg86pG/U8hkSjBlkyFjz380SZ4TTIiI5F+OQB830i53D8hmqmcosa4wR/pnKv8y4Q3dLw=="], - "metro-cache": ["metro-cache@0.81.1", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "metro-core": "0.81.1" } }, "sha512-Uqcmn6sZ+Y0VJHM88VrG5xCvSeU7RnuvmjPmSOpEcyJJBe02QkfHL05MX2ZyGDTyZdbKCzaX0IijrTe4hN3F0Q=="], + "metro-cache": ["metro-cache@0.81.5", "", { "dependencies": { "exponential-backoff": "^3.1.1", "flow-enums-runtime": "^0.0.6", "metro-core": "0.81.5" } }, "sha512-wOsXuEgmZMZ5DMPoz1pEDerjJ11AuMy9JifH4yNW7NmWS0ghCRqvDxk13LsElzLshey8C+my/tmXauXZ3OqZgg=="], - "metro-cache-key": ["metro-cache-key@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-5fDaHR1yTvpaQuwMAeEoZGsVyvjrkw9IFAS7WixSPvaNY5YfleqoJICPc6hbXFJjvwCCpwmIYFkjqzR/qJ6yqA=="], + "metro-cache-key": ["metro-cache-key@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-lGWnGVm1UwO8faRZ+LXQUesZSmP1LOg14OVR+KNPBip8kbMECbQJ8c10nGesw28uQT7AE0lwQThZPXlxDyCLKQ=="], - "metro-config": ["metro-config@0.81.1", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.6.3", "metro": "0.81.1", "metro-cache": "0.81.1", "metro-core": "0.81.1", "metro-runtime": "0.81.1" } }, "sha512-VAAJmxsKIZ+Fz5/z1LVgxa32gE6+2TvrDSSx45g85WoX4EtLmdBGP3DSlpQW3DqFUfNHJCGwMLGXpJnxifd08g=="], + "metro-config": ["metro-config@0.81.5", "", { "dependencies": { "connect": "^3.6.5", "cosmiconfig": "^5.0.5", "flow-enums-runtime": "^0.0.6", "jest-validate": "^29.7.0", "metro": "0.81.5", "metro-cache": "0.81.5", "metro-core": "0.81.5", "metro-runtime": "0.81.5" } }, "sha512-oDRAzUvj6RNRxratFdcVAqtAsg+T3qcKrGdqGZFUdwzlFJdHGR9Z413sW583uD2ynsuOjA2QB6US8FdwiBdNKg=="], - "metro-core": ["metro-core@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.81.1" } }, "sha512-4d2/+02IYqOwJs4dmM0dC8hIZqTzgnx2nzN4GTCaXb3Dhtmi/SJ3v6744zZRnithhN4lxf8TTJSHnQV75M7SSA=="], + "metro-core": ["metro-core@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "lodash.throttle": "^4.1.1", "metro-resolver": "0.81.5" } }, "sha512-+2R0c8ByfV2N7CH5wpdIajCWa8escUFd8TukfoXyBq/vb6yTCsznoA25FhNXJ+MC/cz1L447Zj3vdUfCXIZBwg=="], - "metro-file-map": ["metro-file-map@0.81.1", "", { "dependencies": { "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.6.3", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-aY72H2ujmRfFxcsbyh83JgqFF+uQ4HFN1VhV2FmcfQG4s1bGKf2Vbkk+vtZ1+EswcBwDZFbkpvAjN49oqwGzAA=="], + "metro-file-map": ["metro-file-map@0.81.5", "", { "dependencies": { "debug": "^2.2.0", "fb-watchman": "^2.0.0", "flow-enums-runtime": "^0.0.6", "graceful-fs": "^4.2.4", "invariant": "^2.2.4", "jest-worker": "^29.7.0", "micromatch": "^4.0.4", "nullthrows": "^1.1.1", "walker": "^1.0.7" } }, "sha512-mW1PKyiO3qZvjeeVjj1brhkmIotObA3/9jdbY1fQQYvEWM6Ml7bN/oJCRDGn2+bJRlG+J8pwyJ+DgdrM4BsKyg=="], - "metro-minify-terser": ["metro-minify-terser@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-p/Qz3NNh1nebSqMlxlUALAnESo6heQrnvgHtAuxufRPtKvghnVDq9hGGex8H7z7YYLsqe42PWdt4JxTA3mgkvg=="], + "metro-minify-terser": ["metro-minify-terser@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "terser": "^5.15.0" } }, "sha512-/mn4AxjANnsSS3/Bb+zA1G5yIS5xygbbz/OuPaJYs0CPcZCaWt66D+65j4Ft/nJkffUxcwE9mk4ubpkl3rjgtw=="], - "metro-resolver": ["metro-resolver@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-E61t6fxRoYRkl6Zo3iUfCKW4DYfum/bLjcejXBMt1y3I7LFkK84TCR/Rs9OAwsMCY/7GOPB4+CREYZOtCC7CNA=="], + "metro-resolver": ["metro-resolver@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-6BX8Nq3g3go3FxcyXkVbWe7IgctjDTk6D9flq+P201DfHHQ28J+DWFpVelFcrNTn4tIfbP/Bw7u/0g2BGmeXfQ=="], - "metro-runtime": ["metro-runtime@0.81.1", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-pqu5j5d01rjF85V/K8SDDJ0NR3dRp6bE3z5bKVVb5O2Rx0nbR9KreUxYALQCRCcQHaYySqCg5fYbGKBHC295YQ=="], + "metro-runtime": ["metro-runtime@0.81.5", "", { "dependencies": { "@babel/runtime": "^7.25.0", "flow-enums-runtime": "^0.0.6" } }, "sha512-M/Gf71ictUKP9+77dV/y8XlAWg7xl76uhU7ggYFUwEdOHHWPG6gLBr1iiK0BmTjPFH8yRo/xyqMli4s3oGorPQ=="], - "metro-source-map": ["metro-source-map@0.81.1", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.81.1", "nullthrows": "^1.1.1", "ob1": "0.81.1", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-1i8ROpNNiga43F0ZixAXoFE/SS3RqcRDCCslpynb+ytym0VI7pkTH1woAN2HI9pczYtPrp3Nq0AjRpsuY35ieA=="], + "metro-source-map": ["metro-source-map@0.81.5", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@babel/traverse--for-generate-function-map": "npm:@babel/traverse@^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-symbolicate": "0.81.5", "nullthrows": "^1.1.1", "ob1": "0.81.5", "source-map": "^0.5.6", "vlq": "^1.0.0" } }, "sha512-Jz+CjvCKLNbJZYJTBeN3Kq9kIJf6b61MoLBdaOQZJ5Ajhw6Pf95Nn21XwA8BwfUYgajsi6IXsp/dTZsYJbN00Q=="], - "metro-symbolicate": ["metro-symbolicate@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.81.1", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-Lgk0qjEigtFtsM7C0miXITbcV47E1ZYIfB+m/hCraihiwRWkNUQEPCWvqZmwXKSwVE5mXA0EzQtghAvQSjZDxw=="], + "metro-symbolicate": ["metro-symbolicate@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6", "invariant": "^2.2.4", "metro-source-map": "0.81.5", "nullthrows": "^1.1.1", "source-map": "^0.5.6", "vlq": "^1.0.0" }, "bin": { "metro-symbolicate": "src/index.js" } }, "sha512-X3HV3n3D6FuTE11UWFICqHbFMdTavfO48nXsSpnNGFkUZBexffu0Xd+fYKp+DJLNaQr3S+lAs8q9CgtDTlRRuA=="], - "metro-transform-plugins": ["metro-transform-plugins@0.81.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-7L1lI44/CyjIoBaORhY9fVkoNe8hrzgxjSCQ/lQlcfrV31cZb7u0RGOQrKmUX7Bw4FpejrB70ArQ7Mse9mk7+Q=="], + "metro-transform-plugins": ["metro-transform-plugins@0.81.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/template": "^7.25.0", "@babel/traverse": "^7.25.3", "flow-enums-runtime": "^0.0.6", "nullthrows": "^1.1.1" } }, "sha512-MmHhVx/1dJC94FN7m3oHgv5uOjKH8EX8pBeu1pnPMxbJrx6ZuIejO0k84zTSaQTZ8RxX1wqwzWBpXAWPjEX8mA=="], - "metro-transform-worker": ["metro-transform-worker@0.81.1", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.81.1", "metro-babel-transformer": "0.81.1", "metro-cache": "0.81.1", "metro-cache-key": "0.81.1", "metro-minify-terser": "0.81.1", "metro-source-map": "0.81.1", "metro-transform-plugins": "0.81.1", "nullthrows": "^1.1.1" } }, "sha512-M+2hVT3rEy5K7PBmGDgQNq3Zx53TjScOcO/CieyLnCRFtBGWZiSJ2+bLAXXOKyKa/y3bI3i0owxtyxuPGDwbZg=="], + "metro-transform-worker": ["metro-transform-worker@0.81.5", "", { "dependencies": { "@babel/core": "^7.25.2", "@babel/generator": "^7.25.0", "@babel/parser": "^7.25.3", "@babel/types": "^7.25.2", "flow-enums-runtime": "^0.0.6", "metro": "0.81.5", "metro-babel-transformer": "0.81.5", "metro-cache": "0.81.5", "metro-cache-key": "0.81.5", "metro-minify-terser": "0.81.5", "metro-source-map": "0.81.5", "metro-transform-plugins": "0.81.5", "nullthrows": "^1.1.1" } }, "sha512-lUFyWVHa7lZFRSLJEv+m4jH8WrR5gU7VIjUlg4XmxQfV8ngY4V10ARKynLhMYPeQGl7Qvf+Ayg0eCZ272YZ4Mg=="], "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], @@ -1676,7 +1679,7 @@ "nullthrows": ["nullthrows@1.1.1", "", {}, "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw=="], - "ob1": ["ob1@0.81.1", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-1PEbvI+AFvOcgdNcO79FtDI1TUO8S3lhiKOyAiyWQF3sFDDKS+aw2/BZvGlArFnSmqckwOOB9chQuIX0/OahoQ=="], + "ob1": ["ob1@0.81.5", "", { "dependencies": { "flow-enums-runtime": "^0.0.6" } }, "sha512-iNpbeXPLmaiT9I5g16gFFFjsF3sGxLpYG2EGP3dfFB4z+l9X60mp/yRzStHhMtuNt8qmf7Ww80nOPQHngHhnIQ=="], "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], @@ -1848,7 +1851,7 @@ "react-is": ["react-is@19.0.0", "", {}, "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g=="], - "react-native": ["react-native-tvos@0.77.0-0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native-tvos/virtualized-lists": "0.77.0-0", "@react-native/assets-registry": "0.77.0", "@react-native/codegen": "0.77.0", "@react-native/community-cli-plugin": "0.77.0", "@react-native/gradle-plugin": "0.77.0", "@react-native/js-polyfills": "0.77.0", "@react-native/normalize-colors": "0.77.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", "chalk": "^4.0.0", "commander": "^12.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "jsc-android": "^250231.0.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.81.0", "metro-source-map": "^0.81.0", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.0.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^18.2.6", "react": "^18.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-edIOqGrPadpXHmt5R/LuhekHHLx/0DyrfY5A9odS2AlS+03S0ada7H5oDvusOUVcyq1vc3isrwZpUSQzudoR1g=="], + "react-native": ["react-native-tvos@0.77.2-0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native-tvos/virtualized-lists": "0.77.2-0", "@react-native/assets-registry": "0.77.2", "@react-native/codegen": "0.77.2", "@react-native/community-cli-plugin": "0.77.2", "@react-native/gradle-plugin": "0.77.2", "@react-native/js-polyfills": "0.77.2", "@react-native/normalize-colors": "0.77.2", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", "chalk": "^4.0.0", "commander": "^12.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "jsc-android": "^250231.0.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.81.3", "metro-source-map": "^0.81.3", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.0.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^18.2.6", "react": "^18.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-Ys0tka4VRxClE8oGV4itR0CaeQwtI7jQ51uO7DedmUpt3m8I5uUUFQANgH8IhdEeTtvyPFbnCUffbpcFm59jKg=="], "react-native-awesome-slider": ["react-native-awesome-slider@2.9.0", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.0.0", "react-native-reanimated": ">=3.0.0" } }, "sha512-sc5qgX4YtM6IxjtosjgQLdsal120MvU+YWs0F2MdgQWijps22AXLDCUoBnZZ8vxVhVyJ2WnnIPrmtVBvVJjSuQ=="], @@ -1900,8 +1903,6 @@ "react-native-tab-view": ["react-native-tab-view@4.0.5", "", { "dependencies": { "use-latest-callback": "^0.2.1" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0" } }, "sha512-Xn3TpYo4yvKRC/f4+cOcvsXlitdnSaYkacshckrEI3JiDmFKNFIRVNxtZFggm4MwbJafq2RzuzR6xrgKoxgkTw=="], - "react-native-tvos": ["react-native-tvos@0.77.0-0", "", { "dependencies": { "@jest/create-cache-key-function": "^29.6.3", "@react-native-tvos/virtualized-lists": "0.77.0-0", "@react-native/assets-registry": "0.77.0", "@react-native/codegen": "0.77.0", "@react-native/community-cli-plugin": "0.77.0", "@react-native/gradle-plugin": "0.77.0", "@react-native/js-polyfills": "0.77.0", "@react-native/normalize-colors": "0.77.0", "abort-controller": "^3.0.0", "anser": "^1.4.9", "ansi-regex": "^5.0.0", "babel-jest": "^29.7.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "base64-js": "^1.5.1", "chalk": "^4.0.0", "commander": "^12.0.0", "event-target-shim": "^5.0.1", "flow-enums-runtime": "^0.0.6", "glob": "^7.1.1", "invariant": "^2.2.4", "jest-environment-node": "^29.6.3", "jsc-android": "^250231.0.0", "memoize-one": "^5.0.0", "metro-runtime": "^0.81.0", "metro-source-map": "^0.81.0", "nullthrows": "^1.1.1", "pretty-format": "^29.7.0", "promise": "^8.3.0", "react-devtools-core": "^6.0.1", "react-refresh": "^0.14.0", "regenerator-runtime": "^0.13.2", "scheduler": "0.24.0-canary-efb381bbf-20230505", "semver": "^7.1.3", "stacktrace-parser": "^0.1.10", "whatwg-fetch": "^3.0.0", "ws": "^6.2.3", "yargs": "^17.6.2" }, "peerDependencies": { "@types/react": "^18.2.6", "react": "^18.2.0" }, "optionalPeers": ["@types/react"], "bin": { "react-native": "cli.js" } }, "sha512-edIOqGrPadpXHmt5R/LuhekHHLx/0DyrfY5A9odS2AlS+03S0ada7H5oDvusOUVcyq1vc3isrwZpUSQzudoR1g=="], - "react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="], "react-native-uitextview": ["react-native-uitextview@1.4.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-itm/frzkn/ma3+lwmKn2CkBOXPNo4bL8iVwQwjlzix5gVO59T2+axdfoj/Wi+Ra6F76KzNKxSah+7Y8dYmCHbQ=="], @@ -2422,7 +2423,7 @@ "@react-native/codegen/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware": ["@react-native/dev-middleware@0.77.0", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.77.0", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^2.2.0", "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", "serve-static": "^1.16.2", "ws": "^6.2.3" } }, "sha512-DAlEYujm43O+Dq98KP2XfLSX5c/TEGtt+JBDEIOQewk374uYY52HzRb1+Gj6tNaEj/b33no4GibtdxbO5zmPhg=="], + "@react-native/community-cli-plugin/@react-native/dev-middleware": ["@react-native/dev-middleware@0.77.2", "", { "dependencies": { "@isaacs/ttlcache": "^1.4.1", "@react-native/debugger-frontend": "0.77.2", "chrome-launcher": "^0.15.2", "chromium-edge-launcher": "^0.2.0", "connect": "^3.6.5", "debug": "^2.2.0", "invariant": "^2.2.4", "nullthrows": "^1.1.1", "open": "^7.0.3", "selfsigned": "^2.4.1", "serve-static": "^1.16.2", "ws": "^6.2.3" } }, "sha512-LBK0kY4XxE4vHVHJ3TwBGXmjl2ad9dsbbwnVgXwYNL/mkkWb2MHlmgHj6xlCMe1gtLtem2TpEF17TKg50ykPJw=="], "@react-native/community-cli-plugin/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], @@ -2432,7 +2433,7 @@ "@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], - "@react-native/metro-babel-transformer/@react-native/babel-preset": ["@react-native/babel-preset@0.77.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-arrow-functions": "^7.24.7", "@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-computed-properties": "^7.24.7", "@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-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@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-numeric-separator": "^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.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-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.77.0", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-Z4yxE66OvPyQ/iAlaETI1ptRLcDm7Tk6ZLqtCPuUX3AMg+JNgIA86979T4RSk486/JrBUBH5WZe2xjj7eEHXsA=="], + "@react-native/metro-babel-transformer/@react-native/babel-preset": ["@react-native/babel-preset@0.77.2", "", { "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-arrow-functions": "^7.24.7", "@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-computed-properties": "^7.24.7", "@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-function-name": "^7.25.1", "@babel/plugin-transform-literals": "^7.25.2", "@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-numeric-separator": "^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.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-shorthand-properties": "^7.24.7", "@babel/plugin-transform-spread": "^7.24.7", "@babel/plugin-transform-sticky-regex": "^7.24.7", "@babel/plugin-transform-typescript": "^7.25.2", "@babel/plugin-transform-unicode-regex": "^7.24.7", "@babel/template": "^7.25.0", "@react-native/babel-plugin-codegen": "0.77.2", "babel-plugin-syntax-hermes-parser": "0.25.1", "babel-plugin-transform-flow-enums": "^0.0.2", "react-refresh": "^0.14.0" } }, "sha512-If6X4I0z6W5aVzqZS4JOrN7sh08w1QzEL8Q66i3g0wI8K8ZK+V+/ARlEmboy14VtcOYlmmjXEqSCv+Z2o9cuKg=="], "@react-navigation/core/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="], @@ -2590,7 +2591,7 @@ "react-dom/scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], - "react-native/@react-native/normalize-colors": ["@react-native/normalize-colors@0.77.0", "", {}, "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew=="], + "react-native/@react-native/normalize-colors": ["@react-native/normalize-colors@0.77.2", "", {}, "sha512-knKStQKX4KM8GkieeayotcSTO7I7PIZxwI71nhK/zBeRPqhDTJMNJQh5TnZJ63fO1Y+EZclWkRIKEj+aFRsssw=="], "react-native/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], @@ -2600,16 +2601,6 @@ "react-native/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], - "react-native-tvos/@react-native/normalize-colors": ["@react-native/normalize-colors@0.77.0", "", {}, "sha512-qjmxW3xRZe4T0ZBEaXZNHtuUbRgyfybWijf1yUuQwjBt24tSapmIslwhCjpKidA0p93ssPcepquhY0ykH25mew=="], - - "react-native-tvos/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="], - - "react-native-tvos/glob": ["glob@7.2.3", "", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], - - "react-native-tvos/scheduler": ["scheduler@0.24.0-canary-efb381bbf-20230505", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA=="], - - "react-native-tvos/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], - "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=="], @@ -2756,7 +2747,7 @@ "@react-native/codegen/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "@react-native/community-cli-plugin/@react-native/dev-middleware/@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.77.0", "", {}, "sha512-glOvSEjCbVXw+KtfiOAmrq21FuLE1VsmBsyT7qud4KWbXP43aUEhzn70mWyFuiIdxnzVPKe2u8iWTQTdJksR1w=="], + "@react-native/community-cli-plugin/@react-native/dev-middleware/@react-native/debugger-frontend": ["@react-native/debugger-frontend@0.77.2", "", {}, "sha512-MRLjQLJr9C0M/TggoycEgYR7lUEZph4cg5PhUwBoNyRquV7lGHqMKNkfMBYBT09cuwKn9O+cFvQOmMNVqsPLxw=="], "@react-native/community-cli-plugin/@react-native/dev-middleware/open": ["open@7.4.2", "", { "dependencies": { "is-docker": "^2.0.0", "is-wsl": "^2.1.1" } }, "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q=="], @@ -2764,7 +2755,7 @@ "@react-native/dev-middleware/debug/ms": ["ms@2.0.0", "", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], - "@react-native/metro-babel-transformer/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.77.0", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.77.0" } }, "sha512-5TYPn1k+jdDOZJU4EVb1kZ0p9TCVICXK3uplRev5Gul57oWesAaiWGZOzfRS3lonWeuR4ij8v8PFfIHOaq0vmA=="], + "@react-native/metro-babel-transformer/@react-native/babel-preset/@react-native/babel-plugin-codegen": ["@react-native/babel-plugin-codegen@0.77.2", "", { "dependencies": { "@babel/traverse": "^7.25.3", "@react-native/codegen": "0.77.2" } }, "sha512-2PShbsfsa4NZS+Zt0y2tl1AoWza5podKFmPE5qcYjJoN915VoH3BRkiTVlSpYNKmdvs31o1aQuXAMQDTh7DZ/g=="], "ansi-fragments/slice-ansi/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], @@ -2848,8 +2839,6 @@ "pkg-dir/find-up/locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], - "react-native-tvos/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], - "react-native/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "readable-web-to-node-stream/readable-stream/buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], @@ -2942,8 +2931,6 @@ "pkg-dir/find-up/locate-path/path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], - "react-native-tvos/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], - "react-native/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], @@ -2992,4 +2979,4 @@ "logkitty/yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 7c9ad051..6261c236 100644 --- a/package.json +++ b/package.json @@ -6,12 +6,13 @@ "submodule-reload": "git submodule update --init --remote --recursive", "clean": "echo y | expo prebuild --clean", "start": "bun run submodule-reload && expo start", - "ios": "EXPO_TV=0 expo run:ios", - "ios:tv": "EXPO_TV=1 expo run:ios", - "android": "EXPO_TV=0 expo run:android", - "android:tv": "EXPO_TV=1 expo run:android", - "prebuild": "EXPO_TV=0 bun run clean", - "prebuild:tv": "EXPO_TV=1 bun run clean", + "ios": "cross-env EXPO_TV=0 expo run:ios", + "ios:tv": "cross-env EXPO_TV=1 expo run:ios", + "android": "cross-env EXPO_TV=0 expo run:android", + "android:tv": "cross-env EXPO_TV=1 expo run:android", + "prebuild": "cross-env EXPO_TV=0 bun run clean", + "prebuild:tv": "cross-env EXPO_TV=1 bun run clean", + "build:android:local": "cd android && cross-env NODE_ENV=production ./gradlew assembleRelease", "prepare": "husky", "check": "biome check .", "lint": "biome check --write --unsafe" @@ -120,6 +121,7 @@ "@types/react-native-vector-icons": "^6.4.18", "@types/react-test-renderer": "^19.0.0", "@types/uuid": "^10.0.0", + "cross-env": "^7.0.3", "husky": "^9.1.7", "lint-staged": "^15.5.0", "postinstall-postinstall": "^2.1.0", diff --git a/renovate.json b/renovate.json new file mode 100644 index 00000000..28c19585 --- /dev/null +++ b/renovate.json @@ -0,0 +1,48 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "description": "Default Renovate preset for Streamyfin repositories", + "extends": [ + "config:base", + ":disableDependencyDashboard", + ":enableVulnerabilityAlertsWithLabel(security)", + ":semanticCommitsDisabled", + ":timezone(Etc/UTC)", + "docker:enableMajor", + "group:testNonMajor", + "group:monorepos", + "helpers:pinGitHubActionDigests" + ], + "addLabels": ["dependencies"], + "rebaseWhen": "conflicted", + "ignorePaths": ["**/node_modules/**", "**/bower_components/**"], + "lockFileMaintenance": { + "enabled": true, + "groupName": "lockfiles", + "schedule": ["every month"] + }, + "packageRules": [ + { + "description": "Add 'ci' and 'github-actions' labels to GitHub Action update PRs", + "matchManagers": ["github-actions"], + "addLabels": ["ci", "github-actions"] + }, + { + "description": "Group minor and patch GitHub Action updates into a single PR", + "matchManagers": ["github-actions"], + "groupName": "CI dependencies", + "groupSlug": "ci-deps", + "matchUpdateTypes": ["minor", "patch"] + }, + { + "description": "Group lock file maintenance updates", + "matchUpdateTypes": ["lockFileMaintenance"], + "groupName": "lockfiles", + "dependencyDashboardApproval": true + }, + { + "description": "Add specific labels for Expo and React Native dependencies", + "matchPackagePatterns": ["expo", "react-native"], + "addLabels": ["expo", "react-native"] + } + ] +}