Skip to content

Commit a798979

Browse files
Merge branch 'dev' into Refactor_VideoPlayerUi
2 parents e333197 + aad5e26 commit a798979

108 files changed

Lines changed: 1496 additions & 440 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,16 @@ plugins {
88
}
99

1010
android {
11-
compileSdk 31
11+
compileSdk 32
1212
namespace 'org.schabi.newpipe'
1313

1414
defaultConfig {
1515
applicationId "org.schabi.newpipe"
1616
resValue "string", "app_name", "NewPipe"
1717
minSdk 21
1818
targetSdk 29
19-
versionCode 990
20-
versionName "0.24.0"
19+
versionCode 991
20+
versionName "0.24.1"
2121

2222
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2323

@@ -187,7 +187,7 @@ dependencies {
187187
// name and the commit hash with the commit hash of the (pushed) commit you want to test
188188
// This works thanks to JitPack: https://jitpack.io/
189189
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
190-
implementation 'com.github.TeamNewPipe:NewPipeExtractor:9ffdd0948b2ecd82655f5ff2a3e127b2b7695d5b'
190+
implementation 'com.github.TeamNewPipe:NewPipeExtractor:eb07d70a2ce03bee3cc74fc33b2e4173e1c21436'
191191
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
192192

193193
/** Checkstyle **/
@@ -198,7 +198,7 @@ dependencies {
198198
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
199199

200200
/** AndroidX **/
201-
implementation 'androidx.appcompat:appcompat:1.4.2'
201+
implementation 'androidx.appcompat:appcompat:1.5.1'
202202
implementation 'androidx.cardview:cardview:1.0.0'
203203
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
204204
implementation 'androidx.core:core-ktx:1.8.0'
@@ -271,7 +271,7 @@ dependencies {
271271
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
272272

273273
// Date and time formatting
274-
implementation "org.ocpsoft.prettytime:prettytime:5.0.3.Final"
274+
implementation "org.ocpsoft.prettytime:prettytime:5.0.6.Final"
275275

276276
/** Debugging **/
277277
// Memory leak detection

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
<data android:pathPrefix="/channel/" />
154154
<data android:pathPrefix="/user/" />
155155
<data android:pathPrefix="/c/" />
156+
<data android:pathPrefix="/@" />
156157
<!-- playlist prefix -->
157158
<data android:pathPrefix="/playlist" />
158159
</intent-filter>

app/src/main/java/org/schabi/newpipe/NewVersionWorker.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.schabi.newpipe
22

3-
import android.app.PendingIntent
43
import android.content.Context
54
import android.content.Intent
65
import android.util.Log
@@ -18,6 +17,7 @@ import com.grack.nanojson.JsonParser
1817
import com.grack.nanojson.JsonParserException
1918
import org.schabi.newpipe.extractor.downloader.Response
2019
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
20+
import org.schabi.newpipe.util.PendingIntentCompat
2121
import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry
2222
import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired
2323
import org.schabi.newpipe.util.ReleaseVersionUtil.isReleaseApk
@@ -49,7 +49,7 @@ class NewVersionWorker(
4949
// A pending intent to open the apk location url in the browser.
5050
val intent = Intent(Intent.ACTION_VIEW, apkLocationUrl?.toUri())
5151
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
52-
val pendingIntent = PendingIntent.getActivity(app, 0, intent, 0)
52+
val pendingIntent = PendingIntentCompat.getActivity(app, 0, intent, 0)
5353
val channelId = app.getString(R.string.app_update_notification_channel_id)
5454
val notificationBuilder = NotificationCompat.Builder(app, channelId)
5555
.setSmallIcon(R.drawable.ic_newpipe_update)

app/src/main/java/org/schabi/newpipe/database/feed/dao/FeedDAO.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,10 @@ abstract class FeedDAO {
4848
ON s.uid = f.stream_id
4949
5050
LEFT JOIN feed_group_subscription_join fgs
51-
ON fgs.subscription_id = f.subscription_id
51+
ON (
52+
:groupId <> ${FeedGroupEntity.GROUP_ALL_ID}
53+
AND fgs.subscription_id = f.subscription_id
54+
)
5255
5356
WHERE (
5457
:groupId = ${FeedGroupEntity.GROUP_ALL_ID}

app/src/main/java/org/schabi/newpipe/error/ErrorUtil.kt

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import android.app.PendingIntent
55
import android.content.Context
66
import android.content.Intent
77
import android.graphics.Color
8-
import android.os.Build
98
import android.view.View
109
import android.widget.Toast
1110
import androidx.core.app.NotificationCompat
1211
import androidx.core.app.NotificationManagerCompat
1312
import androidx.fragment.app.Fragment
1413
import com.google.android.material.snackbar.Snackbar
1514
import org.schabi.newpipe.R
15+
import org.schabi.newpipe.util.PendingIntentCompat
1616

1717
/**
1818
* This class contains all of the methods that should be used to let the user know that an error has
@@ -104,11 +104,6 @@ class ErrorUtil {
104104
*/
105105
@JvmStatic
106106
fun createNotification(context: Context, errorInfo: ErrorInfo) {
107-
var pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT
108-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
109-
pendingIntentFlags = pendingIntentFlags or PendingIntent.FLAG_IMMUTABLE
110-
}
111-
112107
val notificationBuilder: NotificationCompat.Builder =
113108
NotificationCompat.Builder(
114109
context,
@@ -119,11 +114,11 @@ class ErrorUtil {
119114
.setContentText(context.getString(errorInfo.messageStringId))
120115
.setAutoCancel(true)
121116
.setContentIntent(
122-
PendingIntent.getActivity(
117+
PendingIntentCompat.getActivity(
123118
context,
124119
0,
125120
getErrorActivityIntent(context, errorInfo),
126-
pendingIntentFlags
121+
PendingIntent.FLAG_UPDATE_CURRENT
127122
)
128123
)
129124

app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ && isAutoplayEnabled()
248248
autoPlayEnabled = true; // forcefully start playing
249249
openVideoPlayerAutoFullscreen();
250250
}
251+
updateOverlayPlayQueueButtonVisibility();
251252
}
252253

253254
@Override
@@ -337,6 +338,8 @@ public void onResume() {
337338

338339
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
339340

341+
updateOverlayPlayQueueButtonVisibility();
342+
340343
setupBrightness();
341344

342345
if (tabSettingsChanged) {
@@ -639,19 +642,7 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) {
639642
? View.VISIBLE
640643
: View.GONE
641644
);
642-
643-
if (DeviceUtils.isTv(getContext())) {
644-
// remove ripple effects from detail controls
645-
final int transparent = ContextCompat.getColor(requireContext(),
646-
R.color.transparent_background_color);
647-
binding.detailControlsPlaylistAppend.setBackgroundColor(transparent);
648-
binding.detailControlsBackground.setBackgroundColor(transparent);
649-
binding.detailControlsPopup.setBackgroundColor(transparent);
650-
binding.detailControlsDownload.setBackgroundColor(transparent);
651-
binding.detailControlsShare.setBackgroundColor(transparent);
652-
binding.detailControlsOpenInBrowser.setBackgroundColor(transparent);
653-
binding.detailControlsPlayWithKodi.setBackgroundColor(transparent);
654-
}
645+
accommodateForTvAndDesktopMode();
655646
}
656647

657648
@Override
@@ -1820,6 +1811,14 @@ public void onQueueUpdate(final PlayQueue queue) {
18201811
+ title + "], playQueue = [" + playQueue + "]");
18211812
}
18221813

1814+
// Register broadcast receiver to listen to playQueue changes
1815+
// and hide the overlayPlayQueueButton when the playQueue is empty / destroyed.
1816+
if (playQueue != null && playQueue.getBroadcastReceiver() != null) {
1817+
playQueue.getBroadcastReceiver().subscribe(
1818+
event -> updateOverlayPlayQueueButtonVisibility()
1819+
);
1820+
}
1821+
18231822
// This should be the only place where we push data to stack.
18241823
// It will allow to have live instance of PlayQueue with actual information about
18251824
// deleted/added items inside Channel/Playlist queue and makes possible to have
@@ -1926,6 +1925,7 @@ public void onServiceStopped() {
19261925
currentInfo.getUploaderName(),
19271926
currentInfo.getThumbnailUrl());
19281927
}
1928+
updateOverlayPlayQueueButtonVisibility();
19291929
}
19301930

19311931
@Override
@@ -2106,6 +2106,30 @@ private void setupBrightness() {
21062106
}
21072107
}
21082108

2109+
/**
2110+
* Make changes to the UI to accommodate for better usability on bigger screens such as TVs
2111+
* or in Android's desktop mode (DeX etc).
2112+
*/
2113+
private void accommodateForTvAndDesktopMode() {
2114+
if (DeviceUtils.isTv(getContext())) {
2115+
// remove ripple effects from detail controls
2116+
final int transparent = ContextCompat.getColor(requireContext(),
2117+
R.color.transparent_background_color);
2118+
binding.detailControlsPlaylistAppend.setBackgroundColor(transparent);
2119+
binding.detailControlsBackground.setBackgroundColor(transparent);
2120+
binding.detailControlsPopup.setBackgroundColor(transparent);
2121+
binding.detailControlsDownload.setBackgroundColor(transparent);
2122+
binding.detailControlsShare.setBackgroundColor(transparent);
2123+
binding.detailControlsOpenInBrowser.setBackgroundColor(transparent);
2124+
binding.detailControlsPlayWithKodi.setBackgroundColor(transparent);
2125+
}
2126+
if (DeviceUtils.isDesktopMode(getContext())) {
2127+
// Remove the "hover" overlay (since it is visible on all mouse events and interferes
2128+
// with the video content being played)
2129+
binding.detailThumbnailRootLayout.setForeground(null);
2130+
}
2131+
}
2132+
21092133
private void checkLandscape() {
21102134
if ((!player.isPlaying() && player.getPlayQueue() != playQueue)
21112135
|| player.getPlayQueue() == null) {
@@ -2392,6 +2416,18 @@ public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
23922416
});
23932417
}
23942418

2419+
private void updateOverlayPlayQueueButtonVisibility() {
2420+
final boolean isPlayQueueEmpty =
2421+
player == null // no player => no play queue :)
2422+
|| player.getPlayQueue() == null
2423+
|| player.getPlayQueue().isEmpty();
2424+
if (binding != null) {
2425+
// binding is null when rotating the device...
2426+
binding.overlayPlayQueueButton.setVisibility(
2427+
isPlayQueueEmpty ? View.GONE : View.VISIBLE);
2428+
}
2429+
}
2430+
23952431
private void updateOverlayData(@Nullable final String overlayTitle,
23962432
@Nullable final String uploader,
23972433
@Nullable final String thumbnailUrl) {

app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package org.schabi.newpipe.local.feed.notifications
22

33
import android.app.NotificationManager
4-
import android.app.PendingIntent
54
import android.content.Context
65
import android.content.Intent
76
import android.graphics.Bitmap
@@ -20,6 +19,7 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem
2019
import org.schabi.newpipe.local.feed.service.FeedUpdateInfo
2120
import org.schabi.newpipe.util.Localization
2221
import org.schabi.newpipe.util.NavigationHelper
22+
import org.schabi.newpipe.util.PendingIntentCompat
2323
import org.schabi.newpipe.util.PicassoHelper
2424

2525
/**
@@ -70,16 +70,13 @@ class NotificationHelper(val context: Context) {
7070

7171
// open the channel page when clicking on the notification
7272
builder.setContentIntent(
73-
PendingIntent.getActivity(
73+
PendingIntentCompat.getActivity(
7474
context,
7575
data.pseudoId,
7676
NavigationHelper
7777
.getChannelIntent(context, data.listInfo.serviceId, data.listInfo.url)
7878
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
79-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
80-
PendingIntent.FLAG_IMMUTABLE
81-
else
82-
0
79+
0
8380
)
8481
)
8582

app/src/main/java/org/schabi/newpipe/local/feed/service/FeedLoadService.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package org.schabi.newpipe.local.feed.service
2121

22-
import android.app.PendingIntent
2322
import android.app.Service
2423
import android.content.BroadcastReceiver
2524
import android.content.Context
@@ -43,6 +42,7 @@ import org.schabi.newpipe.extractor.ListInfo
4342
import org.schabi.newpipe.extractor.stream.StreamInfoItem
4443
import org.schabi.newpipe.local.feed.service.FeedEventManager.Event.ErrorResultEvent
4544
import org.schabi.newpipe.local.feed.service.FeedEventManager.postEvent
45+
import org.schabi.newpipe.util.PendingIntentCompat
4646
import java.util.concurrent.TimeUnit
4747

4848
class FeedLoadService : Service() {
@@ -152,12 +152,8 @@ class FeedLoadService : Service() {
152152
private lateinit var notificationBuilder: NotificationCompat.Builder
153153

154154
private fun createNotification(): NotificationCompat.Builder {
155-
val cancelActionIntent = PendingIntent.getBroadcast(
156-
this,
157-
NOTIFICATION_ID,
158-
Intent(ACTION_CANCEL),
159-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) PendingIntent.FLAG_IMMUTABLE else 0
160-
)
155+
val cancelActionIntent =
156+
PendingIntentCompat.getBroadcast(this, NOTIFICATION_ID, Intent(ACTION_CANCEL), 0)
161157

162158
return NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
163159
.setOngoing(true)

app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import com.xwray.groupie.viewbinding.GroupieViewHolder
2727
import icepick.State
2828
import io.reactivex.rxjava3.disposables.CompositeDisposable
2929
import org.schabi.newpipe.R
30-
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
30+
import org.schabi.newpipe.database.feed.model.FeedGroupEntity.Companion.GROUP_ALL_ID
3131
import org.schabi.newpipe.databinding.DialogTitleBinding
3232
import org.schabi.newpipe.databinding.FeedItemCarouselBinding
3333
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
@@ -254,7 +254,11 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
254254

255255
viewModel = ViewModelProvider(this)[SubscriptionViewModel::class.java]
256256
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }
257-
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) }
257+
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) {
258+
it?.let { (groups, listViewMode) ->
259+
handleFeedGroups(groups, listViewMode)
260+
}
261+
}
258262

259263
setupInitialLayout()
260264
}
@@ -276,14 +280,8 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
276280
}
277281
}
278282
carouselAdapter.setOnItemLongClickListener { item, _ ->
279-
if ((
280-
item is FeedGroupCardItem &&
281-
item.groupId == FeedGroupEntity.GROUP_ALL_ID
282-
) ||
283-
(
284-
item is FeedGroupCardGridItem &&
285-
item.groupId == FeedGroupEntity.GROUP_ALL_ID
286-
)
283+
if ((item is FeedGroupCardItem && item.groupId == GROUP_ALL_ID) ||
284+
(item is FeedGroupCardGridItem && item.groupId == GROUP_ALL_ID)
287285
) {
288286
return@setOnItemLongClickListener false
289287
}
@@ -411,24 +409,22 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
411409
}
412410
}
413411

414-
private fun handleFeedGroups(groups: List<Group>) {
415-
val listViewMode = viewModel.getListViewMode()
416-
412+
private fun handleFeedGroups(groups: List<Group>, listViewMode: Boolean) {
417413
if (feedGroupsCarouselState != null) {
418414
feedGroupsCarousel.onRestoreInstanceState(feedGroupsCarouselState)
419415
feedGroupsCarouselState = null
420416
}
421417

422-
feedGroupsCarousel.listViewMode = listViewMode
423-
feedGroupsSortMenuItem.showSortButton = groups.size > 1
424-
feedGroupsSortMenuItem.listViewMode = listViewMode
425418
binding.itemsList.post {
426419
if (context == null) {
427420
// since this part was posted to the next UI cycle, the fragment might have been
428421
// removed in the meantime
429422
return@post
430423
}
431424

425+
feedGroupsCarousel.listViewMode = listViewMode
426+
feedGroupsSortMenuItem.showSortButton = groups.size > 1
427+
feedGroupsSortMenuItem.listViewMode = listViewMode
432428
feedGroupsCarousel.notifyChanged(FeedGroupCarouselItem.PAYLOAD_UPDATE_LIST_VIEW_MODE)
433429
feedGroupsSortMenuItem.notifyChanged(GroupsHeader.PAYLOAD_UPDATE_ICONS)
434430

@@ -437,10 +433,10 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
437433
clear()
438434
if (listViewMode) {
439435
add(FeedGroupAddNewItem())
440-
add(FeedGroupCardItem(-1, getString(R.string.all), FeedGroupIcon.RSS))
436+
add(FeedGroupCardItem(GROUP_ALL_ID, getString(R.string.all), FeedGroupIcon.RSS))
441437
} else {
442438
add(FeedGroupAddNewGridItem())
443-
add(FeedGroupCardGridItem(-1, getString(R.string.all), FeedGroupIcon.RSS))
439+
add(FeedGroupCardGridItem(GROUP_ALL_ID, getString(R.string.all), FeedGroupIcon.RSS))
444440
}
445441
addAll(groups)
446442
}

0 commit comments

Comments
 (0)