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
-> 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 @@
+
+
+
+
+
+
+