diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..d0cac42e --- /dev/null +++ b/.editorconfig @@ -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 diff --git a/.gitattributes b/.gitattributes index d080aebf..0b163738 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e37d4b5d..c3ab2444 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -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. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 62e1fb4b..01c108a8 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -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 diff --git a/.github/ISSUE_TEMPLATE/download_issue.yml b/.github/ISSUE_TEMPLATE/download_issue.yml index aa5973ef..5b017b85 100644 --- a/.github/ISSUE_TEMPLATE/download_issue.yml +++ b/.github/ISSUE_TEMPLATE/download_issue.yml @@ -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 diff --git a/.github/ISSUE_TEMPLATE/extension_feature_request.yml b/.github/ISSUE_TEMPLATE/extension_feature_request.yml index 8748a780..d8c52ed7 100644 --- a/.github/ISSUE_TEMPLATE/extension_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/extension_feature_request.yml @@ -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 diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 3f3268e8..21a1a2dc 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -50,7 +50,7 @@ body: options: - UI/UX Improvement - Download Feature - - New Service Integration + - Extension System/API - Metadata/Tagging - Performance - Settings/Configuration diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7dbcc05f..c1486114 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,27 +1,42 @@ -## Description +## Summary - + ## Related Issues - + ## 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 + -## 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 - +Validation notes: + + + +## 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 + + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de51f55e..8a799ec4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05648149..2b385681 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/.gitignore b/.gitignore index 2f2ff926..46cdb177 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 09080bd5..faac585f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a37a3d9..8067b528 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 { - @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.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/): - -``` -(): - -[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. diff --git a/README.md b/README.md index ff9ad5da..83c8b0d4 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@
-[![GitHub Release](https://img.shields.io/github/v/release/zarzet/SpotiFLAC-Mobile?style=for-the-badge&logo=github)](https://github.com/zarzet/SpotiFLAC-Mobile/releases) -[![VirusTotal](https://img.shields.io/badge/VirusTotal-Safe-brightgreen?style=for-the-badge&logo=virustotal)](https://www.virustotal.com/gui/file/31d1bf3c3b2015c13e83c4f909a7c6093a9423e3e702f0c582a3e0035c849424) +[![GitHub Release](https://img.shields.io/github/v/release/spotiflacapp/SpotiFLAC-Mobile?style=for-the-badge&logo=github)](https://github.com/spotiflacapp/SpotiFLAC-Mobile/releases) [![Crowdin](https://img.shields.io/badge/HELP%20TRANSLATE%20ON-CROWDIN-%2321252b?style=for-the-badge&logo=crowdin)](https://crowdin.com/project/spotiflac-mobile) [![Telegram Channel](https://img.shields.io/badge/CHANNEL-2CA5E0?style=for-the-badge&logo=telegram&logoColor=white)](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:// Why does the Store tab ask me to enter a URL?
-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. @@ -107,7 +121,9 @@ Yes! Just paste the playlist URL in the search bar. The app will fetch all track Why do I need to grant storage permission?
-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. @@ -115,7 +131,8 @@ The app needs permission to save downloaded files to your device. On Android 13+ Is this app safe?
-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. @@ -128,13 +145,13 @@ Some countries have restricted access to certain streaming service APIs. If down
-Can I add SpotiFLAC to AltStore or SideStore? +Can I add SpotiFLAC Mobile to AltStore or SideStore?
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
> [!NOTE] -> If SpotiFLAC is useful to you, consider supporting development: +> If SpotiFLAC Mobile is useful to you, consider supporting development: > > [![Ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](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! - - + + We also appreciate everyone who helped with [translations on Crowdin](https://crowdin.com/project/spotiflac-mobile), reported bugs, suggested features, and spread the word. diff --git a/apps.json b/apps.json index a6152f14..dc16be77 100644 --- a/apps.json +++ b/apps.json @@ -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 } ] diff --git a/cliff.toml b/cliff.toml index b5680d4b..aee623d3 100644 --- a/cliff.toml +++ b/cliff.toml @@ -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" diff --git a/l10n.yaml b/l10n.yaml index 21b47bec..9c003fae 100644 --- a/l10n.yaml +++ b/l10n.yaml @@ -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 diff --git a/lib/constants/app_info.dart b/lib/constants/app_info.dart index 28ea5d13..3666cb0f 100644 --- a/lib/constants/app_info.dart +++ b/lib/constants/app_info.dart @@ -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'; diff --git a/pubspec.yaml b/pubspec.yaml index bf354cf2..566b28da 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -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 diff --git a/scripts/build_ios.sh b/scripts/build_ios.sh index cb5ce68d..da1b40c6 100644 --- a/scripts/build_ios.sh +++ b/scripts/build_ios.sh @@ -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"