Skip to content

Commit a40f035

Browse files
Merge branch 'dev' into Refactor_VideoDetailFragment
2 parents e4f9746 + aad5e26 commit a40f035

107 files changed

Lines changed: 1485 additions & 425 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: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ android {
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 **/
@@ -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
@@ -262,6 +262,7 @@ && isAutoplayEnabled()
262262
autoPlayEnabled = true; // forcefully start playing
263263
openVideoPlayerAutoFullscreen();
264264
}
265+
updateOverlayPlayQueueButtonVisibility();
265266
}
266267

267268
@Override
@@ -351,6 +352,8 @@ public void onResume() {
351352

352353
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
353354

355+
updateOverlayPlayQueueButtonVisibility();
356+
354357
setupBrightness();
355358

356359
if (tabSettingsChanged) {
@@ -610,19 +613,7 @@ protected void initViews(final View rootView, final Bundle savedInstanceState) {
610613
? View.VISIBLE
611614
: View.GONE
612615
);
613-
614-
if (DeviceUtils.isTv(getContext())) {
615-
// remove ripple effects from detail controls
616-
final int transparent = ContextCompat.getColor(requireContext(),
617-
R.color.transparent_background_color);
618-
binding.detailControlsPlaylistAppend.setBackgroundColor(transparent);
619-
binding.detailControlsBackground.setBackgroundColor(transparent);
620-
binding.detailControlsPopup.setBackgroundColor(transparent);
621-
binding.detailControlsDownload.setBackgroundColor(transparent);
622-
binding.detailControlsShare.setBackgroundColor(transparent);
623-
binding.detailControlsOpenInBrowser.setBackgroundColor(transparent);
624-
binding.detailControlsPlayWithKodi.setBackgroundColor(transparent);
625-
}
616+
accommodateForTvAndDesktopMode();
626617
}
627618

628619
@Override
@@ -1758,6 +1749,14 @@ public void onQueueUpdate(final PlayQueue queue) {
17581749
+ title + "], playQueue = [" + playQueue + "]");
17591750
}
17601751

1752+
// Register broadcast receiver to listen to playQueue changes
1753+
// and hide the overlayPlayQueueButton when the playQueue is empty / destroyed.
1754+
if (playQueue != null && playQueue.getBroadcastReceiver() != null) {
1755+
playQueue.getBroadcastReceiver().subscribe(
1756+
event -> updateOverlayPlayQueueButtonVisibility()
1757+
);
1758+
}
1759+
17611760
// This should be the only place where we push data to stack.
17621761
// It will allow to have live instance of PlayQueue with actual information about
17631762
// deleted/added items inside Channel/Playlist queue and makes possible to have
@@ -1864,6 +1863,7 @@ public void onServiceStopped() {
18641863
currentInfo.getUploaderName(),
18651864
currentInfo.getThumbnailUrl());
18661865
}
1866+
updateOverlayPlayQueueButtonVisibility();
18671867
}
18681868

18691869
@Override
@@ -2044,6 +2044,30 @@ private void setupBrightness() {
20442044
}
20452045
}
20462046

2047+
/**
2048+
* Make changes to the UI to accommodate for better usability on bigger screens such as TVs
2049+
* or in Android's desktop mode (DeX etc).
2050+
*/
2051+
private void accommodateForTvAndDesktopMode() {
2052+
if (DeviceUtils.isTv(getContext())) {
2053+
// remove ripple effects from detail controls
2054+
final int transparent = ContextCompat.getColor(requireContext(),
2055+
R.color.transparent_background_color);
2056+
binding.detailControlsPlaylistAppend.setBackgroundColor(transparent);
2057+
binding.detailControlsBackground.setBackgroundColor(transparent);
2058+
binding.detailControlsPopup.setBackgroundColor(transparent);
2059+
binding.detailControlsDownload.setBackgroundColor(transparent);
2060+
binding.detailControlsShare.setBackgroundColor(transparent);
2061+
binding.detailControlsOpenInBrowser.setBackgroundColor(transparent);
2062+
binding.detailControlsPlayWithKodi.setBackgroundColor(transparent);
2063+
}
2064+
if (DeviceUtils.isDesktopMode(getContext())) {
2065+
// Remove the "hover" overlay (since it is visible on all mouse events and interferes
2066+
// with the video content being played)
2067+
binding.detailThumbnailRootLayout.setForeground(null);
2068+
}
2069+
}
2070+
20472071
private void checkLandscape() {
20482072
if ((!player.isPlaying() && player.getPlayQueue() != playQueue)
20492073
|| player.getPlayQueue() == null) {
@@ -2330,6 +2354,18 @@ public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
23302354
});
23312355
}
23322356

2357+
private void updateOverlayPlayQueueButtonVisibility() {
2358+
final boolean isPlayQueueEmpty =
2359+
player == null // no player => no play queue :)
2360+
|| player.getPlayQueue() == null
2361+
|| player.getPlayQueue().isEmpty();
2362+
if (binding != null) {
2363+
// binding is null when rotating the device...
2364+
binding.overlayPlayQueueButton.setVisibility(
2365+
isPlayQueueEmpty ? View.GONE : View.VISIBLE);
2366+
}
2367+
}
2368+
23332369
private void updateOverlayData(@Nullable final String overlayTitle,
23342370
@Nullable final String uploader,
23352371
@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
}

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica
2727
private val listViewModeFlowable = listViewMode.distinctUntilChanged()
2828

2929
private val mutableStateLiveData = MutableLiveData<SubscriptionState>()
30-
private val mutableFeedGroupsLiveData = MutableLiveData<List<Group>>()
30+
private val mutableFeedGroupsLiveData = MutableLiveData<Pair<List<Group>, Boolean>>()
3131
val stateLiveData: LiveData<SubscriptionState> = mutableStateLiveData
32-
val feedGroupsLiveData: LiveData<List<Group>> = mutableFeedGroupsLiveData
32+
val feedGroupsLiveData: LiveData<Pair<List<Group>, Boolean>> = mutableFeedGroupsLiveData
3333

3434
private var feedGroupItemsDisposable = Flowable
3535
.combineLatest(
@@ -39,7 +39,10 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica
3939
)
4040
.throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS)
4141
.map { (feedGroups, listViewMode) ->
42-
feedGroups.map(if (listViewMode) ::FeedGroupCardItem else ::FeedGroupCardGridItem)
42+
Pair(
43+
feedGroups.map(if (listViewMode) ::FeedGroupCardItem else ::FeedGroupCardGridItem),
44+
listViewMode
45+
)
4346
}
4447
.subscribeOn(Schedulers.io())
4548
.subscribe(

0 commit comments

Comments
 (0)