Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions .github/workflows/build-release-apk.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,78 @@
name: "Build unsigned release APK on master"
name: "Build and Release APK"

on:
workflow_dispatch:
push:
branches:
- master
- main
- dev
tags:
- 'v*'

jobs:
release:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: 'master'

- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: 'gradle'

- name: "Create debug keystore for signing"
run: |
mkdir -p ~/.android
keytool -genkey -v -keystore ~/.android/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"

- name: "Build release APK"
run: ./gradlew assembleRelease --stacktrace

- name: "Rename APK"
- name: "Get version name"
id: version
run: |
VERSION_NAME="$(jq -r ".elements[0].versionName" "app/build/outputs/apk/release/output-metadata.json")"
echo "version=$VERSION_NAME" >> "$GITHUB_OUTPUT"
echo "Version name: $VERSION_NAME" >> "$GITHUB_STEP_SUMMARY"
echo '```json' >> "$GITHUB_STEP_SUMMARY"
cat "app/build/outputs/apk/release/output-metadata.json" >> "$GITHUB_STEP_SUMMARY"
echo >> "$GITHUB_STEP_SUMMARY"
echo '```' >> "$GITHUB_STEP_SUMMARY"
# assume there is only one APK in that folder
mv app/build/outputs/apk/release/*.apk "app/build/outputs/apk/release/NewPipe_v$VERSION_NAME.apk"

- name: "Upload APK"
- name: "Rename APK"
run: |
mv app/build/outputs/apk/release/*.apk "app/build/outputs/apk/release/NewPipeScrolling_v${{ steps.version.outputs.version }}.apk"

- name: "Upload APK as artifact"
uses: actions/upload-artifact@v4
with:
name: app
path: app/build/outputs/apk/release/*.apk

- name: "Create Release"
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.version.outputs.version }}-${{ github.run_number }}
name: NewPipe Scrolling v${{ steps.version.outputs.version }}
body: |
## NewPipe Scrolling v${{ steps.version.outputs.version }}

This is a modified version of NewPipe that can be installed alongside the original app.

### New Features
- **Hold to Fast-Forward**: Hold anywhere on the player to increase playback speed to 2x. Release to return to normal speed.
- New setting in Video & Audio settings to enable/disable this feature.

### Installation
1. Download the APK below
2. Install on your Android device (enable "Install from unknown sources" if needed)
3. This app will appear as "NewPipe Scrolling" and can coexist with the original NewPipe
files: app/build/outputs/apk/release/*.apk
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 changes: 14 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,19 @@ android {
compileSdk = 36
namespace = "org.schabi.newpipe"

signingConfigs {
create("release") {
// Use debug keystore for unsigned releases that can be installed
storeFile = file("${System.getProperty("user.home")}/.android/debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
}
}

defaultConfig {
applicationId = "org.schabi.newpipe"
resValue("string", "app_name", "NewPipe")
applicationId = "org.schabi.newpipe.scrolling"
resValue("string", "app_name", "NewPipe Scrolling")
minSdk = 21
targetSdk = 35

Expand Down Expand Up @@ -72,9 +82,10 @@ android {
}

release {
signingConfig = signingConfigs.getByName("release")
System.getProperty("packageSuffix")?.let { suffix ->
applicationIdSuffix = suffix
resValue("string", "app_name", "NewPipe $suffix")
resValue("string", "app_name", "NewPipe Scrolling $suffix")
}
isMinifyEnabled = true
isShrinkResources = false // disabled to fix F-Droid"s reproducible build
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import android.view.View
import androidx.core.os.postDelayed
import org.schabi.newpipe.databinding.PlayerBinding
import org.schabi.newpipe.player.Player
import org.schabi.newpipe.player.helper.PlayerHelper
import org.schabi.newpipe.player.ui.VideoPlayerUi

/**
Expand All @@ -24,8 +25,59 @@ abstract class BasePlayerGestureListener(
protected val player: Player = playerUi.player
protected val binding: PlayerBinding = playerUi.binding

// ///////////////////////////////////////////////////////////////////
// Long press (hold) to fast-forward
// ///////////////////////////////////////////////////////////////////

private var isHoldingForFastForward = false
private var originalPlaybackSpeed = 1.0f
private val longPressHandler: Handler = Handler(Looper.getMainLooper())
private val longPressRunnable = Runnable {
if (PlayerHelper.isHoldToFastForwardEnabled(player.context) &&
player.currentState == Player.STATE_PLAYING &&
!playerUi.isSomePopupMenuVisible
) {
startFastForward()
}
}

private fun startFastForward() {
if (!isHoldingForFastForward) {
if (DEBUG) {
Log.d(TAG, "startFastForward called")
}
isHoldingForFastForward = true
originalPlaybackSpeed = player.playbackSpeed
player.setPlaybackSpeed(2.0f)
}
}

private fun stopFastForward() {
if (isHoldingForFastForward) {
if (DEBUG) {
Log.d(TAG, "stopFastForward called, restoring speed to $originalPlaybackSpeed")
}
isHoldingForFastForward = false
player.setPlaybackSpeed(originalPlaybackSpeed)
}
longPressHandler.removeCallbacks(longPressRunnable)
}

override fun onTouch(v: View, event: MotionEvent): Boolean {
playerUi.gestureDetector.onTouchEvent(event)

// Handle long press for fast-forward
when (event.action) {
MotionEvent.ACTION_DOWN -> {
// Start timer for long press detection
longPressHandler.postDelayed(longPressRunnable, LONG_PRESS_DELAY)
}
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
// Stop fast-forward when finger is lifted
stopFastForward()
}
}

return false
}

Expand Down Expand Up @@ -184,5 +236,6 @@ abstract class BasePlayerGestureListener(

private const val DOUBLE_TAP = "doubleTap"
private const val DOUBLE_TAP_DELAY = 550L
private const val LONG_PRESS_DELAY = 500L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,11 @@ public static boolean isStartMainPlayerFullscreenEnabled(@NonNull final Context
.getBoolean(context.getString(R.string.start_main_player_fullscreen_key), false);
}

public static boolean isHoldToFastForwardEnabled(@NonNull final Context context) {
return getPreferences(context)
.getBoolean(context.getString(R.string.hold_to_fast_forward_key), true);
}

public static boolean isAutoQueueEnabled(@NonNull final Context context) {
return getPreferences(context)
.getBoolean(context.getString(R.string.auto_queue_key), false);
Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/settings_keys.xml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<string name="screen_brightness_timestamp_key">screen_brightness_timestamp_key</string>
<string name="clear_queue_confirmation_key">clear_queue_confirmation_key</string>
<string name="ignore_hardware_media_buttons_key">ignore_hardware_media_buttons_key</string>
<string name="hold_to_fast_forward_key">hold_to_fast_forward_key</string>

<string name="popup_saved_width_key">popup_saved_width</string>
<string name="popup_saved_x_key">popup_saved_x</string>
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
<string name="clear_queue_confirmation_description">The active player queue will be replaced</string>
<string name="ignore_hardware_media_buttons_title">Ignore hardware media button events</string>
<string name="ignore_hardware_media_buttons_summary">Useful, for instance, if you are using a headset with broken physical buttons</string>
<string name="hold_to_fast_forward_title">Hold to fast-forward</string>
<string name="hold_to_fast_forward_summary">Hold anywhere on the player to increase playback speed to 2x. Release to return to normal speed</string>
<string name="show_comments_title">Show comments</string>
<string name="show_comments_summary">Turn off to hide comments</string>
<string name="show_next_and_similar_title">Show \'Next\' and \'Similar\' videos</string>
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/res/xml/video_audio_settings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -249,5 +249,13 @@
android:title="@string/ignore_hardware_media_buttons_title"
app:singleLineTitle="false"
app:iconSpaceReserved="false" />

<SwitchPreferenceCompat
android:defaultValue="true"
android:key="@string/hold_to_fast_forward_key"
android:summary="@string/hold_to_fast_forward_summary"
android:title="@string/hold_to_fast_forward_title"
app:singleLineTitle="false"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>