mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-02 09:08:35 +02:00
chore(repo): improve contributor experience
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{dart,json,yaml,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.{kt,kts,swift}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.go]
|
||||
indent_style = tab
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{bat,cmd,ps1}]
|
||||
end_of_line = crlf
|
||||
@@ -1,5 +1,9 @@
|
||||
* text=auto eol=lf
|
||||
|
||||
# Scripts executed on Unix runners must keep LF line endings.
|
||||
*.sh text eol=lf
|
||||
gradlew text eol=lf
|
||||
|
||||
# Windows scripts
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
name: Bug Report
|
||||
description: Report a bug or unexpected behavior
|
||||
description: Report a reproducible bug or unexpected behavior
|
||||
title: "[Bug]: "
|
||||
labels: ["bug"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to report a bug! Please fill out the form below.
|
||||
Thanks for reporting a SpotiFLAC Mobile bug. Please provide enough detail for another person to reproduce it.
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have searched existing issues and this bug hasn't been reported yet
|
||||
- label: I searched existing issues and did not find this bug.
|
||||
required: true
|
||||
- label: I am using the latest version of SpotiFLAC (Stable Version)
|
||||
- label: I can reproduce this on the release channel selected below.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: A clear and concise description of what the bug is
|
||||
placeholder: Describe the bug...
|
||||
label: Description
|
||||
description: What happened, and what did you expect instead?
|
||||
placeholder: Include the visible error and any relevant context.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -32,29 +31,26 @@ body:
|
||||
id: steps
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Steps to reproduce the behavior
|
||||
placeholder: |
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. See error
|
||||
1. Open ...
|
||||
2. Enable ...
|
||||
3. Tap ...
|
||||
4. Observe ...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: expected
|
||||
- type: dropdown
|
||||
id: trigger
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: What did you expect to happen?
|
||||
placeholder: Describe what you expected...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: actual
|
||||
attributes:
|
||||
label: Actual Behavior
|
||||
description: What actually happened?
|
||||
placeholder: Describe what actually happened...
|
||||
label: Area
|
||||
options:
|
||||
- App startup
|
||||
- Search or navigation
|
||||
- Download or verification
|
||||
- Library or metadata
|
||||
- Playback or background service
|
||||
- Audio analysis
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -62,62 +58,73 @@ body:
|
||||
id: version
|
||||
attributes:
|
||||
label: App Version
|
||||
description: Which version of SpotiFLAC are you using? (Check in Settings > About)
|
||||
placeholder: "e.g., v2.2.0"
|
||||
description: Find this in Settings > About.
|
||||
placeholder: "e.g. 4.8.1 (139)"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: platform
|
||||
id: channel
|
||||
attributes:
|
||||
label: Platform
|
||||
description: Which platform are you using?
|
||||
label: Release Channel
|
||||
options:
|
||||
- Android
|
||||
- iOS
|
||||
- Stable
|
||||
- Beta
|
||||
- Local or development build
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: device
|
||||
attributes:
|
||||
label: Device & OS Version
|
||||
description: What device and OS version are you using?
|
||||
placeholder: "e.g., Samsung Galaxy S24, Android 14"
|
||||
label: Device and OS
|
||||
placeholder: "e.g. Samsung Galaxy S24, Android 16"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: download-service
|
||||
id: storage
|
||||
attributes:
|
||||
label: Download Service
|
||||
description: Which download service were you using when the bug occurred?
|
||||
label: Download Storage
|
||||
options:
|
||||
- Tidal
|
||||
- Qobuz
|
||||
- Amazon Music
|
||||
- Deezer (search only)
|
||||
- SAF folder
|
||||
- App-specific folder
|
||||
- Not applicable
|
||||
- Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: worker
|
||||
attributes:
|
||||
label: Download Worker
|
||||
options:
|
||||
- Native worker
|
||||
- Dart worker
|
||||
- Not applicable
|
||||
- Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: provider
|
||||
attributes:
|
||||
label: Extension or Provider
|
||||
description: If relevant, include the extension/provider name and version.
|
||||
placeholder: "Name, version, and selected priority"
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs / Screenshots
|
||||
label: Logs and Media
|
||||
description: |
|
||||
If applicable, add logs or screenshots to help explain your problem.
|
||||
|
||||
**To get logs:**
|
||||
1. Go to Settings > Options > Detailed Logging (turn ON)
|
||||
2. Reproduce the bug
|
||||
3. Go to Settings > Logs
|
||||
4. Tap Share button to export logs
|
||||
placeholder: Paste logs or drag & drop screenshots here...
|
||||
Enable detailed logging, reproduce the problem, then export logs from Settings > Logs. For an Android cold-start crash, attach `adb logcat -b crash -d`. Add screenshots or a short recording when useful. Remove credentials and personal data first.
|
||||
placeholder: Paste logs or drag files here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: additional
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Any other context about the problem
|
||||
placeholder: Add any other context...
|
||||
placeholder: Settings, frequency, regression version, or anything else that may help.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: README
|
||||
url: https://github.com/zarzet/SpotiFLAC-Mobile#readme
|
||||
url: https://github.com/spotiflacapp/SpotiFLAC-Mobile#readme
|
||||
about: Check the README for setup instructions and FAQ
|
||||
- name: Extension Development Guide
|
||||
url: https://spotiflac.zarz.moe/docs
|
||||
about: Documentation for building SpotiFLAC extensions
|
||||
about: Documentation for building SpotiFLAC Mobile extensions
|
||||
|
||||
@@ -1,111 +1,124 @@
|
||||
name: Download Issue
|
||||
description: Report issues with downloading specific tracks or albums
|
||||
description: Report a wrong, missing, failed, or low-quality download
|
||||
title: "[Download]: "
|
||||
labels: ["download-issue"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Having trouble downloading a specific track or album? Please provide details below.
|
||||
Download matching is extension-driven. Include the source item, provider order, and logs so the exact decision path can be inspected.
|
||||
|
||||
- type: checkboxes
|
||||
id: checklist
|
||||
attributes:
|
||||
label: Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have tried downloading with a different service (Tidal/Qobuz/Amazon)
|
||||
- label: I searched existing issues and did not find this problem.
|
||||
required: true
|
||||
- label: I am using the latest version of SpotiFLAC (Stable Version)
|
||||
- label: I updated the affected extension and retried once.
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: issue-type
|
||||
attributes:
|
||||
label: Issue Type
|
||||
description: What kind of download issue are you experiencing?
|
||||
options:
|
||||
- Track not found on service
|
||||
- Track or album not found
|
||||
- Wrong track downloaded
|
||||
- Download fails/errors
|
||||
- Metadata incorrect
|
||||
- Audio quality issue
|
||||
- Download fails or stalls
|
||||
- Metadata or cover is incorrect
|
||||
- Audio format or quality is incorrect
|
||||
- Duplicate or replacement behavior
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: spotify-url
|
||||
id: source-url
|
||||
attributes:
|
||||
label: Spotify URL
|
||||
description: The Spotify URL of the track/album you're trying to download
|
||||
placeholder: "https://open.spotify.com/track/..."
|
||||
validations:
|
||||
required: true
|
||||
label: Source URL
|
||||
description: URL pasted or opened in SpotiFLAC Mobile, if available.
|
||||
placeholder: "https://..."
|
||||
|
||||
- type: input
|
||||
id: track-info
|
||||
attributes:
|
||||
label: Track Info
|
||||
description: Artist name and track title
|
||||
placeholder: "Artist - Track Title"
|
||||
label: Track or Album
|
||||
placeholder: "Artist - Track or album title"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: metadata-source
|
||||
attributes:
|
||||
label: Search or Metadata Extension
|
||||
placeholder: "Extension name and version"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: download-provider
|
||||
attributes:
|
||||
label: Selected Download Extension
|
||||
placeholder: "Extension name and version"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: priority
|
||||
attributes:
|
||||
label: Provider Priority and Requested Quality
|
||||
placeholder: |
|
||||
Provider order: first, second, third
|
||||
Requested quality: best / 24-bit / ...
|
||||
Automatic fallback: on/off
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: download-service
|
||||
id: storage
|
||||
attributes:
|
||||
label: Download Service
|
||||
description: Which service did you try to download from?
|
||||
label: Download Storage
|
||||
options:
|
||||
- Tidal
|
||||
- Qobuz
|
||||
- Amazon Music
|
||||
- All services
|
||||
- SAF folder
|
||||
- App-specific folder
|
||||
- Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: dropdown
|
||||
id: search-service
|
||||
id: worker
|
||||
attributes:
|
||||
label: Search Service
|
||||
description: Which search service are you using?
|
||||
label: Download Worker
|
||||
options:
|
||||
- Spotify
|
||||
- Deezer
|
||||
- Native worker
|
||||
- Dart worker
|
||||
- Not sure
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Description
|
||||
description: Describe the issue in detail
|
||||
placeholder: |
|
||||
What happened? What did you expect?
|
||||
If wrong track was downloaded, what track was downloaded instead?
|
||||
label: What Happened?
|
||||
description: For a wrong match, identify both the expected and downloaded recording.
|
||||
placeholder: Describe the result and the expected result.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
id: environment
|
||||
attributes:
|
||||
label: App Version
|
||||
description: Which version of SpotiFLAC are you using?
|
||||
placeholder: "e.g., v2.2.0"
|
||||
label: App Version, Device, and OS
|
||||
placeholder: "4.8.1 (139), device model, Android/iOS version"
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: screenshots
|
||||
id: logs
|
||||
attributes:
|
||||
label: Screenshots / Logs
|
||||
description: |
|
||||
If applicable, add screenshots or logs.
|
||||
|
||||
**To get logs:**
|
||||
1. Go to Settings > Options > Detailed Logging (turn ON)
|
||||
2. Try downloading the track again
|
||||
3. Go to Settings > Logs
|
||||
4. Tap Share button to export logs
|
||||
placeholder: Drag & drop screenshots or paste logs here...
|
||||
label: Logs and Screenshots
|
||||
description: Enable detailed logging, retry once, and export Settings > Logs. Remove credentials and personal data.
|
||||
placeholder: Paste logs or drag files here.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
@@ -6,7 +6,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for helping improve the SpotiFLAC Extension API!
|
||||
Thanks for helping improve the SpotiFLAC Mobile Extension API!
|
||||
This form is for extension developers who need new features or capabilities that don't exist yet.
|
||||
|
||||
- type: checkboxes
|
||||
@@ -15,7 +15,7 @@ body:
|
||||
label: Checklist
|
||||
description: Please confirm the following before submitting
|
||||
options:
|
||||
- label: I have read the [Extension Development Guide](https://github.com/zarzet/SpotiFLAC-Mobile/blob/main/docs/EXTENSION_DEVELOPMENT.md)
|
||||
- label: I have read the [Extension Development Guide](https://github.com/spotiflacapp/SpotiFLAC-Mobile/blob/main/docs/EXTENSION_DEVELOPMENT.md)
|
||||
required: true
|
||||
- label: I have searched existing issues and this API feature hasn't been requested yet
|
||||
required: true
|
||||
|
||||
@@ -50,7 +50,7 @@ body:
|
||||
options:
|
||||
- UI/UX Improvement
|
||||
- Download Feature
|
||||
- New Service Integration
|
||||
- Extension System/API
|
||||
- Metadata/Tagging
|
||||
- Performance
|
||||
- Settings/Configuration
|
||||
|
||||
@@ -1,27 +1,42 @@
|
||||
## Description
|
||||
## Summary
|
||||
|
||||
<!-- What does this PR do? Why is it needed? -->
|
||||
<!-- What changed, why is it needed, and which user-visible behavior is affected? -->
|
||||
|
||||
## Related Issues
|
||||
|
||||
<!-- Link related issues, e.g. "Fixes #123" -->
|
||||
<!-- Use "Fixes #123" when this PR should close an issue. -->
|
||||
|
||||
## Type of Change
|
||||
|
||||
- [ ] Bug fix
|
||||
- [ ] New feature
|
||||
- [ ] Refactor (no functional change)
|
||||
- [ ] Documentation
|
||||
- [ ] Other (describe below)
|
||||
- [ ] Feature
|
||||
- [ ] Performance improvement
|
||||
- [ ] Refactor with no intended behavior change
|
||||
- [ ] Tests, build, or repository maintenance
|
||||
- [ ] Documentation or localization
|
||||
|
||||
## Checklist
|
||||
## Validation
|
||||
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] `flutter analyze` and `flutter test` pass
|
||||
- [ ] `go vet ./...` and `go test ./...` pass in `go_backend/` (if Go code changed)
|
||||
- [ ] Documentation updated (if needed)
|
||||
- [ ] Commit messages follow the [conventional commits](https://www.conventionalcommits.org) format
|
||||
<!-- Check only commands relevant to this change. Explain skipped checks below. -->
|
||||
|
||||
## Screenshots
|
||||
- [ ] `dart format --output=none --set-exit-if-changed lib test`
|
||||
- [ ] `flutter analyze`
|
||||
- [ ] `flutter test`
|
||||
- [ ] `gofmt`, `go vet ./...`, and `go test ./...` in `go_backend/`
|
||||
- [ ] Android or iOS native checks
|
||||
- [ ] Manual reproduction or device test
|
||||
|
||||
<!-- For UI changes, add before/after screenshots. Delete this section otherwise. -->
|
||||
Validation notes:
|
||||
|
||||
<!-- Devices, commands, test cases, or the reason a check was not applicable. -->
|
||||
|
||||
## Contributor Checklist
|
||||
|
||||
- [ ] This PR is focused and contains no unrelated changes.
|
||||
- [ ] Extension-specific behavior, if any, uses a generic capability or manifest contract.
|
||||
- [ ] User-facing strings, documentation, and generated files are updated where needed.
|
||||
- [ ] No credentials, downloaded media, or build artifacts are included.
|
||||
|
||||
## Screenshots or Recordings
|
||||
|
||||
<!-- Add before/after media for UI changes. Delete this section otherwise. -->
|
||||
|
||||
@@ -37,6 +37,7 @@ jobs:
|
||||
- 'pubspec.lock'
|
||||
- 'analysis_options.yaml'
|
||||
- 'l10n.yaml'
|
||||
- '.fvmrc'
|
||||
- '.github/workflows/ci.yml'
|
||||
go:
|
||||
- 'go_backend/**'
|
||||
@@ -51,6 +52,7 @@ jobs:
|
||||
- 'lib/services/platform_bridge.dart'
|
||||
- 'pubspec.yaml'
|
||||
- 'pubspec.lock'
|
||||
- '.fvmrc'
|
||||
- '.github/workflows/ci.yml'
|
||||
|
||||
flutter:
|
||||
@@ -67,6 +69,7 @@ jobs:
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version-file: .fvmrc
|
||||
cache: true
|
||||
|
||||
- name: Cache pub dependencies
|
||||
@@ -102,8 +105,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
# Keep in sync with release.yml
|
||||
go-version: "1.26.5"
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
|
||||
- name: Check formatting
|
||||
@@ -134,13 +136,14 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26.5"
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
|
||||
- name: Setup Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version-file: .fvmrc
|
||||
cache: true
|
||||
|
||||
- name: Setup Gradle
|
||||
|
||||
@@ -70,7 +70,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26.5"
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
|
||||
# Cache Gradle for faster builds
|
||||
@@ -129,6 +129,7 @@ jobs:
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version-file: .fvmrc
|
||||
cache: true
|
||||
|
||||
- name: Cache pub dependencies
|
||||
@@ -146,13 +147,10 @@ jobs:
|
||||
|
||||
- name: Build APK (Release - unsigned)
|
||||
run: |
|
||||
flutter build apk --release --split-per-abi || true
|
||||
# Verify APKs were created
|
||||
flutter build apk --release --split-per-abi
|
||||
ls -la build/app/outputs/flutter-apk/
|
||||
if [ ! -f "build/app/outputs/flutter-apk/app-arm64-v8a-release.apk" ]; then
|
||||
echo "ERROR: APK not found!"
|
||||
exit 1
|
||||
fi
|
||||
test -f build/app/outputs/flutter-apk/app-arm64-v8a-release.apk
|
||||
test -f build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk
|
||||
|
||||
- name: Sign APKs
|
||||
uses: r0adkll/sign-android-release@v1
|
||||
@@ -168,12 +166,29 @@ jobs:
|
||||
|
||||
- name: Rename APKs
|
||||
run: |
|
||||
VERSION=${{ needs.get-version.outputs.version }}
|
||||
VERSION="${{ needs.get-version.outputs.version }}"
|
||||
cd build/app/outputs/flutter-apk
|
||||
# Signed files have -signed suffix
|
||||
mv app-arm64-v8a-release-signed.apk SpotiFLAC-${VERSION}-arm64.apk || mv app-arm64-v8a-release.apk SpotiFLAC-${VERSION}-arm64.apk || true
|
||||
mv app-armeabi-v7a-release-signed.apk SpotiFLAC-${VERSION}-arm32.apk || mv app-armeabi-v7a-release.apk SpotiFLAC-${VERSION}-arm32.apk || true
|
||||
mv app-release-signed.apk SpotiFLAC-${VERSION}-universal.apk || mv app-release.apk SpotiFLAC-${VERSION}-universal.apk || true
|
||||
|
||||
rename_required_apk() {
|
||||
unsigned="$1"
|
||||
destination="$2"
|
||||
signed="${unsigned%.apk}-signed.apk"
|
||||
if [ -f "$signed" ]; then
|
||||
mv "$signed" "$destination"
|
||||
elif [ -f "$unsigned" ]; then
|
||||
mv "$unsigned" "$destination"
|
||||
else
|
||||
echo "ERROR: Missing APK: $unsigned"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
rename_required_apk \
|
||||
app-arm64-v8a-release.apk \
|
||||
"SpotiFLAC-${VERSION}-arm64.apk"
|
||||
rename_required_apk \
|
||||
app-armeabi-v7a-release.apk \
|
||||
"SpotiFLAC-${VERSION}-arm32.apk"
|
||||
ls -la
|
||||
|
||||
- name: Upload APK artifact
|
||||
@@ -198,7 +213,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version: "1.26.5"
|
||||
go-version-file: go_backend/go.mod
|
||||
cache-dependency-path: go_backend/go.sum
|
||||
|
||||
# Cache CocoaPods
|
||||
@@ -274,6 +289,7 @@ jobs:
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version-file: .fvmrc
|
||||
cache: true
|
||||
|
||||
- name: Cache pub dependencies
|
||||
@@ -474,7 +490,7 @@ jobs:
|
||||
|
||||
jq --arg ver "$VERSION_NUM" \
|
||||
--arg date "$DATE" \
|
||||
--arg url "https://github.com/zarzet/SpotiFLAC-Mobile/releases/download/${VERSION}/SpotiFLAC-${VERSION}-ios-unsigned.ipa" \
|
||||
--arg url "https://github.com/${{ github.repository }}/releases/download/${VERSION}/SpotiFLAC-${VERSION}-ios-unsigned.ipa" \
|
||||
--argjson size "$IPA_SIZE" \
|
||||
'.apps[0].version = $ver | .apps[0].versionDate = $date | .apps[0].downloadURL = $url | .apps[0].size = $size' \
|
||||
apps.json > apps.json.tmp && mv apps.json.tmp apps.json
|
||||
|
||||
+70
-65
@@ -1,93 +1,98 @@
|
||||
# OS files
|
||||
# Operating-system files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# IDE
|
||||
# Editors and local assistants
|
||||
.idea/
|
||||
.vscode/
|
||||
*.iml
|
||||
.cursorignore
|
||||
.cursorrules
|
||||
|
||||
# Kiro specs (development only)
|
||||
.kiro/
|
||||
.playwright-mcp/
|
||||
.rtk/
|
||||
.claude/settings.local.json
|
||||
CLAUDE.md
|
||||
AGENTS.md
|
||||
|
||||
# Design assets (banners, mockups)
|
||||
design/
|
||||
|
||||
# Reference folder (development only)
|
||||
referensi/
|
||||
|
||||
# Documentation published separately. Keep the in-repo extension contract
|
||||
# available because contribution templates link to it.
|
||||
docs/*
|
||||
!docs/EXTENSION_DEVELOPMENT.md
|
||||
|
||||
# Old spotiflac_android folder (moved to root)
|
||||
spotiflac_android/
|
||||
|
||||
# Flutter/Dart
|
||||
# Flutter and Dart
|
||||
.dart_tool/
|
||||
.fvm/
|
||||
.packages
|
||||
build/
|
||||
*.lock
|
||||
!pubspec.lock
|
||||
.flutter-plugins
|
||||
.flutter-plugins-dependencies
|
||||
.metadata
|
||||
/build/
|
||||
/coverage/
|
||||
*.apk
|
||||
*.aab
|
||||
*.ipa
|
||||
|
||||
# Go backend build artifacts
|
||||
go_backend/*.aar
|
||||
go_backend/*.jar
|
||||
go_backend/*.exe
|
||||
go_backend/*.xcframework/
|
||||
# Local JavaScript tooling (the app itself has no Node dependency)
|
||||
/node_modules/
|
||||
/bun.lock
|
||||
/package-lock.json
|
||||
|
||||
# Android
|
||||
android/.gradle/
|
||||
android/app/libs/gobackend.aar
|
||||
android/app/libs/gobackend-sources.jar
|
||||
android/local.properties
|
||||
android/*.iml
|
||||
android/key.properties
|
||||
android/*.jks
|
||||
android/*.keystore
|
||||
android/app/*.jks
|
||||
# Go backend build outputs
|
||||
/go_backend/*.aar
|
||||
/go_backend/*.jar
|
||||
/go_backend/*.exe
|
||||
/go_backend/*.xcframework/
|
||||
|
||||
# iOS
|
||||
ios/Frameworks/
|
||||
ios/Pods/
|
||||
ios/.symlinks/
|
||||
ios/Flutter/Flutter.framework/
|
||||
ios/Flutter/Flutter.podspec
|
||||
# Android build state and signing material
|
||||
/android/.gradle/
|
||||
/android/.kotlin/
|
||||
/android/app/build/
|
||||
/android/app/libs/*.aar
|
||||
/android/app/libs/*-sources.jar
|
||||
/android/local.properties
|
||||
/android/*.iml
|
||||
/android/key.properties
|
||||
/android/*.jks
|
||||
/android/*.keystore
|
||||
/android/app/*.jks
|
||||
|
||||
# Extension folder
|
||||
extension/*
|
||||
extension/v2/
|
||||
extension/v2/**
|
||||
# iOS generated state
|
||||
/ios/Frameworks/
|
||||
/ios/Pods/
|
||||
/ios/.symlinks/
|
||||
/ios/Flutter/ephemeral/
|
||||
/ios/Flutter/Flutter.framework/
|
||||
/ios/Flutter/Flutter.podspec
|
||||
*.xcarchive
|
||||
DerivedData/
|
||||
|
||||
# Agent instructions
|
||||
AGENTS.md
|
||||
# Credentials and machine-local configuration
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.mobileprovision
|
||||
*.p12
|
||||
*.pem
|
||||
|
||||
# Temp/misc
|
||||
.tmp/
|
||||
# Local research and design material
|
||||
/design/
|
||||
/referensi/
|
||||
/extension/
|
||||
/tool/
|
||||
/spotiflac_android/
|
||||
|
||||
# Documentation published separately. Keep the in-repo extension contract
|
||||
# available because contribution templates link to it.
|
||||
/docs/*
|
||||
!/docs/EXTENSION_DEVELOPMENT.md
|
||||
|
||||
# Temporary files and logs
|
||||
/.tmp/
|
||||
nul
|
||||
NUL
|
||||
network_requests.txt
|
||||
*.bak
|
||||
/network_requests.txt
|
||||
/AndroidManifest.xml
|
||||
|
||||
# Log files
|
||||
*.bak
|
||||
*.orig
|
||||
*.swp
|
||||
*.tmp
|
||||
*.log
|
||||
hs_err_*.log
|
||||
flutter_*.log
|
||||
|
||||
# Development tools
|
||||
tool/
|
||||
.claude/settings.local.json
|
||||
.playwright-mcp/
|
||||
.rtk/
|
||||
CLAUDE.md
|
||||
|
||||
# FVM Version Cache
|
||||
.fvm/
|
||||
|
||||
+13
-13
@@ -1206,8 +1206,8 @@ Thank you for your understanding and continued support. This decision was made t
|
||||
|
||||
### Highlights
|
||||
|
||||
- **Local Library Scanning** ([#117](https://github.com/zarzet/SpotiFLAC-Mobile/issues/117)): Scan existing music collection to detect duplicates (FLAC, M4A, MP3, Opus, OGG)
|
||||
- **Duplicate Detection** ([#117](https://github.com/zarzet/SpotiFLAC-Mobile/issues/117)): "In Library" badge on tracks matching by ISRC or track name + artist
|
||||
- **Local Library Scanning** ([#117](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/117)): Scan existing music collection to detect duplicates (FLAC, M4A, MP3, Opus, OGG)
|
||||
- **Duplicate Detection** ([#117](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/117)): "In Library" badge on tracks matching by ISRC or track name + artist
|
||||
- **Unified Library Tab**: History renamed to Library, shows Downloaded + Local Library tracks with source badges
|
||||
|
||||
### Added
|
||||
@@ -1275,7 +1275,7 @@ Same as 3.3.1 but fixes crash issues caused by FFmpeg.
|
||||
|
||||
### Added
|
||||
|
||||
- **Clear All Queue Button**: Cancel all queued downloads with one tap ([#96](https://github.com/zarzet/SpotiFLAC-Mobile/issues/96))
|
||||
- **Clear All Queue Button**: Cancel all queued downloads with one tap ([#96](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/96))
|
||||
- **IDHS Fallback**: Fallback link resolver when SongLink fails (rate limited 8 req/min)
|
||||
- **Lossy Bitrate Options**: MP3 (320/256/192/128kbps), Opus (128/96/64kbps)
|
||||
- **Search Filters**: Filter results by type (Tracks, Artists, Albums, Playlists)
|
||||
@@ -1292,10 +1292,10 @@ Same as 3.3.1 but fixes crash issues caused by FFmpeg.
|
||||
|
||||
### Fixed
|
||||
|
||||
- **MP3 Download Error 403**: Fixed 403 Forbidden error when downloading MP3 files ([#108](https://github.com/zarzet/SpotiFLAC-Mobile/issues/108))
|
||||
- **MP3 Download Error 403**: Fixed 403 Forbidden error when downloading MP3 files ([#108](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/108))
|
||||
- **Opus Cover Art**: Implemented METADATA_BLOCK_PICTURE for proper cover embedding
|
||||
- **Deezer Pagination**: Fixed >25 tracks only showing first 25 ([#112](https://github.com/zarzet/SpotiFLAC-Mobile/issues/112))
|
||||
- **Duplicate Embed Lyrics Setting**: Removed from Options page ([#110](https://github.com/zarzet/SpotiFLAC-Mobile/issues/110))
|
||||
- **Deezer Pagination**: Fixed >25 tracks only showing first 25 ([#112](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/112))
|
||||
- **Duplicate Embed Lyrics Setting**: Removed from Options page ([#110](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/110))
|
||||
|
||||
---
|
||||
|
||||
@@ -1508,7 +1508,7 @@ Same as 3.3.1 but fixes crash issues caused by FFmpeg.
|
||||
- Spanish: Credits 125 ([@credits125](https://crowdin.com/profile/credits125))
|
||||
- Portuguese: Pedro Marcondes ([@justapedro](https://crowdin.com/profile/justapedro))
|
||||
- Russian: Владислав ([@odinokiy_kot](https://crowdin.com/profile/odinokiy_kot))
|
||||
- **Quick Search Provider Switcher** ([#76](https://github.com/zarzet/SpotiFLAC-Mobile/issues/76)): Dropdown menu in search bar for instant provider switching
|
||||
- **Quick Search Provider Switcher** ([#76](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/76)): Dropdown menu in search bar for instant provider switching
|
||||
- Tap the search icon to reveal a dropdown menu with all available search providers
|
||||
- Shows default provider (Deezer based on metadata source setting) at the top
|
||||
- Lists all enabled extensions with custom search capability
|
||||
@@ -1517,16 +1517,16 @@ Same as 3.3.1 but fixes crash issues caused by FFmpeg.
|
||||
- Search hint text updates immediately when switching providers
|
||||
- Re-triggers search automatically if there's existing text in the search bar
|
||||
- Eliminates need to navigate to Settings > Extensions > Search Provider
|
||||
- **Extension Button Setting Type** ([#74](https://github.com/zarzet/SpotiFLAC-Mobile/issues/74)): New setting type for extension actions
|
||||
- **Extension Button Setting Type** ([#74](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/74)): New setting type for extension actions
|
||||
- Extensions can define `button` type in manifest settings
|
||||
- Triggers JavaScript function when tapped (e.g., start OAuth flow)
|
||||
- Useful for authentication, manual sync, or any custom action
|
||||
- **Genre & Label Metadata** ([#75](https://github.com/zarzet/SpotiFLAC-Mobile/issues/75)): Downloaded tracks now include genre and record label information
|
||||
- **Genre & Label Metadata** ([#75](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/75)): Downloaded tracks now include genre and record label information
|
||||
- Fetches genre and label from Deezer album API for each track
|
||||
- Embeds GENRE, ORGANIZATION (label), and COPYRIGHT tags into FLAC files
|
||||
- Works automatically when Deezer track ID is available (via ISRC matching)
|
||||
- Supports all download services (Tidal, Qobuz, Amazon) and extension downloads
|
||||
- **MP3 Quality Option** ([#69](https://github.com/zarzet/SpotiFLAC-Mobile/issues/69)): Optional MP3 download format with FLAC-to-MP3 conversion
|
||||
- **MP3 Quality Option** ([#69](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/69)): Optional MP3 download format with FLAC-to-MP3 conversion
|
||||
- New "Enable MP3 Option" toggle in Settings > Download > Audio Quality
|
||||
- When enabled, MP3 (320kbps) appears as a quality option alongside FLAC options
|
||||
- Available in both the quality picker dialog and default quality settings
|
||||
@@ -1552,12 +1552,12 @@ Same as 3.3.1 but fixes crash issues caused by FFmpeg.
|
||||
- **Artist Name in Album Screen**: Album info card now displays artist name below album title
|
||||
- Extracted from first track's artist metadata
|
||||
- Styled with `onSurfaceVariant` color for visual hierarchy
|
||||
- **Disc Separation for Multi-Disc Albums** ([#70](https://github.com/zarzet/SpotiFLAC-Mobile/issues/70)): Downloaded albums with multiple discs now display tracks grouped by disc
|
||||
- **Disc Separation for Multi-Disc Albums** ([#70](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/70)): Downloaded albums with multiple discs now display tracks grouped by disc
|
||||
- Visual disc separator header showing "Disc 1", "Disc 2", etc.
|
||||
- Tracks sorted by disc number first, then by track number
|
||||
- Single-disc albums display normally without separators
|
||||
- Fixes confusion when albums have duplicate track numbers across discs
|
||||
- **Album Grouping in Recents** ([#70](https://github.com/zarzet/SpotiFLAC-Mobile/issues/70)): Downloads now show as albums instead of individual tracks in the Recent section
|
||||
- **Album Grouping in Recents** ([#70](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues/70)): Downloads now show as albums instead of individual tracks in the Recent section
|
||||
- Prevents flooding the recents list when downloading full albums
|
||||
- Groups tracks by album name and artist
|
||||
- Tapping navigates directly to the downloaded album screen
|
||||
@@ -1697,4 +1697,4 @@ SpotiFLAC 3.0 introduces a powerful extension system that allows third-party int
|
||||
|
||||
---
|
||||
|
||||
_For older versions, see [GitHub Releases_](https://github.com/zarzet/SpotiFLAC-Mobile/releases)
|
||||
_For older versions, see [GitHub Releases_](https://github.com/spotiflacapp/SpotiFLAC-Mobile/releases)
|
||||
|
||||
+117
-239
@@ -1,289 +1,167 @@
|
||||
# Contributing to SpotiFLAC
|
||||
# Contributing to SpotiFLAC Mobile
|
||||
|
||||
First off, thank you for considering contributing to SpotiFLAC! 🎉
|
||||
Thank you for helping improve SpotiFLAC Mobile. Bug reports, focused pull
|
||||
requests, documentation, and translations are all welcome.
|
||||
|
||||
This document provides guidelines and steps for contributing. Following these guidelines helps maintain code quality and ensures a smooth collaboration process.
|
||||
Please follow the [Code of Conduct](CODE_OF_CONDUCT.md) when participating in
|
||||
the project.
|
||||
|
||||
## Table of Contents
|
||||
## Before You Start
|
||||
|
||||
- [Code of Conduct](#code-of-conduct)
|
||||
- [How Can I Contribute?](#how-can-i-contribute)
|
||||
- [Reporting Bugs](#reporting-bugs)
|
||||
- [Suggesting Features](#suggesting-features)
|
||||
- [Code Contributions](#code-contributions)
|
||||
- [Translations](#translations)
|
||||
- [Development Setup](#development-setup)
|
||||
- [Project Structure](#project-structure)
|
||||
- [Coding Guidelines](#coding-guidelines)
|
||||
- [Commit Guidelines](#commit-guidelines)
|
||||
- [Pull Request Process](#pull-request-process)
|
||||
- Search the [existing issues](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues)
|
||||
before opening a new one.
|
||||
- Use the issue template that best matches the problem.
|
||||
- Keep pull requests focused. Separate unrelated fixes into separate PRs.
|
||||
- Never commit credentials, signing files, downloaded media, or generated build
|
||||
artifacts.
|
||||
|
||||
## Code of Conduct
|
||||
Translations are managed through the
|
||||
[SpotiFLAC Mobile Crowdin project](https://crowdin.com/project/spotiflac-mobile).
|
||||
The English source strings live in `lib/l10n/arb/app_en.arb`.
|
||||
|
||||
This project and everyone participating in it is governed by our [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers.
|
||||
## Toolchain
|
||||
|
||||
## How Can I Contribute?
|
||||
The repository is the source of truth for tool versions:
|
||||
|
||||
### Reporting Bugs
|
||||
- Flutter: `.fvmrc`
|
||||
- Dart: bundled with the pinned Flutter SDK
|
||||
- Go: `go_backend/go.mod`
|
||||
- Android SDK, NDK, and Java: `.github/workflows/ci.yml`
|
||||
- Xcode: required only for iOS builds
|
||||
|
||||
Before creating bug reports, please check the [existing issues](https://github.com/zarzet/SpotiFLAC-Mobile/issues) to avoid duplicates.
|
||||
|
||||
When creating a bug report, please use the bug report template and include:
|
||||
|
||||
- **Clear and descriptive title**
|
||||
- **Steps to reproduce** the issue
|
||||
- **Expected behavior** vs **actual behavior**
|
||||
- **Screenshots or screen recordings** if applicable
|
||||
- **Device information** (model, OS version)
|
||||
- **App version**
|
||||
- **Logs** from Settings > About > View Logs
|
||||
|
||||
### Suggesting Features
|
||||
|
||||
Feature requests are welcome! Please use the feature request template and:
|
||||
|
||||
- **Check existing issues** to avoid duplicates
|
||||
- **Describe the feature** clearly
|
||||
- **Explain the use case** - why would this be useful?
|
||||
- **Consider the scope** - is this a small enhancement or a major feature?
|
||||
|
||||
### Code Contributions
|
||||
|
||||
1. **Fork the repository** and create your branch from `main`
|
||||
2. **Make your changes** following our coding guidelines
|
||||
3. **Test your changes** thoroughly
|
||||
4. **Submit a pull request** to the `main` branch
|
||||
|
||||
### Translations
|
||||
|
||||
We use [Crowdin](https://crowdin.com/project/spotiflac-mobile) for translations. To contribute:
|
||||
|
||||
1. Visit our [Crowdin project](https://crowdin.com/project/spotiflac-mobile)
|
||||
2. Select your language or request a new one
|
||||
3. Start translating!
|
||||
|
||||
Translation files are located in `lib/l10n/arb/`.
|
||||
[FVM](https://fvm.app/) is recommended. If you do not use FVM, install the
|
||||
exact Flutter version declared in `.fvmrc` and replace `fvm flutter` with
|
||||
`flutter` (and `fvm dart` with `dart`) in the commands below.
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Prerequisites
|
||||
1. Fork and clone the repository:
|
||||
|
||||
- **Flutter SDK** 3.10.0 or higher
|
||||
- **Dart SDK** 3.10.0 or higher
|
||||
- **Android Studio** or **VS Code** with Flutter extensions
|
||||
- **Git**
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. **Clone your fork**
|
||||
```bash
|
||||
git clone https://github.com/YOUR_USERNAME/SpotiFLAC-Mobile.git
|
||||
cd SpotiFLAC-Mobile
|
||||
```
|
||||
|
||||
2. **Add upstream remote**
|
||||
```bash
|
||||
git remote add upstream https://github.com/spotiflacapp/SpotiFLAC-Mobile.git
|
||||
```
|
||||
|
||||
3. **Use FVM (Flutter Version: 3.41.5)**
|
||||
2. Install the pinned Flutter SDK and Dart dependencies:
|
||||
|
||||
```bash
|
||||
fvm use
|
||||
fvm install
|
||||
fvm flutter pub get
|
||||
```
|
||||
|
||||
4. **Install dependencies**
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
5. **Generate code** (for Riverpod, JSON serialization, etc.)
|
||||
```bash
|
||||
dart run build_runner build --delete-conflicting-outputs
|
||||
```
|
||||
|
||||
6. **Set up Go environment (Go Version: 1.25.9)**
|
||||
|
||||
Building the Go backend for Android requires the **Android NDK** (r29 is what CI uses). Make sure `ANDROID_NDK_HOME` points to it and `CGO_ENABLED=1`.
|
||||
3. Build the Go backend for Android. `ANDROID_NDK_HOME` must point to the NDK
|
||||
version used by CI and `CGO_ENABLED` must be enabled.
|
||||
|
||||
```bash
|
||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||
gomobile init
|
||||
cd go_backend
|
||||
go mod download
|
||||
go install golang.org/x/mobile/cmd/gomobile
|
||||
gomobile init
|
||||
mkdir -p ../android/app/libs
|
||||
gomobile bind -target=android -androidapi 24 -o ../android/app/libs/gobackend.aar .
|
||||
gomobile bind \
|
||||
-target=android/arm,android/arm64 \
|
||||
-androidapi 24 \
|
||||
-o ../android/app/libs/gobackend.aar \
|
||||
.
|
||||
cd ..
|
||||
```
|
||||
|
||||
7. **Run the app**
|
||||
Running `go install` from `go_backend/` uses the `x/mobile` version pinned by
|
||||
`go.mod`. Do not replace it with `@latest` in project scripts.
|
||||
|
||||
4. Run the app:
|
||||
|
||||
```bash
|
||||
flutter run
|
||||
fvm flutter run
|
||||
```
|
||||
|
||||
### Building
|
||||
For iOS, run `scripts/build_ios.sh` on macOS before opening
|
||||
`ios/Runner.xcworkspace`.
|
||||
|
||||
## Project Boundaries
|
||||
|
||||
```text
|
||||
lib/ Flutter UI, state, models, and platform orchestration
|
||||
go_backend/ Download pipeline, extension runtime, and shared backend logic
|
||||
android/ Android platform bridge and foreground worker
|
||||
ios/ iOS platform bridge and application project
|
||||
test/ Flutter unit and widget tests
|
||||
assets/ Images, fonts, and bundled resources
|
||||
docs/ Contributor-facing technical contracts
|
||||
scripts/ Reproducible project build helpers
|
||||
```
|
||||
|
||||
SpotiFLAC Mobile is extension-driven. Extension-specific behavior must be
|
||||
declared through a generic manifest field, capability, or reusable app API.
|
||||
Do not add provider-name checks such as `if source == 'provider-name'` to the
|
||||
main app. The Go backend should parse and expose the generic declaration, and
|
||||
Dart should consume that declaration without knowing which extension uses it.
|
||||
|
||||
## Generated Files
|
||||
|
||||
- After changing ARB files, run `fvm flutter gen-l10n` and commit the resulting
|
||||
localization sources.
|
||||
- Run `fvm dart run build_runner build --delete-conflicting-outputs` only when a
|
||||
model or generator input changes, then commit the relevant generated source.
|
||||
- Do not commit `build/`, `.dart_tool/`, AAR/XCFramework output, IDE state, or
|
||||
local research directories.
|
||||
|
||||
## Validation
|
||||
|
||||
Run checks that cover the code you changed. Before opening a PR, the relevant
|
||||
commands should pass.
|
||||
|
||||
Flutter and Dart:
|
||||
|
||||
```bash
|
||||
# Debug build
|
||||
flutter build apk --debug
|
||||
|
||||
# Release build
|
||||
flutter build apk --release
|
||||
fvm dart format --output=none --set-exit-if-changed lib test
|
||||
fvm flutter analyze
|
||||
fvm flutter test
|
||||
```
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
lib/
|
||||
├── l10n/ # Localization files
|
||||
│ └── arb/ # ARB translation files
|
||||
├── models/ # Data models
|
||||
├── providers/ # Riverpod providers
|
||||
├── screens/ # UI screens
|
||||
│ └── settings/ # Settings sub-screens
|
||||
├── services/ # Business logic services
|
||||
├── theme/ # App theming
|
||||
├── utils/ # Utility functions
|
||||
├── widgets/ # Reusable widgets
|
||||
├── app.dart # App configuration
|
||||
└── main.dart # Entry point
|
||||
```
|
||||
|
||||
## Coding Guidelines
|
||||
|
||||
### General
|
||||
|
||||
- Follow [Effective Dart](https://dart.dev/effective-dart) guidelines
|
||||
- Use meaningful variable and function names
|
||||
- Keep functions small and focused
|
||||
- Add comments for complex logic
|
||||
|
||||
### Formatting
|
||||
|
||||
- Use `dart format` before committing
|
||||
- Maximum line length: 80 characters
|
||||
- Use trailing commas for better formatting
|
||||
Go backend:
|
||||
|
||||
```bash
|
||||
dart format .
|
||||
cd go_backend
|
||||
gofmt -w .
|
||||
go vet ./...
|
||||
go test ./...
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
Ensure your code passes all lints:
|
||||
Android native code, after building `gobackend.aar`:
|
||||
|
||||
```bash
|
||||
flutter analyze
|
||||
cd android
|
||||
./gradlew :app:compileDebugKotlin :app:testDebugUnitTest
|
||||
```
|
||||
|
||||
### State Management
|
||||
For user-facing changes, add or update tests where practical and include
|
||||
before/after screenshots for UI changes.
|
||||
|
||||
We use **Riverpod** for state management, with hand-written `Notifier`s
|
||||
(no `riverpod_annotation` code generation). Follow this pattern:
|
||||
## Code and Commit Style
|
||||
|
||||
```dart
|
||||
class MyNotifier extends Notifier<MyState> {
|
||||
@override
|
||||
MyState build() => MyState();
|
||||
- Follow `analysis_options.yaml`, `.editorconfig`, and existing module patterns.
|
||||
- Keep user-facing strings in the localization files.
|
||||
- Prefer small functions and explicit error handling at platform boundaries.
|
||||
- Use [Conventional Commits](https://www.conventionalcommits.org/), for example:
|
||||
|
||||
// Methods to update state
|
||||
}
|
||||
```text
|
||||
feat(download): add batch selection
|
||||
fix(storage): handle revoked folder access
|
||||
docs(contributing): refresh Android setup
|
||||
```
|
||||
|
||||
final myProvider = NotifierProvider<MyNotifier, MyState>(MyNotifier.new);
|
||||
```
|
||||
## Pull Requests
|
||||
|
||||
### Localization
|
||||
1. Create a branch from an up-to-date `main`.
|
||||
2. Make one focused change and include tests or verification evidence.
|
||||
3. Complete the pull request template, including any checks that were not run
|
||||
and why.
|
||||
4. Link related issues with `Fixes #123` where appropriate.
|
||||
5. Respond to review feedback with follow-up commits; maintainers may squash
|
||||
commits when merging.
|
||||
|
||||
All user-facing strings should be localized:
|
||||
|
||||
```dart
|
||||
// Good
|
||||
Text(AppLocalizations.of(context)!.downloadComplete)
|
||||
|
||||
// Bad
|
||||
Text('Download Complete')
|
||||
```
|
||||
|
||||
To add new strings:
|
||||
1. Add the key to `lib/l10n/arb/app_en.arb`
|
||||
2. Run `flutter gen-l10n`
|
||||
|
||||
## Commit Guidelines
|
||||
|
||||
We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||
|
||||
```
|
||||
<type>(<scope>): <description>
|
||||
|
||||
[optional body]
|
||||
|
||||
[optional footer(s)]
|
||||
```
|
||||
|
||||
### Types
|
||||
|
||||
- `feat`: New feature
|
||||
- `fix`: Bug fix
|
||||
- `docs`: Documentation changes
|
||||
- `style`: Code style changes (formatting, etc.)
|
||||
- `refactor`: Code refactoring
|
||||
- `perf`: Performance improvements
|
||||
- `test`: Adding or updating tests
|
||||
- `chore`: Maintenance tasks
|
||||
|
||||
### Examples
|
||||
|
||||
```
|
||||
feat(download): add batch download support
|
||||
fix(ui): resolve overflow on small screens
|
||||
docs: update contributing guidelines
|
||||
chore(deps): update flutter_riverpod to 3.1.0
|
||||
```
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. **Update your fork**
|
||||
```bash
|
||||
git fetch upstream
|
||||
git rebase upstream/main
|
||||
```
|
||||
|
||||
2. **Create a feature branch**
|
||||
```bash
|
||||
git checkout -b feat/my-new-feature
|
||||
```
|
||||
|
||||
3. **Make your changes** and commit following our guidelines
|
||||
|
||||
4. **Push to your fork**
|
||||
```bash
|
||||
git push origin feat/my-new-feature
|
||||
```
|
||||
|
||||
5. **Create a Pull Request**
|
||||
- Target the `main` branch
|
||||
- Fill in the PR template
|
||||
- Link related issues
|
||||
|
||||
6. **Address review feedback**
|
||||
- Make requested changes
|
||||
- Push additional commits
|
||||
- Request re-review when ready
|
||||
|
||||
### PR Requirements
|
||||
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] All tests pass
|
||||
- [ ] No new linting errors
|
||||
- [ ] Documentation updated (if needed)
|
||||
- [ ] Commit messages follow guidelines
|
||||
- [ ] PR description is clear and complete
|
||||
|
||||
CI runs `flutter analyze`, `flutter test`, `go vet`, and `go test` on every pull request — make sure they pass locally before pushing.
|
||||
|
||||
## Questions?
|
||||
|
||||
If you have questions, feel free to:
|
||||
|
||||
- Open a [Discussion](https://github.com/spotiflacapp/SpotiFLAC-Mobile/discussions)
|
||||
- Check existing [Issues](https://github.com/spotiflacapp/SpotiFLAC-Mobile/issues)
|
||||
|
||||
Thank you for contributing! 💚
|
||||
When reporting a crash, include the SpotiFLAC Mobile version, release channel,
|
||||
device/OS, exact reproduction steps, storage mode, and exported app logs. For a
|
||||
cold-start Android crash, `adb logcat -b crash -d` is especially useful.
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
<div align="center">
|
||||
|
||||
[](https://github.com/zarzet/SpotiFLAC-Mobile/releases)
|
||||
[](https://www.virustotal.com/gui/file/31d1bf3c3b2015c13e83c4f909a7c6093a9423e3e702f0c582a3e0035c849424)
|
||||
[](https://github.com/spotiflacapp/SpotiFLAC-Mobile/releases)
|
||||
[](https://crowdin.com/project/spotiflac-mobile)
|
||||
|
||||
[](https://t.me/spotiflac)
|
||||
@@ -59,6 +58,18 @@ Extensions let the community add new music sources and features without waiting
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
SpotiFLAC Mobile combines a Flutter/Dart UI, a Go backend compiled with
|
||||
`gomobile`, and thin Android/iOS platform bridges. Toolchain versions are
|
||||
pinned in [`.fvmrc`](.fvmrc), [`go_backend/go.mod`](go_backend/go.mod), and the
|
||||
GitHub Actions workflows.
|
||||
|
||||
Start with the [Contributing Guide](CONTRIBUTING.md) for the development setup,
|
||||
project boundaries, validation commands, and pull request checklist.
|
||||
|
||||
---
|
||||
|
||||
## Related Projects
|
||||
|
||||
### [SpotiFLAC (Desktop)](https://github.com/afkarxyz/SpotiFLAC)
|
||||
@@ -75,7 +86,10 @@ Python library for SpotiFLAC integration, maintained by [@ShuShuzinhuu](https://
|
||||
<summary><b>Why does the Store tab ask me to enter a URL?</b></summary>
|
||||
<br>
|
||||
|
||||
Starting from version 3.8.0, SpotiFLAC uses a decentralized extension repository system extensions are hosted on GitHub repositories rather than a built-in server, so anyone can create and host their own. Enter a repository URL in the Store tab to browse and install extensions.
|
||||
Starting from version 3.8.0, SpotiFLAC Mobile uses a decentralized extension
|
||||
repository system. Extensions are hosted independently rather than on a
|
||||
built-in server, so anyone can create and host a compatible repository. Enter
|
||||
a repository URL in the Store tab to browse and install extensions.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -107,7 +121,9 @@ Yes! Just paste the playlist URL in the search bar. The app will fetch all track
|
||||
<summary><b>Why do I need to grant storage permission?</b></summary>
|
||||
<br>
|
||||
|
||||
The app needs permission to save downloaded files to your device. On Android 13+, you may need to grant **All files access** under **Settings > Apps > SpotiFLAC > Permissions**.
|
||||
The app needs a writable destination for downloaded files. On Android, choose a
|
||||
folder with the system folder picker (SAF), or use the app-specific folder. If
|
||||
Android revokes a saved folder grant, select the folder again in Settings.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -115,7 +131,8 @@ The app needs permission to save downloaded files to your device. On Android 13+
|
||||
<summary><b>Is this app safe?</b></summary>
|
||||
<br>
|
||||
|
||||
Yes SpotiFLAC is open source and you can verify the code yourself. Each release is also scanned with VirusTotal (see badge above).
|
||||
SpotiFLAC Mobile is open source, so its code and build workflows can be
|
||||
inspected directly in this repository.
|
||||
|
||||
</details>
|
||||
|
||||
@@ -128,13 +145,13 @@ Some countries have restricted access to certain streaming service APIs. If down
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Can I add SpotiFLAC to AltStore or SideStore?</b></summary>
|
||||
<summary><b>Can I add SpotiFLAC Mobile to AltStore or SideStore?</b></summary>
|
||||
<br>
|
||||
|
||||
Yes! Add the official source to receive updates directly within the app. Copy this link:
|
||||
|
||||
```
|
||||
https://raw.githubusercontent.com/zarzet/SpotiFLAC-Mobile/refs/heads/main/apps.json
|
||||
https://raw.githubusercontent.com/spotiflacapp/SpotiFLAC-Mobile/refs/heads/main/apps.json
|
||||
```
|
||||
|
||||
In AltStore/SideStore, go to **Browse > Sources**, tap **+**, and paste the link.
|
||||
@@ -142,7 +159,7 @@ In AltStore/SideStore, go to **Browse > Sources**, tap **+**, and paste the link
|
||||
</details>
|
||||
|
||||
> [!NOTE]
|
||||
> If SpotiFLAC is useful to you, consider supporting development:
|
||||
> If SpotiFLAC Mobile is useful to you, consider supporting development:
|
||||
>
|
||||
> [](https://ko-fi.com/zarzet)
|
||||
|
||||
@@ -152,8 +169,8 @@ In AltStore/SideStore, go to **Browse > Sources**, tap **+**, and paste the link
|
||||
|
||||
Thanks to everyone who has contributed to SpotiFLAC Mobile!
|
||||
|
||||
<a href="https://github.com/zarzet/SpotiFLAC-Mobile/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=zarzet/SpotiFLAC-Mobile" />
|
||||
<a href="https://github.com/spotiflacapp/SpotiFLAC-Mobile/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=spotiflacapp/SpotiFLAC-Mobile" />
|
||||
</a>
|
||||
|
||||
We also appreciate everyone who helped with [translations on Crowdin](https://crowdin.com/project/spotiflac-mobile), reported bugs, suggested features, and spread the word.
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
"developerName": "zarzet",
|
||||
"version": "4.7.1",
|
||||
"versionDate": "2026-07-01",
|
||||
"downloadURL": "https://github.com/zarzet/SpotiFLAC-Mobile/releases/download/v4.7.1/SpotiFLAC-v4.7.1-ios-unsigned.ipa",
|
||||
"localizedDescription": "SpotiFLAC Mobile is written in Flutter. Download tracks in true FLAC via installable extensions for Tidal, Qobuz, Deezer, and more.",
|
||||
"iconURL": "https://raw.githubusercontent.com/zarzet/SpotiFLAC-Mobile/main/assets/images/logo.png",
|
||||
"downloadURL": "https://github.com/spotiflacapp/SpotiFLAC-Mobile/releases/download/v4.7.1/SpotiFLAC-v4.7.1-ios-unsigned.ipa",
|
||||
"localizedDescription": "SpotiFLAC Mobile is written in Flutter and uses installable extensions for metadata and audio downloads.",
|
||||
"iconURL": "https://raw.githubusercontent.com/spotiflacapp/SpotiFLAC-Mobile/main/assets/images/logo.png",
|
||||
"size": 37455821
|
||||
}
|
||||
]
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
# Template for the changelog body
|
||||
body = """
|
||||
{%- macro remote_url() -%}
|
||||
https://github.com/zarzet/SpotiFLAC-Mobile
|
||||
https://github.com/spotiflacapp/SpotiFLAC-Mobile
|
||||
{%- endmacro -%}
|
||||
|
||||
{% if version %}\
|
||||
@@ -99,5 +99,5 @@ tag_pattern = "v[0-9].*"
|
||||
sort_commits = "newest"
|
||||
|
||||
[remote.github]
|
||||
owner = "zarzet"
|
||||
owner = "spotiflacapp"
|
||||
repo = "SpotiFLAC-Mobile"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
arb-dir: lib/l10n/arb
|
||||
arb-dir: lib/l10n/arb
|
||||
template-arb-file: app_en.arb
|
||||
output-localization-file: app_localizations.dart
|
||||
output-class: AppLocalizations
|
||||
|
||||
@@ -13,7 +13,7 @@ class AppInfo {
|
||||
static const String mobileAuthor = 'zarzet';
|
||||
static const String originalAuthor = 'afkarxyz';
|
||||
|
||||
static const String githubRepo = 'zarzet/SpotiFLAC-Mobile';
|
||||
static const String githubRepo = 'spotiflacapp/SpotiFLAC-Mobile';
|
||||
static const String githubUrl = 'https://github.com/$githubRepo';
|
||||
static const String originalGithubUrl =
|
||||
'https://github.com/afkarxyz/SpotiFLAC';
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name: spotiflac_android
|
||||
description: Download Spotify tracks in FLAC using extension providers
|
||||
description: Extension-driven music metadata and downloads for mobile devices
|
||||
publish_to: "none"
|
||||
version: 4.8.1+139
|
||||
|
||||
|
||||
+26
-59
@@ -1,78 +1,45 @@
|
||||
#!/bin/bash
|
||||
# Build script for iOS XCFramework
|
||||
# This script compiles the Go backend to XCFramework for iOS
|
||||
# Must be run on macOS with Xcode installed
|
||||
#!/usr/bin/env bash
|
||||
# Build the Go backend XCFramework used by SpotiFLAC Mobile on iOS.
|
||||
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
GO_BACKEND_DIR="$PROJECT_DIR/go_backend"
|
||||
IOS_DIR="$PROJECT_DIR/ios"
|
||||
OUTPUT_DIR="$IOS_DIR/Frameworks"
|
||||
OUTPUT_DIR="$PROJECT_DIR/ios/Frameworks"
|
||||
|
||||
echo "=== SpotiFLAC iOS Build Script ==="
|
||||
echo "Project directory: $PROJECT_DIR"
|
||||
echo "Go backend directory: $GO_BACKEND_DIR"
|
||||
echo "Output directory: $OUTPUT_DIR"
|
||||
echo "SpotiFLAC Mobile iOS backend build"
|
||||
echo "Project: $PROJECT_DIR"
|
||||
echo "Output: $OUTPUT_DIR"
|
||||
|
||||
# Check if running on macOS
|
||||
if [[ "$(uname)" != "Darwin" ]]; then
|
||||
echo "Error: This script must be run on macOS"
|
||||
exit 1
|
||||
echo "Error: this script must run on macOS with Xcode installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if Go is installed
|
||||
if ! command -v go &> /dev/null; then
|
||||
echo "Error: Go is not installed. Please install Go first."
|
||||
exit 1
|
||||
if ! command -v go >/dev/null 2>&1; then
|
||||
echo "Error: Go is not installed." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Go version: $(go version)"
|
||||
cd "$GO_BACKEND_DIR"
|
||||
go mod download
|
||||
|
||||
# Check if gomobile is installed
|
||||
if ! command -v gomobile &> /dev/null; then
|
||||
echo "Installing gomobile..."
|
||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||
go install golang.org/x/mobile/cmd/gobind@latest
|
||||
fi
|
||||
|
||||
# Initialize gomobile (required for iOS builds)
|
||||
echo "Initializing gomobile..."
|
||||
# Running inside the module installs the x/mobile revision pinned by go.mod.
|
||||
go install golang.org/x/mobile/cmd/gomobile
|
||||
export PATH="$(go env GOPATH)/bin:$PATH"
|
||||
gomobile init
|
||||
|
||||
# Create output directory
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
gomobile bind \
|
||||
-target=ios \
|
||||
-tags ios \
|
||||
-o "$OUTPUT_DIR/Gobackend.xcframework" \
|
||||
.
|
||||
|
||||
# Navigate to Go backend directory
|
||||
cd "$GO_BACKEND_DIR"
|
||||
|
||||
# Download dependencies
|
||||
echo "Downloading Go dependencies..."
|
||||
go mod download
|
||||
go mod tidy
|
||||
|
||||
# Build XCFramework for iOS
|
||||
echo "Building XCFramework for iOS..."
|
||||
gomobile bind -target=ios -o "$OUTPUT_DIR/Gobackend.xcframework" .
|
||||
|
||||
# Verify output
|
||||
if [ -d "$OUTPUT_DIR/Gobackend.xcframework" ]; then
|
||||
echo "✅ Successfully built Gobackend.xcframework"
|
||||
echo "Output: $OUTPUT_DIR/Gobackend.xcframework"
|
||||
|
||||
# List architectures
|
||||
echo ""
|
||||
echo "Architectures included:"
|
||||
ls -la "$OUTPUT_DIR/Gobackend.xcframework/"
|
||||
else
|
||||
echo "❌ Failed to build XCFramework"
|
||||
exit 1
|
||||
if [[ ! -d "$OUTPUT_DIR/Gobackend.xcframework" ]]; then
|
||||
echo "Error: Gobackend.xcframework was not created." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "=== Build Complete ==="
|
||||
echo "Next steps:"
|
||||
echo "1. Open ios/Runner.xcworkspace in Xcode"
|
||||
echo "2. Add Gobackend.xcframework to the project"
|
||||
echo "3. Build and run the app"
|
||||
echo "Built $OUTPUT_DIR/Gobackend.xcframework"
|
||||
|
||||
Reference in New Issue
Block a user