diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..7851727a --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: edde746 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 00000000..c274feea --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,101 @@ +name: Bug Report +description: Report a bug or unexpected behavior +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to report a bug! Please fill out the information below to help us diagnose and fix the issue. + + - type: textarea + id: description + attributes: + label: Bug Description + description: A clear and concise description of what the bug is. + placeholder: What went wrong? + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to Reproduce + description: Steps to reproduce the behavior + placeholder: | + 1. Go to '...' + 2. Tap on '...' + 3. Scroll down to '...' + 4. See error + validations: + required: true + + - type: textarea + id: expected + attributes: + label: Expected Behavior + description: What did you expect to happen? + placeholder: Describe what should have happened + validations: + required: true + + - type: textarea + id: actual + attributes: + label: Actual Behavior + description: What actually happened? + placeholder: Describe what actually happened + validations: + required: true + + - type: input + id: plezy-version + attributes: + label: Plezy Version + description: Check the app settings for the version number and paste it here + placeholder: e.g., 1.7.0 + validations: + required: true + + - type: dropdown + id: platform + attributes: + label: Platform + description: Which platform(s) are affected? + multiple: true + options: + - iOS + - Android + - Windows + - macOS + - Android TV + - Linux + validations: + required: true + + - type: input + id: device + attributes: + label: Device Information + description: What device are you using? + placeholder: e.g., iPhone 14 Pro, Pixel 7, Chrome on macOS + + - type: textarea + id: logs + attributes: + label: Logs and Stack Traces + description: Please paste any relevant logs or stack traces + render: shell + placeholder: Paste logs here + + - type: textarea + id: screenshots + attributes: + label: Screenshots + description: If applicable, add screenshots to help explain your problem + placeholder: Drag and drop screenshots here + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context about the problem here diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..0c6e9893 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Questions and Discussions + url: https://github.com/edde746/plezy/discussions + about: Ask questions and discuss ideas with the community diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 00000000..6931d7dd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,65 @@ +name: Feature Request +description: Suggest a new feature or enhancement +labels: ["enhancement"] +body: + - type: markdown + attributes: + value: | + Thanks for suggesting a new feature! Please provide as much detail as possible. + + - type: textarea + id: problem + attributes: + label: Problem Statement + description: Is your feature request related to a problem? Please describe. + placeholder: I'm frustrated when... / It would be helpful if... + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Proposed Solution + description: Describe the solution you'd like to see + placeholder: What feature would solve this problem? + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Alternatives Considered + description: Have you considered any alternative solutions or features? + placeholder: Describe alternatives you've considered + + - type: textarea + id: use-case + attributes: + label: Use Case + description: Describe how you would use this feature + placeholder: | + 1. As a user, I would... + 2. This would help me... + 3. The benefit would be... + + - type: dropdown + id: platform + attributes: + label: Target Platform + description: Which platform(s) should this feature target? + multiple: true + options: + - Android + - iOS + - Web + - macOS + - Windows + - Linux + - All platforms + + - type: textarea + id: additional + attributes: + label: Additional Context + description: Add any other context, mockups, or screenshots about the feature request + placeholder: Add mockups, links to similar features, or any other helpful context diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e035d5ff --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,161 @@ +name: CI - Sanity Checks + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + analyze: + name: Code Analysis + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" + cache: true + + - name: Cache Pub dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + key: ${{ runner.os }}-pub-v2-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-pub-v2- + + - name: Install dependencies + run: | + + flutter pub get + + - name: Verify formatting + run: | + # Find all Dart files excluding generated files + find lib $([ -d test ] && echo test) -name "*.dart" ! -name "*.g.dart" ! -name "*.freezed.dart" -type f 2>/dev/null | while IFS= read -r file; do + files_found=true + break + done + if [ "$files_found" != "true" ]; then + echo "No Dart files found to format" + exit 0 + fi + find lib $([ -d test ] && echo test) -name "*.dart" ! -name "*.g.dart" ! -name "*.freezed.dart" -type f 2>/dev/null -print0 | xargs -0 dart format --output=none --set-exit-if-changed + - name: Analyze code + run: | + # Run flutter analyze + # Fails on errors or warnings only (info messages are allowed) + flutter analyze 2>&1 | tee analyze_output.txt || true + + # Check output for errors or warnings + if grep -q "error •" analyze_output.txt; then + echo "❌ Analysis failed with errors" + exit 1 + elif grep -q "warning •" analyze_output.txt; then + echo "⚠️ Analysis completed with warnings" + exit 1 + else + echo "✅ Analysis passed!" + exit 0 + fi + + - name: Check for unused code + run: | + echo "🔍 Checking for unused code..." + dart run dart_code_linter:metrics check-unused-code lib 2>&1 | tee unused_code.txt + if grep -qi "no unused code found" unused_code.txt; then + echo "✅ No unused code found" + else + echo "❌ Found unused code:" + cat unused_code.txt + exit 1 + fi + + - name: Check for unused files + run: | + echo "🔍 Checking for unused files..." + dart run dart_code_linter:metrics check-unused-files lib 2>&1 | tee unused_files.txt + if grep -qi "no unused files found" unused_files.txt; then + echo "✅ No unused files found" + else + echo "❌ Found unused files:" + cat unused_files.txt + exit 1 + fi + + test: + name: Unit Tests + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" + cache: true + + - name: Cache Pub dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + key: ${{ runner.os }}-pub-v2-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-pub-v2- + + - name: Install dependencies + run: | + flutter clean + flutter pub get + + - name: Run tests + run: | + if [ -d "test" ] && [ "$(find test -name '*_test.dart' | wc -l)" -gt 0 ]; then + flutter test + else + echo "No tests found, skipping test execution" + fi + + dependency-check: + name: Dependency Validation + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: "stable" + cache: true + + - name: Cache Pub dependencies + uses: actions/cache@v4 + with: + path: | + ~/.pub-cache + key: ${{ runner.os }}-pub-v2-${{ hashFiles('**/pubspec.lock') }} + restore-keys: | + ${{ runner.os }}-pub-v2- + + - name: Verify dependencies + run: | + flutter clean + flutter pub get + flutter pub outdated diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..6e576967 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,82 @@ +name: Release + +on: + workflow_dispatch: + inputs: + version: + description: 'Version number (e.g., 1.9.0)' + required: true + type: string + +permissions: + contents: write + actions: write + +jobs: + release: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Validate version format + run: | + if ! echo "${{ inputs.version }}" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+$'; then + echo "Error: Version must be in semantic versioning format (e.g., 1.9.0)" + exit 1 + fi + + - name: Extract current build number + id: get_build + run: | + # Extract current build number from pubspec.yaml + CURRENT_VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //') + CURRENT_BUILD=$(echo "$CURRENT_VERSION" | cut -d'+' -f2) + NEW_BUILD=$((CURRENT_BUILD + 1)) + + echo "current_build=$CURRENT_BUILD" >> $GITHUB_OUTPUT + echo "new_build=$NEW_BUILD" >> $GITHUB_OUTPUT + echo "Current build: $CURRENT_BUILD" + echo "New build: $NEW_BUILD" + + - name: Update pubspec.yaml + run: | + NEW_VERSION="${{ inputs.version }}+${{ steps.get_build.outputs.new_build }}" + sed -i "s/^version: .*/version: $NEW_VERSION/" pubspec.yaml + echo "Updated version to: $NEW_VERSION" + cat pubspec.yaml | grep '^version:' + + - name: Configure Git + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - name: Commit version bump + run: | + git add pubspec.yaml + git commit -m "chore: bump version to ${{ inputs.version }}" + + - name: Create Git tag + run: | + git tag "${{ inputs.version }}" + echo "Created tag: ${{ inputs.version }}" + + - name: Push changes and tag + run: | + git push origin main + git push origin --tags + + - name: Trigger build workflow + run: | + curl -L \ + -X POST \ + -H "Accept: application/vnd.github+json" \ + -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/${{ github.repository }}/actions/workflows/build.yml/dispatches \ + -d '{"ref":"main"}' + + echo "Build workflow triggered successfully" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1742ed9d..9ce9e5e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,29 @@ ## Development - Follow Dart/Flutter conventions -- Run `flutter analyze` before submitting +- Run `dart format .` to format your code (note: generated files like `*.g.dart` are excluded from CI checks) +- Run `flutter analyze` before submitting to check for issues +- Run `flutter test` if tests are available - Test your changes thoroughly +### Code Quality Checks + +The project includes automated CI checks that run on all pull requests: + +1. **Code Formatting**: Ensures code follows Dart formatting standards + - Run locally: `dart format .` to format all files + - Note: CI only checks non-generated files (excludes `.g.dart`, `.freezed.dart`) + - Generated files are reformatted automatically by build tools + +2. **Static Analysis**: Checks for code issues and potential bugs + - Run locally: `flutter analyze` + - Note: CI excludes generated files from analysis (configured in `analysis_options.yaml`) + +3. **Tests**: Runs unit and widget tests (when available) + - Run locally: `flutter test` + +All these checks must pass before your changes can be merged. + ## Internationalization (i18n) This project uses `slang` for internationalization with JSON files. diff --git a/README.md b/README.md index e2092494..654c1dcb 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,6 @@ Plezy is a modern Plex media client that provides a seamless streaming experienc Download on the App Store Get it on Google Play -> Google Play version is in closed testing ([required by Google](https://support.google.com/googleplay/android-developer/answer/14151465#overview)). Join the [Google Group](https://groups.google.com/g/plezy-testers-2) to get access. - ### Desktop - [Windows (x64)](https://github.com/edde746/plezy/releases/latest/download/plezy-windows-installer.exe) - [macOS (Universal)](https://github.com/edde746/plezy/releases/latest/download/plezy-macos.zip) @@ -41,6 +39,7 @@ Plezy is a modern Plex media client that provides a seamless streaming experienc ### 🎬 Video Playback - Wide codec support including HEVC, AV1, VP9, and more +- HDR and Dolby Vision support (iOS, macOS & Windows) - Advanced subtitle rendering with full ASS/SSA support - Audio and subtitle track selection with user profile preferences - Playback progress sync and resume functionality @@ -85,24 +84,10 @@ The project uses code generation for JSON serialization. After modifying model c dart run build_runner build --delete-conflicting-outputs ``` -## Building for Production - -### Android -```bash -flutter build apk --release -# or -flutter build appbundle --release -``` - -### Desktop -```bash -flutter build macos --release -flutter build windows --release -flutter build linux --release -``` - ## Acknowledgments - Built with [Flutter](https://flutter.dev) -- Media playback powered by [MediaKit](https://github.com/media-kit/media-kit) - Designed for [Plex Media Server](https://www.plex.tv) +- Playback powered by [mpv](https://mpv.io) + - [MPVKit](https://github.com/mpvkit/MPVKit) + - [mpv-android](https://github.com/mpv-android/mpv-android) diff --git a/analysis_options.yaml b/analysis_options.yaml index f9b30346..d6f4d7bf 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +1,12 @@ include: package:flutter_lints/flutter.yaml + +analyzer: + exclude: + - "**/*.g.dart" + - "**/*.freezed.dart" + plugins: + - dart_code_linter + +dart_code_linter: + rules: + - avoid-unused-parameters diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 1f4346cd..52e31986 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -26,7 +26,7 @@ android { applicationId = "com.edde746.plezy" // You can update the following values to match your application needs. // For more information, see: https://flutter.dev/to/review-gradle-config. - minSdk = flutter.minSdkVersion + minSdk = 26 // Required by libmpv-android targetSdk = flutter.targetSdkVersion versionCode = flutter.versionCode versionName = flutter.versionName @@ -62,3 +62,7 @@ android { flutter { source = "../.." } + +dependencies { + implementation("dev.jdtech.mpv:libmpv:0.5.1") +} diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 13b13acc..3c0021f1 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -13,6 +13,11 @@ + + + + + + +