Skip to content

Commit 0b8b7d3

Browse files
committed
Show loading when action takes some time
Convert RxJava3 calls to suspend functions, sometimes requiring .await() to bridge between the two Also migrate play queue items' popup menu to new long press menu Also do centralized error handling
1 parent fd7cd9e commit 0b8b7d3

15 files changed

Lines changed: 375 additions & 369 deletions

File tree

app/src/main/java/org/schabi/newpipe/QueueItemMenuUtil.java

Lines changed: 0 additions & 94 deletions
This file was deleted.

app/src/main/java/org/schabi/newpipe/RouterActivity.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -823,15 +823,15 @@ private void openAddToPlaylistDialog(final int currentServiceId, final String cu
823823
.compose(this::pleaseWait)
824824
.subscribe(
825825
info -> getActivityContext().ifPresent(context ->
826-
PlaylistDialog.createCorrespondingDialog(context,
827-
List.of(new StreamEntity(info)),
828-
playlistDialog -> runOnVisible(ctx -> {
829-
// dismiss listener to be handled by FragmentManager
830-
final FragmentManager fm =
831-
ctx.getSupportFragmentManager();
832-
playlistDialog.show(fm, "addToPlaylistDialog");
833-
})
834-
)),
826+
disposables.add(
827+
PlaylistDialog.createCorrespondingDialog(context,
828+
List.of(new StreamEntity(info)))
829+
.subscribe(dialog -> runOnVisible(ctx -> {
830+
// dismiss listener to be handled by FragmentManager
831+
final FragmentManager fm =
832+
ctx.getSupportFragmentManager();
833+
dialog.show(fm, "addToPlaylistDialog");
834+
})))),
835835
throwable -> runOnVisible(ctx -> handleError(ctx, new ErrorInfo(
836836
throwable, UserAction.REQUESTED_STREAM,
837837
"Tried to add " + currentUrl + " to a playlist",

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ enum class UserAction(val message: String) {
3737
PREFERENCES_MIGRATION("migration of preferences"),
3838
SHARE_TO_NEWPIPE("share to newpipe"),
3939
CHECK_FOR_NEW_APP_VERSION("check for new app version"),
40-
OPEN_INFO_ITEM_DIALOG("open info item dialog"),
4140
GETTING_MAIN_SCREEN_TAB("getting main screen tab"),
4241
PLAY_ON_POPUP("play on popup"),
43-
SUBSCRIPTIONS("loading subscriptions")
42+
SUBSCRIPTIONS("loading subscriptions"),
43+
LONG_PRESS_MENU_ACTION("long press menu action"),
4444
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ class VideoDetailFragment :
439439
PlaylistDialog.createCorrespondingDialog(
440440
requireContext(),
441441
listOf(StreamEntity(info))
442-
) { dialog -> dialog.show(getParentFragmentManager(), TAG) }
442+
).subscribe { dialog -> dialog.show(getParentFragmentManager(), TAG) }
443443
)
444444
}
445445
}

app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -237,15 +237,15 @@ public boolean onOptionsItemSelected(final MenuItem item) {
237237
break;
238238
case R.id.menu_item_append_playlist:
239239
if (currentInfo != null) {
240-
disposables.add(PlaylistDialog.createCorrespondingDialog(
241-
getContext(),
242-
getPlayQueue()
243-
.getStreams()
244-
.stream()
245-
.map(StreamEntity::new)
246-
.collect(Collectors.toList()),
247-
dialog -> dialog.show(getFM(), TAG)
248-
));
240+
disposables.add(
241+
PlaylistDialog.createCorrespondingDialog(
242+
getContext(),
243+
getPlayQueue()
244+
.getStreams()
245+
.stream()
246+
.map(StreamEntity::new)
247+
.collect(Collectors.toList())
248+
).subscribe(dialog -> dialog.show(getFM(), TAG)));
249249
}
250250
break;
251251
default:

app/src/main/java/org/schabi/newpipe/local/dialog/PlaylistDialog.java

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
import java.util.List;
2121
import java.util.Objects;
2222
import java.util.Queue;
23-
import java.util.function.Consumer;
2423
import java.util.stream.Collectors;
2524
import java.util.stream.Stream;
2625

2726
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
27+
import io.reactivex.rxjava3.core.Maybe;
2828
import io.reactivex.rxjava3.disposables.Disposable;
2929

3030
public abstract class PlaylistDialog extends DialogFragment implements StateSaver.WriteRead {
@@ -135,22 +135,18 @@ protected void setStreamEntities(final List<StreamEntity> streamEntities) {
135135
*
136136
* @param context context used for accessing the database
137137
* @param streamEntities used for crating the dialog
138-
* @param onExec execution that should occur after a dialog got created, e.g. showing it
139-
* @return the disposable that was created
138+
* @return the {@link Maybe} to subscribe to to obtain the correct {@link PlaylistDialog}
140139
*/
141-
public static Disposable createCorrespondingDialog(
140+
public static Maybe<PlaylistDialog> createCorrespondingDialog(
142141
final Context context,
143-
final List<StreamEntity> streamEntities,
144-
final Consumer<PlaylistDialog> onExec) {
142+
final List<StreamEntity> streamEntities) {
145143

146144
return new LocalPlaylistManager(NewPipeDatabase.getInstance(context))
147145
.hasPlaylists()
148-
.observeOn(AndroidSchedulers.mainThread())
149-
.subscribe(hasPlaylists ->
150-
onExec.accept(hasPlaylists
151-
? PlaylistAppendDialog.newInstance(streamEntities)
152-
: PlaylistCreationDialog.newInstance(streamEntities))
153-
);
146+
.map(hasPlaylists -> hasPlaylists
147+
? PlaylistAppendDialog.newInstance(streamEntities)
148+
: PlaylistCreationDialog.newInstance(streamEntities))
149+
.observeOn(AndroidSchedulers.mainThread());
154150
}
155151

156152
/**
@@ -175,7 +171,7 @@ public static Disposable showForPlayQueue(
175171
return Disposable.empty();
176172
}
177173

178-
return PlaylistDialog.createCorrespondingDialog(player.getContext(), streamEntities,
179-
dialog -> dialog.show(fragmentManager, "PlaylistDialog"));
174+
return PlaylistDialog.createCorrespondingDialog(player.getContext(), streamEntities)
175+
.subscribe(dialog -> dialog.show(fragmentManager, "PlaylistDialog"));
180176
}
181177
}

app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package org.schabi.newpipe.player;
22

3-
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
43
import static org.schabi.newpipe.player.helper.PlayerHelper.formatSpeed;
4+
import static org.schabi.newpipe.ui.components.menu.LongPressMenuKt.openLongPressMenuInActivity;
55

66
import android.content.ComponentName;
77
import android.content.Intent;
@@ -41,6 +41,8 @@
4141
import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder;
4242
import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
4343
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
44+
import org.schabi.newpipe.ui.components.menu.LongPressAction;
45+
import org.schabi.newpipe.ui.components.menu.LongPressable;
4446
import org.schabi.newpipe.util.Localization;
4547
import org.schabi.newpipe.util.NavigationHelper;
4648
import org.schabi.newpipe.util.PermissionHelper;
@@ -328,8 +330,11 @@ public void selected(final PlayQueueItem item, final View view) {
328330
@Override
329331
public void held(final PlayQueueItem item, final View view) {
330332
if (player != null && player.getPlayQueue().indexOf(item) != -1) {
331-
openPopupMenu(player.getPlayQueue(), item, view, false,
332-
getSupportFragmentManager(), PlayQueueActivity.this);
333+
openLongPressMenuInActivity(
334+
PlayQueueActivity.this,
335+
LongPressable.fromPlayQueueItem(item),
336+
LongPressAction.fromPlayQueueItem(item, player.getPlayQueue(), true)
337+
);
333338
}
334339
}
335340

app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ class PlayQueueItem private constructor(
6565
.subscribeOn(Schedulers.io())
6666
.doOnError { throwable -> error = throwable }
6767

68+
fun toStreamInfoItem(): StreamInfoItem {
69+
val item = StreamInfoItem(serviceId, url, title, streamType)
70+
item.duration = duration
71+
item.thumbnails = thumbnails
72+
item.uploaderName = uploader
73+
item.uploaderUrl = uploaderUrl
74+
return item
75+
}
76+
6877
override fun equals(o: Any?) = o is PlayQueueItem && serviceId == o.serviceId && url == o.url
6978

7079
override fun hashCode() = Objects.hash(url, serviceId)

app/src/main/java/org/schabi/newpipe/player/ui/MainPlayerUi.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
44
import static org.schabi.newpipe.MainActivity.DEBUG;
5-
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
65
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
76
import static org.schabi.newpipe.ktx.ViewUtils.animate;
87
import static org.schabi.newpipe.player.Player.STATE_COMPLETED;
@@ -14,6 +13,7 @@
1413
import static org.schabi.newpipe.player.helper.PlayerHelper.getTimeString;
1514
import static org.schabi.newpipe.player.helper.PlayerHelper.globalScreenOrientationLocked;
1615
import static org.schabi.newpipe.player.notification.NotificationConstants.ACTION_PLAY_PAUSE;
16+
import static org.schabi.newpipe.ui.components.menu.LongPressMenuKt.openLongPressMenuInActivity;
1717

1818
import android.app.Activity;
1919
import android.content.Context;
@@ -68,6 +68,8 @@
6868
import org.schabi.newpipe.player.playqueue.PlayQueueItemBuilder;
6969
import org.schabi.newpipe.player.playqueue.PlayQueueItemHolder;
7070
import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
71+
import org.schabi.newpipe.ui.components.menu.LongPressAction;
72+
import org.schabi.newpipe.ui.components.menu.LongPressable;
7173
import org.schabi.newpipe.util.DeviceUtils;
7274
import org.schabi.newpipe.util.NavigationHelper;
7375
import org.schabi.newpipe.util.external_communication.KoreUtils;
@@ -795,8 +797,11 @@ public void held(final PlayQueueItem item, final View view) {
795797
@Nullable final PlayQueue playQueue = player.getPlayQueue();
796798
@Nullable final AppCompatActivity parentActivity = getParentActivity().orElse(null);
797799
if (playQueue != null && parentActivity != null && playQueue.indexOf(item) != -1) {
798-
openPopupMenu(player.getPlayQueue(), item, view, true,
799-
parentActivity.getSupportFragmentManager(), context);
800+
openLongPressMenuInActivity(
801+
parentActivity,
802+
LongPressable.fromPlayQueueItem(item),
803+
LongPressAction.fromPlayQueueItem(item, playQueue, false)
804+
);
800805
}
801806
}
802807

app/src/main/java/org/schabi/newpipe/ui/DetectDragModifier.kt renamed to app/src/main/java/org/schabi/newpipe/ui/GestureModifiers.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import androidx.compose.foundation.gestures.awaitEachGesture
55
import androidx.compose.foundation.gestures.awaitFirstDown
66
import androidx.compose.ui.Modifier
77
import androidx.compose.ui.geometry.Offset
8+
import androidx.compose.ui.input.pointer.PointerEventPass
89
import androidx.compose.ui.input.pointer.PointerEventTimeoutCancellationException
10+
import androidx.compose.ui.input.pointer.PointerInputChange
911
import androidx.compose.ui.input.pointer.changedToUp
1012
import androidx.compose.ui.input.pointer.isOutOfBounds
1113
import androidx.compose.ui.input.pointer.pointerInput
@@ -87,3 +89,22 @@ fun Modifier.detectDragGestures(
8789
}
8890

8991
private fun Offset.toIntOffset() = IntOffset(this.x.toInt(), this.y.toInt())
92+
93+
/**
94+
* Discards all touches on child composables. See https://stackoverflow.com/a/69146178.
95+
* @param doDiscard whether this Modifier is active (touches discarded) or not (no effect).
96+
*/
97+
fun Modifier.discardAllTouchesIf(doDiscard: Boolean) = if (doDiscard) {
98+
pointerInput(Unit) {
99+
awaitPointerEventScope {
100+
// we should wait for all new pointer events
101+
while (true) {
102+
awaitPointerEvent(pass = PointerEventPass.Initial)
103+
.changes
104+
.forEach(PointerInputChange::consume)
105+
}
106+
}
107+
}
108+
} else {
109+
this
110+
}

0 commit comments

Comments
 (0)