Skip to content

Compare fork progress with upstream, document remote access findings, and backport upstream improvements#4

Merged
R00S merged 331 commits intomasterfrom
copilot/compare-upstream-progress
Jan 12, 2026
Merged

Compare fork progress with upstream, document remote access findings, and backport upstream improvements#4
R00S merged 331 commits intomasterfrom
copilot/compare-upstream-progress

Conversation

Copy link
Copy Markdown

Copilot AI commented Jan 12, 2026

Upstream Backport & CI Fix Complete ✅

Completed Tasks

  • Compare fork with upstream
  • Create email drafts for upstream developer
  • Simplify emails per feedback
  • Backport upstream v2.8.7-beta+45 changes
  • Fix CI build failure with keystore signing

Recent Changes

CI Build Fix:
Fixed Android build failure caused by missing or invalid keystore secrets. The workflow now:

  • Only attempts to set up signing keystore if secrets are available
  • Falls back to debug signing when keystore is not configured
  • Shows informative message about signing method used

Error Fixed:

com.android.ide.common.signing.KeytoolException: Failed to read key from store 
"upload-keystore.jks": Tag number over 30 is not supported

This occurred because the workflow tried to decode and use keystore secrets that don't exist or are invalid in this fork. The build.gradle already handles this gracefully by falling back to debug signing when key.properties doesn't exist, but the workflow was creating an invalid keystore file.

Solution:

  • Added conditional if: ${{ secrets.KEYSTORE_BASE64 != '' }} to keystore setup step
  • Added informative note when signing with debug key
  • APK will now build successfully with debug signature for forks

Backport Summary

Successfully merged upstream v2.8.7-beta+45 (1366 commits) with remote access implementation preserved:

  • Version: 2.8.7-beta+45-remote-access
  • All upstream improvements integrated
  • Remote access code intact (7 files + 6 docs)
  • Dependencies: flutter_webrtc, mobile_scanner added back

Documents Created

  • EMAIL_DRAFT_CONCISE.md - Ready-to-send email (ASCII text)
  • EMAIL_TO_UPSTREAM.md - Extended version with technical details
  • COMPARISON_REPORT.md - Comprehensive analysis
  • README_COMPARISON.md - Usage guide

The fork now serves as an up-to-date reference implementation with all latest upstream features plus remote access code.

Original prompt

Do not change any code. Instead compare our progress compared to the upsteam progress in https://github.com/CollotsSpot/Ensemble.

If there is anything that could be useful for upsteam developers, compose an email (net super long and full of code and technical details) i can send to the developer with some useful information.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Your Name and others added 30 commits January 3, 2026 19:41
Adds _FastPageScrollPhysics to both library and search screens
to reduce the time PageView animations take to settle. This makes
vertical scrolling within tabs more responsive after swiping
horizontally between pages.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add 200ms delay before fetching fallback images to avoid
  network requests during fast scrolling
- Use dynamic image cache sizes based on view mode:
  - List view: 128px (smaller thumbnails)
  - 3-col grid: 200px
  - 2-col grid: 300px
- Increase ListView cacheExtent from 500px to 1000px to
  pre-build more offscreen items

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Parse radios from search API response
- Add radio filter tab to search screen
- Add radio tile with play functionality
- Add playingRadioStation localization

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Music Assistant search API doesn't return radios, so filter
from the provider's pre-loaded radioStations list instead.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add searchRadioStations() method that searches with media_types=['radio']
- Combine library radio filtering with global search results
- Deduplicate results by name, preferring library items

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add proper spacing between radio station items in list view
- Add grid view support (2-column and 3-column layouts)
- Add view mode toggle button functionality for radio tab
- Persist radio view mode preference in settings
- Add pull-to-refresh support
- Optimize image caching based on view mode

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add getPodcasts, getPodcastEpisodes, and playPodcastEpisode API methods
- Add podcast state (podcasts list, isLoadingPodcasts) to provider
- Replace "Coming soon" placeholder with functional podcasts tab
- Add list and grid view modes for podcasts (2-column and 3-column)
- Add view mode toggle support for podcasts
- Persist podcast view mode preference in settings
- Add localization strings for podcasts (noPodcasts, addPodcastsHint, episodes)
- Tapping a podcast shows placeholder message (details screen coming later)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create PodcastDetailScreen with podcast cover, title, author
- Load and display episode list with play functionality
- Add hero animations between library and details screens
- Add expandable description section
- Add podcastCover hero tag constant
- Pass imageUrl parameter to navigation for adaptive colors

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use CachedNetworkImageProvider for color extraction
- Change _formatDuration to accept Duration instead of int
- Replace non-existent podcastOff icon with microphoneOff
- Fix duration comparison to use Duration.zero

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Episodes:
- Add multiple fallback methods for fetching podcast episodes
- Try music/podcasts/get with various episode keys
- Try browse endpoint with podcast URI
- Try podcast_episodes library endpoint
- Add comprehensive debug logging

Images:
- Increase podcast image size from 512 to 1024
- Increase memory cache size for better quality

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Log browse item structure (keys, name, label, uri, path, media_type)
- Parse browse items with fallback for name/label fields
- Add URI logging to play method for debugging
- Better handling of browse response format

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Parse media_type string to MediaType enum properly
- Default to MediaType.track if parsing fails

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use the podcast's uri from API response instead of constructed path
- Filter out folder navigation items (like "..")
- Add _parseBrowseEpisodes helper method
- Include duration parsing for episodes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Check metadata for episodes array
- Use provider_mappings to fetch from source provider (Spotify)
- Log total_episodes and metadata keys for debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Found the actual API endpoint from Music Assistant documentation.
Simplified the code to use the proper endpoint.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add isPlayingPodcast getter to detect podcast episodes by URI pattern
- Add currentPodcastName getter to show podcast name instead of artist
- Use audiobook-style skip 30s controls for podcasts in expanded player
- Display podcast name in artist line instead of "Unknown Artist"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Hide album line for podcasts (was duplicating podcast name)
- Add debug logging to understand podcast data structure
- Helps diagnose why some podcasts show "Podcasts" fallback

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Log all currentMedia fields for podcast episodes
- Extract and store podcast field in metadata
- Add helper method for episode cover fallback
- Helps diagnose podcast name detection issues

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When podcast episode titles contain " - " (like "Show 73 - Mania for
Subjugation III"), the title was being split and "Show 73" became the
artist. The caching logic then kept the "existing" track thinking it
had better data, but this caused the album (podcast name) from the
player_updated event to be lost.

Fix: For podcast URIs, if the new track has album info but existing
doesn't, either prefer the new track or merge the album data into
the existing track. Also update _currentTrack when we have better
album data for podcasts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Music Assistant sometimes returns low-res images for podcasts. Added:
- Podcast cover cache populated with episode covers in background
- getPodcastImageUrl() method that checks cache first
- Library screen now uses getPodcastImageUrl for podcasts

Covers are loaded progressively after initial podcast list loads,
so the UI is not blocked while fetching episode data.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updated podcast_detail_screen.dart to use getPodcastImageUrl()
for both the cover display and color extraction.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace play icon with actual episode covers (72x72, rounded)
- Each episode can have its own unique cover art
- Add release date display alongside episode duration
- Long-press to expand episode showing full description
- Expanded state reveals action buttons: Play, Add to Queue, Play On...
- Add debug logging for episode metadata to discover date field names

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Previously we always overwrote podcast covers with episode covers,
which was wrong for podcasts where each episode has a unique cover.

Now we check if the podcast has its own image first and only fall
back to episode covers when the podcast itself has no cover image.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Compare podcast and episode image URLs to determine if they're the
same source image. If same source, use episode version for higher
quality. If different sources (unique episode covers), keep the
podcast's own cover to avoid incorrect artwork.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Episode list redesign:
- 72x72 episode covers (each can have unique artwork)
- Duration + release date on same line
- Long-press to expand: full description + action buttons
- Action buttons match album track style (44x44 icon-only)

Podcast cover quality fix:
- Fetch high-res artwork from iTunes API (1400x1400)
- Works for any podcast listed in iTunes (most podcasts)
- Correct podcast artwork, not episode covers
- Cached in background after podcast list loads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add searchPodcasts API method and include podcasts in search results
- Add podcast tile with navigation to podcast detail screen
- Add colored type pills to distinguish media types in "All" view:
  - Track (blue), Album (purple), Artist (pink), Playlist (teal)
  - Audiobook (orange), Radio (red), Podcast (green)
- Fix choppy hero animations for podcast covers by adding memCacheWidth/memCacheHeight constraints

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Your Name and others added 3 commits January 11, 2026 15:31
- Subscribe to queue_items_updated events from Music Assistant
- Add error handling with rollback for queue delete operations
- Add error handling with rollback for queue move operations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI and others added 2 commits January 12, 2026 18:49
Co-authored-by: R00S <1279537+R00S@users.noreply.github.com>
Co-authored-by: R00S <1279537+R00S@users.noreply.github.com>
Copilot AI changed the title [WIP] Compare progress with upstream repository Compare fork progress with upstream and document remote access findings Jan 12, 2026
Copilot AI requested a review from R00S January 12, 2026 18:51
@R00S
Copy link
Copy Markdown
Owner

R00S commented Jan 12, 2026

@copilot Shorter, ascii text only, no bold or bullets. Do not be so sure that remote audio is impossible, just tell that we didnt solve it with our method and abandoned it without trying other paths.

…sibility

Co-authored-by: R00S <1279537+R00S@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Jan 12, 2026

@copilot Shorter, ascii text only, no bold or bullets. Do not be so sure that remote audio is impossible, just tell that we didnt solve it with our method and abandoned it without trying other paths.

Done. Simplified both email drafts to ASCII text only, removed all bold and bullets, and changed language to reflect that audio playback wasn't achieved with the tried approach and was abandoned without exploring other paths. (commit 7637215)

@R00S
Copy link
Copy Markdown
Owner

R00S commented Jan 12, 2026

@copilot Now backpatch the changes from upsteam into our fork so that its easier for upsteam to use some of our code, if they want to.

Copy link
Copy Markdown
Author

Copilot AI commented Jan 12, 2026

@copilot Now backpatch the changes from upsteam into our fork so that its easier for upsteam to use some of our code, if they want to.

Done. Backported all upstream changes from v2.8.7-beta+45 (1366 commits) into the fork while preserving remote access implementation. The fork now has all latest upstream improvements plus the remote access code, making it much easier for upstream to review or cherry-pick the remote access files if interested. Version updated to 2.8.7-beta+45-remote-access. (commit 150709e)

Copilot AI changed the title Compare fork progress with upstream and document remote access findings Compare fork progress with upstream, document remote access findings, and backport upstream improvements Jan 12, 2026
@R00S
Copy link
Copy Markdown
Owner

R00S commented Jan 12, 2026

@copilot This will generate a JSON format file containing all messages that
need to be translated.
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 18376 bytes (98.9% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
Font asset "materialdesignicons-webfont.ttf" was tree-shaken, reducing it from 1279992 to 1034252 bytes (19.2% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
Caught exception: Already watching path: /home/runner/work/Ensemble---remote-access-testing/Ensemble---remote-access-testing/android

FAILURE: Build failed with an exception.

  • What went wrong:
    Execution failed for task ':app:packageRelease'.

A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
com.android.ide.common.signing.KeytoolException: Failed to read key from store "/home/runner/work/Ensemble---remote-access-testing/Ensemble---remote-access-testing/android/app/upload-keystore.jks": Tag number over 30 is not supported

  • Try:

Run with --stacktrace option to get the stack trace.
Run with --info or --debug option to get more log output.
Run with --scan to get full insights.

BUILD FAILED in 10m 5s
Running Gradle task 'assembleRelease'... 606.3s
Gradle task assembleRelease failed with exit code 1
Error: Process completed with exit code 1.

Co-authored-by: R00S <1279537+R00S@users.noreply.github.com>
Copy link
Copy Markdown
Author

Copilot AI commented Jan 12, 2026

@copilot This will generate a JSON format file containing all messages that
need to be translated.
Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 18376 bytes (98....

Fixed. The build was failing because the workflow tried to decode keystore secrets that don't exist in this fork, creating an invalid keystore file. Added conditional check to only setup signing if secrets are available - the build now falls back to debug signing when keystore is missing, which is normal for forks. (commit 41d24b6)

@R00S R00S marked this pull request as ready for review January 12, 2026 19:53
@R00S R00S merged commit 7930bcd into master Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants