Skip to content

Keep current player when clicking on timestamp#12254

Merged
Stypox merged 17 commits intodevfrom
timestamp-keep-current-player
Sep 6, 2025
Merged

Keep current player when clicking on timestamp#12254
Stypox merged 17 commits intodevfrom
timestamp-keep-current-player

Conversation

@Profpatsch
Copy link
Contributor

@Profpatsch Profpatsch commented May 5, 2025

one extra commit on top of #12252

What is it?

  • Bugfix (user facing)
  • Feature (user facing)
  • Codebase improvement (dev facing)
  • Meta improvement to the project (dev facing)

Description of the changes in your PR

Makes the player stay the same when a timestamp is pressed instead of always opening the popup player.

Before/After Screenshots/Screen Record

  • Before:
newpipe_timestamp_always_opens_popup_player.mp4
  • After:
newpipe_player_timestamp_stays_the_same.mp4

Fixes the following issue(s)

Relies on the following changes

#12252

APK testing

The APK can be found by going to the "Checks" tab below the title. On the left pane, click on "CI", scroll down to "artifacts" and click "app" to download the zip file which contains the debug APK of this PR. You can find more info and a video demonstration on this wiki page.

Due diligence

@github-actions github-actions bot added the size/large PRs with less than 750 changed lines label May 5, 2025
@Profpatsch Profpatsch changed the title Timestamp keep current player Keep current player when clicking on timestamp May 5, 2025
@Profpatsch Profpatsch changed the base branch from master to dev May 5, 2025 19:15
@Profpatsch Profpatsch force-pushed the timestamp-keep-current-player branch 2 times, most recently from 24c2560 to 61432a2 Compare May 6, 2025 08:28
@sonarqubecloud
Copy link

sonarqubecloud bot commented May 6, 2025

@ShareASmile ShareASmile added feature request Issue is related to a feature in the app player Issues related to any player (main, popup and background) labels May 11, 2025
Comment on lines +10 to +16
@Parcelize
enum class PlayerIntentType : Parcelable {
Enqueue,
EnqueueNext,
TimestampChange,
AllOthers
}
Copy link
Member

@Isira-Seneviratne Isira-Seneviratne Jul 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enums are serializable, so they can be passed to/retrieved from intents/bundles as serializable objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what’s the difference? I don’t see any.

Copy link
Member

@Isira-Seneviratne Isira-Seneviratne Sep 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some suggestions with the relevant changes, so the Parcelable implementation can be removed for this enum.

Copy link
Member

@Isira-Seneviratne Isira-Seneviratne Sep 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@Parcelize
enum class PlayerIntentType : Parcelable {
Enqueue,
EnqueueNext,
TimestampChange,
AllOthers
}
enum class PlayerIntentType {
Enqueue,
EnqueueNext,
TimestampChange,
AllOthers
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but why? I don’t see a big difference and like Parcellable more than Serializable

// by long pressing the video detail fragment, playlist or channel controls
return getPlayerIntent(context, targetClazz, playQueue, false)
.putExtra(Player.ENQUEUE, true);
intent.putExtra(Player.PLAYER_INTENT_TYPE, (Parcelable) PlayerIntentType.TimestampChange);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
intent.putExtra(Player.PLAYER_INTENT_TYPE, (Parcelable) PlayerIntentType.TimestampChange);
intent.putExtra(Player.PLAYER_INTENT_TYPE, PlayerIntentType.TimestampChange);

final String queueCache = intent.getStringExtra(PLAY_QUEUE_KEY);
if (queueCache == null) {

final PlayerIntentType playerIntentType = intent.getParcelableExtra(PLAYER_INTENT_TYPE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
final PlayerIntentType playerIntentType = intent.getParcelableExtra(PLAYER_INTENT_TYPE);
final var playerIntentType = IntentCompat.getSerializableExtra(intent, PLAYER_INTENT_TYPE, PlayerIntentType.class);

return;
}
case TimestampChange -> {
final TimestampChangeData dat = intent.getParcelableExtra(PLAYER_INTENT_DATA);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
final TimestampChangeData dat = intent.getParcelableExtra(PLAYER_INTENT_DATA);
final var dat = IntentCompat.getParcelableExtra(intent, PLAYER_INTENT_DATA, TimestampChangeData.class);

@Profpatsch Profpatsch force-pushed the timestamp-keep-current-player branch from 61432a2 to 2e92fb1 Compare September 5, 2025 14:56
The only use of the key was removed in commit
2a2c82e
but the handling logic stayed around. So let’s get rid of it.
@Profpatsch Profpatsch force-pushed the timestamp-keep-current-player branch 2 times, most recently from cf966a7 to 0485817 Compare September 5, 2025 17:04
Funnily enough, I’m pretty sure that whole comment will be not
necessary, because we never check `resumePlayback` on handling the
intent anyway.
Okay, so this is the … only? branch in this if-chain that will
conditionally fire if `playQueue` *is* `null`, sometimes.

This is why the unconditional `initPlayback` in `else` is not passed a
`null` in many cases … because `RESUME_PLAYBACK` is `true` and
`playQueue` is `null`.

It’s gonna be hard to figure out which parts of that are intentional,
I say.
We can do this, because:

1. if `playQueue` is not null, we return early
2. if `playQueue` is null and we need to enqueue:
  - the only “proper” case that could be triggered is
    the `RESUME_PLAYBACK` case, which is never `true` for the queuing
    intents, see the comment in `NavigationHelper.enqueueOnPlayer`
  - the generic `else` case is degenerate, because it would crash on
  `playQueue` being `null`.

This makes some sense, because there is no way to trigger the
enqueueing logic via the UI currently if there is no video playing
yet, in which case `playQueue` is not `null`.

So we need to transform this whole if desaster into a big switch.
The goal here is to convert all player intents to use a single enum
with extra data for each case. The queue ones are pretty easy, they
don’t carry any extra data. We fall through for everything else for
now.
They are just read from the player preferences and don’t influence the
branching, no need to read them in the intent parsing logic.
Instead of implicitely reconstructing whether the intent was
intended (lol) to be a timestamp change, we create a new kind of
intent that *only* sets the data we need to switch to a new timestamp.

This means that the logic of what to do (opening a popup player) gets
moved from `InternalUrlsHandler.playOnPopup` to the
`Player.handleIntent` method, we only pass that we want to jump to a
new timestamp. Thus, the stream is now loaded *after* sending the
intent instead of before sending.

This is somewhat messy right now and still does not fix the issue of
queue deletion, but from now on the queue logic should get more
straightforward to implement.

In the end, everything should be a giant switch. Thus we don’t
fall-through anymore, but run the post-setup code manually by calling
`handeIntentPost` and then returning.
Fixes #11013

We finally are at the point where we can have good logic around
clicking on timestamps.

This is pretty straightforward:

1) if we are already playing the stream (usual case), we skip to the
   correct second directly
2) If we don’t have a queue yet, create a trivial one with the stream
3) If we have a queue, we insert the video as next item and start
  playing it.

The skipping logic in 1) is similar to the one further down in the old
optimization block, but will always correctly fire for timestamps now.
I copied it because it’s not quite the same code, and moving into a
separate method at this stage would complicate the code too much.
In 063dcd4 I falsely claimed that the
fallthrough case is always degenerate, but it kinda somehow still
worked because if you long-click on e.g. the popup button, it would
call enqueue, but if nothing was running yet it would fallthrough to
the very last case and start the player with the video.

So let’s return to that and add a TODO for further refactoring in the
future.
We always need to handleIntentPost otherwise the VideoDetailFragment
is not setup correctly.
@Profpatsch Profpatsch force-pushed the timestamp-keep-current-player branch from 0485817 to 2937943 Compare September 6, 2025 13:33
This was always a bit weird, that clicking a timestamp would
unconditionally switch to the popup player.

With the new enum, it’s trivial to change it to always stay at the
selected player now ;)
@Profpatsch Profpatsch force-pushed the timestamp-keep-current-player branch from 2937943 to 1723bf0 Compare September 6, 2025 15:40
Copy link
Member

@Stypox Stypox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging this which includes #12252; I had left review comments there which have then been solved.

@Stypox Stypox enabled auto-merge September 6, 2025 15:43
@Stypox Stypox disabled auto-merge September 6, 2025 15:51
@Stypox Stypox merged commit 803aba4 into dev Sep 6, 2025
5 checks passed
@TobiGr TobiGr deleted the timestamp-keep-current-player branch September 7, 2025 19:20
@TobiGr TobiGr mentioned this pull request Dec 21, 2025
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request Issue is related to a feature in the app player Issues related to any player (main, popup and background) size/large PRs with less than 750 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Change timestamp behavior to seek in the same player when timestamp is pressed instead of always opening in popup player

4 participants