diff --git a/.gitattributes b/.gitattributes index 56dea9663..4d651aeb4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,28 @@ -.modules/vlc-player/Frameworks/*.xcframework filter=lfs diff=lfs merge=lfs -text +# Normalise line endings to LF for everyone. Files are stored as LF in git and +# checked out as LF on every OS, so Windows clones stop producing CRLF churn +# (no more "LF will be replaced by CRLF" warnings) regardless of core.autocrlf. +* text=auto eol=lf + +# Windows-only scripts must stay CRLF +*.bat text eol=crlf +*.cmd text eol=crlf + +# Binary assets — never touched / never normalised +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.webp binary +*.ico binary +*.icns binary +*.ttf binary +*.otf binary +*.woff binary +*.woff2 binary +*.mp3 binary +*.mp4 binary +*.mov binary +*.pdf binary +*.keystore binary +*.jks binary +*.p12 binary diff --git a/.github/ISSUE_TEMPLATE/issue_report.yml b/.github/ISSUE_TEMPLATE/issue_report.yml index ccdb0d0ed..af86644dd 100644 --- a/.github/ISSUE_TEMPLATE/issue_report.yml +++ b/.github/ISSUE_TEMPLATE/issue_report.yml @@ -1,5 +1,5 @@ name: "🐛 Bug Report" -description: Create a report to help us improve +description: Create a report to help Streamyfin improve title: "[Bug]: " labels: - "🐛 bug" @@ -36,7 +36,7 @@ body: attributes: label: What happened? description: A clear and concise description of what the bug is. - placeholder: Describe what happened in detail. + placeholder: Describe what happened in detail, the more precise the better. validations: required: true @@ -67,7 +67,7 @@ body: attributes: label: Which device and operating system are you using? description: Please provide your device model and OS version - placeholder: e.g. iPhone 15 Pro, iOS 18.1.1 or Samsung Galaxy S24, Android 14 + placeholder: e.g. iPhone 17 Pro / iOS 26.5.1, Samsung Galaxy S25 / Android 16, Apple TV / tvOS 26.5 validations: required: true @@ -75,11 +75,11 @@ body: id: version attributes: label: Streamyfin Version - description: What version of Streamyfin are you running? + description: What version of Streamyfin are you using? options: - - 0.47.1 - - 0.30.2 - - older + - 0.54.1 + - 0.51.0 + - Older - TestFlight/Development build validations: required: true @@ -90,9 +90,9 @@ body: label: Jellyfin Server Information description: Please provide details about your Jellyfin server placeholder: | - - Jellyfin Server Version: e.g. 10.10.7 - - Server OS: e.g. Ubuntu 22.04, Windows 11, Docker - - Connection: e.g. Local network, Remote via domain, VPN + - Jellyfin Server Version: e.g. 10.11.10 + - Server OS: e.g. Ubuntu 26.04, Windows 11, Docker, Proxmox + - Connection: e.g. Local network, remote via domain, VPN - type: textarea id: screenshots @@ -104,7 +104,7 @@ body: id: logs attributes: label: Relevant logs (if available) - description: If you have access to app logs or crash reports, please include them here. **Remember to remove any personal information like server URLs or usernames.** + description: If you have access to app logs or crash reports, please include them here. **Remember to remove any personal information like server URL, API keys or usernames.** render: shell - type: textarea diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index c6effebf1..feb9a00fe 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -1,51 +1,51 @@ -name: 🌐 Translation Sync - -on: - push: - branches: [develop] - paths: - - "translations/**" - - "crowdin.yml" - - "i18n.ts" - - ".github/workflows/crowdin.yml" - # Run weekly to pull new translations - schedule: - - cron: "0 2 * * 1" # Every Monday at 2 AM UTC - workflow_dispatch: - -permissions: - contents: write - pull-requests: write - -jobs: - sync-translations: - runs-on: ubuntu-latest - - steps: - - name: 📥 Checkout Repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - fetch-depth: 0 - - - name: 🌐 Sync Translations with Crowdin - uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2 - with: - upload_sources: true - upload_translations: true - download_translations: true - localization_branch_name: I10n_crowdin_translations - create_pull_request: true - pull_request_title: "feat: New Crowdin Translations" - pull_request_body: "New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)" - pull_request_base_branch_name: "develop" - pull_request_labels: "🌐 translation" - # Quality control options - skip_untranslated_strings: false - skip_untranslated_files: false - export_only_approved: false - # Commit customization - commit_message: "feat(i18n): update translations from Crowdin" - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} - CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} +name: 🌐 Translation Sync + +on: + push: + branches: [develop] + paths: + - "translations/**" + - "crowdin.yml" + - "i18n.ts" + - ".github/workflows/crowdin.yml" + # Run weekly to pull new translations + schedule: + - cron: "0 2 * * 1" # Every Monday at 2 AM UTC + workflow_dispatch: + +permissions: + contents: write + pull-requests: write + +jobs: + sync-translations: + runs-on: ubuntu-latest + + steps: + - name: 📥 Checkout Repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - name: 🌐 Sync Translations with Crowdin + uses: crowdin/github-action@8868a33591d21088edfc398968173a3b98d51706 # v2.16.2 + with: + upload_sources: true + upload_translations: true + download_translations: true + localization_branch_name: I10n_crowdin_translations + create_pull_request: true + pull_request_title: "feat: New Crowdin Translations" + pull_request_body: "New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)" + pull_request_base_branch_name: "develop" + pull_request_labels: "🌐 translation" + # Quality control options + skip_untranslated_strings: false + skip_untranslated_files: false + export_only_approved: false + # Commit customization + commit_message: "feat(i18n): update translations from Crowdin" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} + CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} diff --git a/.github/workflows/detect-duplicate.yml b/.github/workflows/detect-duplicate.yml new file mode 100644 index 000000000..09aa23565 --- /dev/null +++ b/.github/workflows/detect-duplicate.yml @@ -0,0 +1,38 @@ +name: 🔁 Detect Duplicate Issues + +on: + issues: + types: [opened] + +permissions: + contents: read + +concurrency: + group: detect-duplicate-${{ github.event.issue.number }} + cancel-in-progress: true + +jobs: + detect: + name: 🔍 Find similar issues + if: github.actor != 'github-actions[bot]' + runs-on: ubuntu-24.04 + permissions: + issues: write + contents: read + steps: + - name: 📥 Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: 🍞 Setup Bun + uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 + with: + bun-version: latest + + - name: 🔍 Detect duplicate issues + run: bun scripts/detect-duplicate-issue.mjs + env: + GH_TOKEN: ${{ github.token }} + GITHUB_REPOSITORY: ${{ github.repository }} + ISSUE_NUMBER: ${{ github.event.issue.number }} + ISSUE_TITLE: ${{ github.event.issue.title }} + ISSUE_BODY: ${{ github.event.issue.body }} diff --git a/.gitignore b/.gitignore index ef41769f9..d46c8a6f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ # Dependencies and Package Managers node_modules/ -bun.lock bun.lockb package-lock.json @@ -21,10 +20,8 @@ web-build/ # Gradle caches (top-level + per-module native projects) **/.gradle/ -# Module-specific Builds -modules/mpv-player/android/build -modules/player/android -modules/hls-downloader/android/build +# Native module build outputs (any module) +modules/*/android/build/ # Generated Applications Streamyfin.app @@ -69,10 +66,6 @@ certs/ # Version and Backup Files /version-backup-* -/modules/sf-player/android/build -/modules/music-controls/android/build -modules/background-downloader/android/build/* -/modules/mpv-player/android/build # ios:unsigned-build Artifacts build/ diff --git a/app/(auth)/(tabs)/(favorites)/see-all.tsx b/app/(auth)/(tabs)/(favorites)/see-all.tsx index e3b0198ab..c885afdc2 100644 --- a/app/(auth)/(tabs)/(favorites)/see-all.tsx +++ b/app/(auth)/(tabs)/(favorites)/see-all.tsx @@ -161,9 +161,7 @@ export default function FavoritesSeeAllScreen() { /> {!itemType ? ( - - {t("favorites.noData", { defaultValue: "No items found." })} - + {t("favorites.noData")} ) : isLoading ? ( @@ -194,7 +192,7 @@ export default function FavoritesSeeAllScreen() { ListEmptyComponent={ - {t("home.no_items", { defaultValue: "No items" })} + {t("home.no_items")} } diff --git a/app/(auth)/(tabs)/(home)/downloads/index.tsx b/app/(auth)/(tabs)/(home)/downloads/index.tsx index da4a8272c..68340e6bf 100644 --- a/app/(auth)/(tabs)/(home)/downloads/index.tsx +++ b/app/(auth)/(tabs)/(home)/downloads/index.tsx @@ -137,12 +137,12 @@ export default function DownloadsPage() { deleteFileByType("Episode") .then(() => toast.success( - t("home.downloads.toasts.deleted_all_tvseries_successfully"), + t("home.downloads.toasts.deleted_all_series_successfully"), ), ) .catch((reason) => { writeToLog("ERROR", reason); - toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries")); + toast.error(t("home.downloads.toasts.failed_to_delete_all_series")); }); const deleteOtherMedia = () => Promise.all( @@ -207,7 +207,7 @@ export default function DownloadsPage() { - {t("home.downloads.tvseries")} + {t("home.downloads.series")} @@ -288,7 +288,7 @@ export default function DownloadsPage() { {t("home.downloads.delete_all_movies_button")} {otherMedia.length > 0 && (