New video page with media3 based player from pipepipex#46
Closed
InfinityLoop1308 wants to merge 14 commits into
Closed
New video page with media3 based player from pipepipex#46InfinityLoop1308 wants to merge 14 commits into
InfinityLoop1308 wants to merge 14 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces an experimental, opt-in (via “Use beta UI”) video detail page built with Jetpack Compose plus a new Media3-based playback stack, while preserving the existing (legacy) player path when the setting is disabled.
Changes:
- Adds a Compose-hosted video detail screen and a lightweight state/viewmodel layer to drive it.
- Introduces a new Media3
PlaybackService, controller abstraction, queue manager, and media source factory for extractor-backed playback. - Routes key playback/navigation entry points (main/background/popup/enqueue/timestamps) to the experimental stack when enabled.
Reviewed changes
Copilot reviewed 27 out of 27 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| app/src/main/res/layout/activity_main.xml | Adds a hidden ComposeView host for the experimental video detail UI. |
| app/src/main/java/project/pipepipe/app/viewmodel/VideoDetailViewModel.kt | New viewmodel-like state holder for experimental video detail navigation/loading. |
| app/src/main/java/project/pipepipe/app/uistate/VideoDetailUiState.kt | Defines experimental video detail UI state container. |
| app/src/main/java/project/pipepipe/app/uistate/VideoDetailPageState.kt | Defines page-state enum (hidden/bottom/detail/fullscreen). |
| app/src/main/java/project/pipepipe/app/ui/screens/videodetail/VideoDetailScreen.kt | Compose implementation of the experimental video detail + embedded PlayerView. |
| app/src/main/java/project/pipepipe/app/ui/ExperimentalVideoDetailHost.kt | Binds the Compose host to MainActivity and bridges navigation/back handling. |
| app/src/main/java/project/pipepipe/app/SharedContext.kt | Adds shared controller/queue/playback-mode plumbing for the experimental stack. |
| app/src/main/java/project/pipepipe/app/service/PlaybackService.kt | New Media3 MediaLibraryService hosting an ExoPlayer + session + popup manager. |
| app/src/main/java/project/pipepipe/app/QueueManager.kt | New queue state + shuffle/unshuffle + sync hooks to controller. |
| app/src/main/java/project/pipepipe/app/popup/PopupPlayerManager.kt | Media3-based popup player window manager integration. |
| app/src/main/java/project/pipepipe/app/PlaybackMode.kt | Experimental playback mode enum (video/audio/popup). |
| app/src/main/java/project/pipepipe/app/platform/PlatformMediaItem.kt | Platform-agnostic media item model for the experimental controller layer. |
| app/src/main/java/project/pipepipe/app/platform/PlatformMediaController.kt | Controller interface + playback/track selection abstractions for experimental stack. |
| app/src/main/java/project/pipepipe/app/platform/AndroidMediaController.kt | Media3-backed implementation of PlatformMediaController. |
| app/src/main/java/project/pipepipe/app/mediasource/StreamInfoRepository.kt | In-memory cache for extracted StreamInfo keyed by URL. |
| app/src/main/java/project/pipepipe/app/mediasource/MediaItemFactory.kt | Maps between extractor StreamInfo, platform items, and Media3 MediaItem. |
| app/src/main/java/project/pipepipe/app/mediasource/ExtractorMediaSourceFactory.kt | Media3 MediaSource.Factory that builds sources from extractor stream data. |
| app/src/main/java/project/pipepipe/app/LegacyPlayQueueAdapter.kt | Adapts legacy PlayQueue into the experimental platform item list. |
| app/src/main/java/project/pipepipe/app/ExperimentalPlaybackRouter.kt | Routes play/enqueue/seek actions to experimental service/controller stack. |
| app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java | Switches playback/detail navigation to experimental routing when enabled. |
| app/src/main/java/org/schabi/newpipe/util/MediaButtonReceiver.java | Disables legacy media-button receiver behavior when experimental UI is enabled. |
| app/src/main/java/org/schabi/newpipe/util/external_communication/TextLinkifier.java | Routes timestamp clicks to experimental seek when enabled. |
| app/src/main/java/org/schabi/newpipe/util/external_communication/InternalUrlsHandler.java | Routes internal timestamp URLs to experimental seek when enabled. |
| app/src/main/java/org/schabi/newpipe/util/CarConnectionStateReceiver.java | Stops the experimental service instead of legacy when experimental UI is enabled. |
| app/src/main/java/org/schabi/newpipe/MainActivity.java | Attaches the experimental Compose host and integrates experimental back handling. |
| app/src/main/AndroidManifest.xml | Registers the new experimental PlaybackService. |
| app/build.gradle | Adds Compose BOM usage and adds Media3 dependencies alongside legacy ExoPlayer deps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+7
to
+11
| import androidx.media3.exoplayer.ExoPlayer | ||
| import androidx.media3.session.MediaLibraryService | ||
| import androidx.media3.session.MediaSession | ||
| import androidx.preference.PreferenceManager | ||
| import project.pipepipe.app.SharedContext |
Comment on lines
+78
to
+86
| <service | ||
| android:name="project.pipepipe.app.service.PlaybackService" | ||
| android:exported="true" | ||
| android:foregroundServiceType="mediaPlayback"> | ||
| <intent-filter> | ||
| <action android:name="androidx.media3.session.MediaLibraryService" /> | ||
| <action android:name="android.media.browse.MediaBrowserService" /> | ||
| </intent-filter> | ||
| </service> |
|
|
||
| @JvmStatic | ||
| fun play(context: Context, queue: PlayQueue, mode: PlaybackMode, shuffle: Boolean) { | ||
| context.startService(Intent(context, PlaybackService::class.java)) |
|
|
||
| @JvmStatic | ||
| fun enqueue(context: Context, queue: PlayQueue, next: Boolean) { | ||
| context.startService(Intent(context, PlaybackService::class.java)) |
Comment on lines
+44
to
+53
| fun fromMediaItem(item: MediaItem): PlatformMediaItem = PlatformMediaItem( | ||
| mediaId = item.mediaId, | ||
| title = item.mediaMetadata.title?.toString(), | ||
| artist = item.mediaMetadata.artist?.toString(), | ||
| artworkUrl = item.mediaMetadata.artworkUri?.toString(), | ||
| durationMs = item.mediaMetadata.durationMs, | ||
| serviceId = item.mediaMetadata.extras?.getInt(KEY_SERVICE_ID), | ||
| uuid = item.mediaMetadata.extras?.getString(KEY_UUID) | ||
| ?: java.util.UUID.randomUUID().toString() | ||
| ) |
Comment on lines
+124
to
+130
| IconButton(onClick = { | ||
| val playbackController = controller ?: return@IconButton | ||
| if (playbackController.currentMediaItem.value?.mediaId != streamInfo.url) { | ||
| val item = MediaItemFactory.fromStreamInfo(streamInfo) | ||
| SharedContext.queueManager.setQueue(listOf(item)) | ||
| playbackController.prepare() | ||
| } |
Comment on lines
+32
to
+44
| runCatching { | ||
| withContext(Dispatchers.IO) { | ||
| ExtractorHelper.getStreamInfo(serviceId, url, false).blockingGet() | ||
| } | ||
| }.onSuccess { | ||
| MediaItemFactory.fromStreamInfo(it) | ||
| mutableUiState.value = mutableUiState.value.copy( | ||
| streamInfoStack = mutableUiState.value.streamInfoStack + it, | ||
| isLoading = false | ||
| ) | ||
| }.onFailure { | ||
| mutableUiState.value = mutableUiState.value.copy(isLoading = false, error = it) | ||
| } |
Comment on lines
+66
to
+73
| mutableQueue.value = mutableQueue.value.toMutableList().apply { | ||
| add(to, removeAt(from)) | ||
| } | ||
| backup?.let { | ||
| val item = it.removeAt(from) | ||
| it.add(to, item) | ||
| } | ||
| controller?.syncQueueMove(from, to) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(experimental) a very aggressive refactor, targeting to replace the whole player & mediaservice & videodetailfragement with there equivalents in ppx. still wip and waiting for codex 5 hour limit. haven't done any test.
issues of the current codebase:
doing the refactor can help simplify the codebase and remove tech debt. but the consideration here is: none of the reasons are essential enough.
I'll going to see if codex is able to achieve a roughly-work stage. if not it seems better to abort the pr and go #45
(below gen by codex)
Purpose
Introduce an experimental Media3 and Compose-based video detail/player implementation while
retaining the existing player as a fallback.
The existing Use beta UI setting selects the implementation:
This allows incremental migration and real-world testing before removing the legacy player.
Impact Scope
The legacy implementation remains unchanged and available when the beta UI setting is
disabled.
Completed
Added an independent top-level ComposeView host for the new video detail page.
Added a Media3 playback service, controller abstraction, shared playback state, and queue
manager.
Routed main player, background player, popup player, enqueue, enqueue-next, and shuffle
actions to Media3 when beta UI is enabled.
Prevented experimental playback paths from accidentally starting the legacy player.
Routed media buttons, timestamp links, and car connection events to the selected
implementation.
Added an initial Compose video detail page with:
Added a Media3 popup player while reusing the existing popup window behavior:
Added Media3 source handling for:
Fixed queue synchronization, shuffle behavior, enqueue-next ordering, and playback mode
switching.
Confirmed that assembleDebug builds successfully.
Not Yet Completed
Full video detail functionality:
Complete player controls:
Fullscreen behavior:
Popup playback control UI.
YouTube-specific Media3 HTTP handling for range/rn parameters and expired URL refresh.
NicoNico live WebSocket/HLS handling.
Complete notification, lock-screen control, Android Auto, service lifecycle, and process
restoration behavior.
Device-level playback regression testing for YouTube, BiliBili, and NicoNico.
Removal of the legacy player after the experimental implementation reaches feature parity.