Skip to content

Commit f5c0e6a

Browse files
committed
Initial work on handling many long-press actions
1 parent 9fa9617 commit f5c0e6a

4 files changed

Lines changed: 258 additions & 110 deletions

File tree

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.schabi.newpipe.extractor.utils.Utils.isBlank;
44
import static org.schabi.newpipe.ktx.ViewUtils.animate;
55
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
6+
import static org.schabi.newpipe.ui.components.menu.LongPressMenuKt.getLongPressMenuView;
67
import static org.schabi.newpipe.util.ServiceHelper.getServiceById;
78

89
import android.content.Context;
@@ -150,6 +151,16 @@ private PlayQueue getPlayQueueStartingAt(final StreamInfoItem infoItem) {
150151

151152
@Override
152153
protected void showInfoItemDialog(final StreamInfoItem item) {
154+
activity.addContentView(
155+
getLongPressMenuView(requireContext(), item),
156+
new ViewGroup.LayoutParams(
157+
ViewGroup.LayoutParams.MATCH_PARENT,
158+
ViewGroup.LayoutParams.MATCH_PARENT
159+
)
160+
);
161+
if (Context.class.getSimpleName().startsWith("C")) {
162+
return;
163+
}
153164
final Context context = getContext();
154165
try {
155166
final InfoItemDialog.Builder dialogBuilder =
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package org.schabi.newpipe.ui.components.menu
2+
3+
import android.content.Context
4+
import android.net.Uri
5+
import androidx.annotation.StringRes
6+
import androidx.compose.material.icons.Icons
7+
import androidx.compose.material.icons.automirrored.filled.PlaylistAdd
8+
import androidx.compose.material.icons.filled.AddToQueue
9+
import androidx.compose.material.icons.filled.Cast
10+
import androidx.compose.material.icons.filled.Delete
11+
import androidx.compose.material.icons.filled.Done
12+
import androidx.compose.material.icons.filled.Download
13+
import androidx.compose.material.icons.filled.Headset
14+
import androidx.compose.material.icons.filled.OpenInBrowser
15+
import androidx.compose.material.icons.filled.Person
16+
import androidx.compose.material.icons.filled.PictureInPicture
17+
import androidx.compose.material.icons.filled.PlayArrow
18+
import androidx.compose.material.icons.filled.QueuePlayNext
19+
import androidx.compose.material.icons.filled.Share
20+
import androidx.compose.ui.graphics.vector.ImageVector
21+
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
22+
import org.schabi.newpipe.R
23+
import org.schabi.newpipe.database.stream.model.StreamEntity
24+
import org.schabi.newpipe.extractor.InfoItem
25+
import org.schabi.newpipe.extractor.stream.StreamInfoItem
26+
import org.schabi.newpipe.ktx.findFragmentActivity
27+
import org.schabi.newpipe.local.dialog.PlaylistAppendDialog
28+
import org.schabi.newpipe.local.dialog.PlaylistDialog
29+
import org.schabi.newpipe.local.history.HistoryRecordManager
30+
import org.schabi.newpipe.player.playqueue.PlayQueue
31+
import org.schabi.newpipe.player.playqueue.SinglePlayQueue
32+
import org.schabi.newpipe.util.NavigationHelper
33+
import org.schabi.newpipe.util.SparseItemUtil
34+
import org.schabi.newpipe.util.external_communication.KoreUtils
35+
import org.schabi.newpipe.util.external_communication.ShareUtils
36+
37+
data class LongPressAction(
38+
val type: Type,
39+
val action: (context: Context) -> Unit,
40+
val enabled: (isPlayerRunning: Boolean) -> Boolean = { true },
41+
) {
42+
enum class Type(
43+
@StringRes val label: Int,
44+
val icon: ImageVector,
45+
) {
46+
Enqueue(R.string.enqueue, Icons.Default.AddToQueue),
47+
EnqueueNext(R.string.enqueue_next_stream, Icons.Default.QueuePlayNext),
48+
Background(R.string.controls_background_title, Icons.Default.Headset),
49+
Popup(R.string.controls_popup_title, Icons.Default.PictureInPicture),
50+
Play(R.string.play, Icons.Default.PlayArrow),
51+
PlayWithKodi(R.string.play_with_kodi_title, Icons.Default.Cast),
52+
Download(R.string.download, Icons.Default.Download),
53+
AddToPlaylist(R.string.add_to_playlist, Icons.AutoMirrored.Default.PlaylistAdd),
54+
Share(R.string.share, Icons.Default.Share),
55+
OpenInBrowser(R.string.open_in_browser, Icons.Default.OpenInBrowser),
56+
ShowChannelDetails(R.string.show_channel_details, Icons.Default.Person),
57+
MarkAsWatched(R.string.mark_as_watched, Icons.Default.Done),
58+
Delete(R.string.delete, Icons.Default.Delete),
59+
;
60+
61+
// TODO allow actions to return disposables
62+
// TODO add actions that use the whole list the item belongs to (see wholeListQueue)
63+
64+
fun buildAction(
65+
enabled: (isPlayerRunning: Boolean) -> Boolean = { true },
66+
action: (context: Context) -> Unit,
67+
) = LongPressAction(this, action, enabled)
68+
}
69+
70+
companion object {
71+
private fun buildPlayerActionList(queue: () -> PlayQueue): List<LongPressAction> {
72+
return listOf(
73+
Type.Enqueue.buildAction({ isPlayerRunning -> isPlayerRunning }) { context ->
74+
NavigationHelper.enqueueOnPlayer(context, queue())
75+
},
76+
Type.EnqueueNext.buildAction({ isPlayerRunning -> isPlayerRunning }) { context ->
77+
NavigationHelper.enqueueNextOnPlayer(context, queue())
78+
},
79+
Type.Background.buildAction { context ->
80+
NavigationHelper.playOnBackgroundPlayer(context, queue(), true)
81+
},
82+
Type.Popup.buildAction { context ->
83+
NavigationHelper.playOnPopupPlayer(context, queue(), true)
84+
},
85+
Type.Play.buildAction { context ->
86+
NavigationHelper.playOnMainPlayer(context, queue(), false)
87+
},
88+
)
89+
}
90+
91+
private fun buildShareActionList(item: InfoItem): List<LongPressAction> {
92+
return listOf(
93+
Type.Share.buildAction { context ->
94+
ShareUtils.shareText(context, item.name, item.url, item.thumbnails)
95+
},
96+
Type.OpenInBrowser.buildAction { context ->
97+
ShareUtils.openUrlInBrowser(context, item.url)
98+
},
99+
)
100+
}
101+
102+
fun buildActionList(
103+
item: StreamInfoItem,
104+
isKodiEnabled: Boolean,
105+
/* TODO wholeListQueue: (() -> PlayQueue)? */
106+
): List<LongPressAction> {
107+
return buildPlayerActionList { SinglePlayQueue(item) } +
108+
buildShareActionList(item) +
109+
listOf(
110+
Type.Download.buildAction { context -> /* TODO */ },
111+
Type.AddToPlaylist.buildAction { context ->
112+
PlaylistDialog.createCorrespondingDialog(
113+
context,
114+
listOf(StreamEntity(item))
115+
) { dialog: PlaylistDialog ->
116+
val tag = if (dialog is PlaylistAppendDialog) "append" else "create"
117+
dialog.show(
118+
context.findFragmentActivity().supportFragmentManager,
119+
"StreamDialogEntry@${tag}_playlist"
120+
)
121+
}
122+
},
123+
Type.ShowChannelDetails.buildAction { context ->
124+
SparseItemUtil.fetchUploaderUrlIfSparse(
125+
context, item.serviceId, item.url, item.uploaderUrl
126+
) { url: String ->
127+
NavigationHelper.openChannelFragment(
128+
context.findFragmentActivity().supportFragmentManager,
129+
item.serviceId,
130+
url,
131+
item.uploaderName,
132+
)
133+
}
134+
},
135+
Type.MarkAsWatched.buildAction { context ->
136+
HistoryRecordManager(context)
137+
.markAsWatched(item)
138+
.onErrorComplete()
139+
.observeOn(AndroidSchedulers.mainThread())
140+
.subscribe()
141+
},
142+
) + if (isKodiEnabled) listOf(
143+
Type.PlayWithKodi.buildAction { context ->
144+
KoreUtils.playWithKore(context, Uri.parse(item.url))
145+
},
146+
) else listOf()
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)