Fix formatting with new ktlint rules
This commit is contained in:
parent
8f19f95fee
commit
70c502d31f
@ -40,5 +40,5 @@ enum class UserAction(val message: String) {
|
||||
GETTING_MAIN_SCREEN_TAB("getting main screen tab"),
|
||||
PLAY_ON_POPUP("play on popup"),
|
||||
SUBSCRIPTIONS("loading subscriptions"),
|
||||
LONG_PRESS_MENU_ACTION("long press menu action"),
|
||||
LONG_PRESS_MENU_ACTION("long press menu action")
|
||||
}
|
||||
|
||||
@ -1425,7 +1425,10 @@ class VideoDetailFragment :
|
||||
|
||||
if (info.viewCount >= 0) {
|
||||
binding.detailViewCountView.text = Localization.localizeViewCount(
|
||||
activity, false, info.streamType, info.viewCount
|
||||
activity,
|
||||
false,
|
||||
info.streamType,
|
||||
info.viewCount
|
||||
)
|
||||
binding.detailViewCountView.visibility = View.VISIBLE
|
||||
} else {
|
||||
|
||||
@ -8,5 +8,4 @@ package org.schabi.newpipe.ktx
|
||||
* .letIf(someCondition) { padding(right = 4.dp) }
|
||||
* ```
|
||||
*/
|
||||
inline fun <T> T.letIf(condition: Boolean, block: T.() -> T): T =
|
||||
if (condition) block(this) else this
|
||||
inline fun <T> T.letIf(condition: Boolean, block: T.() -> T): T = if (condition) block(this) else this
|
||||
|
||||
@ -425,8 +425,8 @@ class FeedFragment : BaseStateFragment<FeedState>() {
|
||||
// just in case
|
||||
Log.w(TAG, "Could not get full list of items on long press")
|
||||
return@fromStreamEntity SinglePlayQueue(item.stream.toStreamInfoItem())
|
||||
},
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ fun Modifier.detectDragGestures(
|
||||
}
|
||||
handleDragGestureChange(
|
||||
change.position.toIntOffset(),
|
||||
change.positionChange(),
|
||||
change.positionChange()
|
||||
)
|
||||
change.consume()
|
||||
}
|
||||
|
||||
@ -39,7 +39,7 @@ fun NavigationIcon() {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = stringResource(R.string.back),
|
||||
modifier = Modifier.padding(horizontal = SizeTokens.SpacingExtraSmall),
|
||||
modifier = Modifier.padding(horizontal = SizeTokens.SpacingExtraSmall)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ fun ScaffoldWithToolbar(
|
||||
IconButton(onClick = onBackClick) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = stringResource(R.string.back),
|
||||
contentDescription = stringResource(R.string.back)
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
@ -36,7 +36,7 @@ import org.schabi.newpipe.ui.theme.AppTheme
|
||||
fun StreamListItem(
|
||||
stream: StreamInfoItem,
|
||||
showProgress: Boolean,
|
||||
onClick: (StreamInfoItem) -> Unit = {},
|
||||
onClick: (StreamInfoItem) -> Unit = {}
|
||||
) {
|
||||
var showLongPressMenu by rememberSaveable { mutableStateOf(false) }
|
||||
|
||||
@ -81,7 +81,7 @@ fun StreamListItem(
|
||||
longPressable = LongPressable.fromStreamInfoItem(stream),
|
||||
// TODO queueFromHere: allow playing the whole list starting from one stream
|
||||
longPressActions = LongPressAction.fromStreamInfoItem(stream, null),
|
||||
onDismissRequest = { showLongPressMenu = false },
|
||||
onDismissRequest = { showLongPressMenu = false }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ data class LongPressAction(
|
||||
val type: Type,
|
||||
@MainThread
|
||||
val action: suspend (context: Context) -> Unit,
|
||||
val enabled: (isPlayerRunning: Boolean) -> Boolean = { true },
|
||||
val enabled: (isPlayerRunning: Boolean) -> Boolean = { true }
|
||||
) {
|
||||
enum class Type(
|
||||
/**
|
||||
@ -69,7 +69,7 @@ data class LongPressAction(
|
||||
*/
|
||||
val id: Int,
|
||||
@StringRes val label: Int,
|
||||
val icon: ImageVector,
|
||||
val icon: ImageVector
|
||||
) {
|
||||
Enqueue(0, R.string.enqueue, Icons.Default.AddToQueue),
|
||||
EnqueueNext(1, R.string.enqueue_next_stream, Icons.Default.QueuePlayNext),
|
||||
@ -92,7 +92,7 @@ data class LongPressAction(
|
||||
UnsetPlaylistThumbnail(18, R.string.unset_playlist_thumbnail, Icons.Default.HideImage),
|
||||
Unsubscribe(19, R.string.unsubscribe, Icons.Default.Delete),
|
||||
ShowDetails(20, R.string.play_queue_stream_detail, Icons.Default.Info),
|
||||
Remove(21, R.string.play_queue_remove, Icons.Default.Delete),
|
||||
Remove(21, R.string.play_queue_remove, Icons.Default.Delete)
|
||||
;
|
||||
|
||||
// TODO allow actions to return disposables
|
||||
@ -100,7 +100,7 @@ data class LongPressAction(
|
||||
|
||||
fun buildAction(
|
||||
enabled: (isPlayerRunning: Boolean) -> Boolean = { true },
|
||||
action: suspend (context: Context) -> Unit,
|
||||
action: suspend (context: Context) -> Unit
|
||||
) = LongPressAction(this, action, enabled)
|
||||
|
||||
companion object {
|
||||
@ -109,7 +109,7 @@ data class LongPressAction(
|
||||
val DefaultEnabledActions: List<Type> = listOf(
|
||||
ShowDetails, Enqueue, EnqueueNext, Background, Popup, BackgroundFromHere, Download,
|
||||
AddToPlaylist, Share, OpenInBrowser, MarkAsWatched, Delete,
|
||||
Rename, SetAsPlaylistThumbnail, UnsetPlaylistThumbnail, Unsubscribe, Remove,
|
||||
Rename, SetAsPlaylistThumbnail, UnsetPlaylistThumbnail, Unsubscribe, Remove
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -133,7 +133,7 @@ data class LongPressAction(
|
||||
},
|
||||
Type.Play.buildAction { context ->
|
||||
NavigationHelper.playOnMainPlayer(context, queue(context), false)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ data class LongPressAction(
|
||||
},
|
||||
Type.PlayFromHere.buildAction { context ->
|
||||
NavigationHelper.playOnMainPlayer(context, queueFromHere(), false)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ data class LongPressAction(
|
||||
},
|
||||
Type.OpenInBrowser.buildAction { context ->
|
||||
ShareUtils.openUrlInBrowser(context, item.url)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ data class LongPressAction(
|
||||
},
|
||||
Type.OpenInBrowser.buildAction { context ->
|
||||
ShareUtils.openUrlInBrowser(context, url)
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -200,13 +200,16 @@ data class LongPressAction(
|
||||
},
|
||||
Type.ShowChannelDetails.buildAction { context ->
|
||||
val uploaderUrl = fetchUploaderUrlIfSparse(
|
||||
context, item.serviceId, item.url, item.uploaderUrl
|
||||
context,
|
||||
item.serviceId,
|
||||
item.url,
|
||||
item.uploaderUrl
|
||||
)
|
||||
NavigationHelper.openChannelFragment(
|
||||
context.findFragmentActivity().supportFragmentManager,
|
||||
item.serviceId,
|
||||
uploaderUrl,
|
||||
item.uploaderName,
|
||||
item.uploaderName
|
||||
)
|
||||
},
|
||||
Type.MarkAsWatched.buildAction { context ->
|
||||
@ -216,7 +219,7 @@ data class LongPressAction(
|
||||
},
|
||||
Type.PlayWithKodi.buildAction { context ->
|
||||
KoreUtils.playWithKore(context, item.url.toUri())
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@ -227,7 +230,7 @@ data class LongPressAction(
|
||||
@JvmStatic
|
||||
fun fromStreamInfoItem(
|
||||
item: StreamInfoItem,
|
||||
queueFromHere: (() -> PlayQueue)?,
|
||||
queueFromHere: (() -> PlayQueue)?
|
||||
/* TODO isKodiEnabled: Boolean, */
|
||||
): List<LongPressAction> {
|
||||
return buildPlayerActionList { context -> fetchItemInfoIfSparse(context, item) } +
|
||||
@ -239,7 +242,7 @@ data class LongPressAction(
|
||||
@JvmStatic
|
||||
fun fromStreamEntity(
|
||||
item: StreamEntity,
|
||||
queueFromHere: (() -> PlayQueue)?,
|
||||
queueFromHere: (() -> PlayQueue)?
|
||||
): List<LongPressAction> {
|
||||
// TODO decide if it's fine to just convert to StreamInfoItem here (it poses an
|
||||
// unnecessary dependency on the extractor, when we want to just look at data; maybe
|
||||
@ -251,38 +254,43 @@ data class LongPressAction(
|
||||
fun fromPlayQueueItem(
|
||||
item: PlayQueueItem,
|
||||
playQueueFromWhichToDelete: PlayQueue,
|
||||
showDetails: Boolean,
|
||||
showDetails: Boolean
|
||||
): List<LongPressAction> {
|
||||
// TODO decide if it's fine to just convert to StreamInfoItem here (it poses an
|
||||
// unnecessary dependency on the extractor, when we want to just look at data; maybe
|
||||
// using something like LongPressable would work)
|
||||
val streamInfoItem = item.toStreamInfoItem()
|
||||
return buildShareActionList(streamInfoItem) +
|
||||
buildAdditionalStreamActionList(streamInfoItem) +
|
||||
if (showDetails) {
|
||||
listOf(
|
||||
Type.ShowDetails.buildAction { context ->
|
||||
// playQueue is null since we don't want any queue change
|
||||
NavigationHelper.openVideoDetail(
|
||||
context, item.serviceId, item.url, item.title, null, false
|
||||
)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
listOf()
|
||||
} +
|
||||
buildAdditionalStreamActionList(streamInfoItem) +
|
||||
if (showDetails) {
|
||||
listOf(
|
||||
Type.Remove.buildAction {
|
||||
val index = playQueueFromWhichToDelete.indexOf(item)
|
||||
playQueueFromWhichToDelete.remove(index)
|
||||
Type.ShowDetails.buildAction { context ->
|
||||
// playQueue is null since we don't want any queue change
|
||||
NavigationHelper.openVideoDetail(
|
||||
context,
|
||||
item.serviceId,
|
||||
item.url,
|
||||
item.title,
|
||||
null,
|
||||
false
|
||||
)
|
||||
}
|
||||
)
|
||||
} else {
|
||||
listOf()
|
||||
} +
|
||||
listOf(
|
||||
Type.Remove.buildAction {
|
||||
val index = playQueueFromWhichToDelete.indexOf(item)
|
||||
playQueueFromWhichToDelete.remove(index)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromStreamStatisticsEntry(
|
||||
item: StreamStatisticsEntry,
|
||||
queueFromHere: (() -> PlayQueue)?,
|
||||
queueFromHere: (() -> PlayQueue)?
|
||||
): List<LongPressAction> {
|
||||
return fromStreamEntity(item.streamEntity, queueFromHere) +
|
||||
listOf(
|
||||
@ -304,7 +312,7 @@ data class LongPressAction(
|
||||
queueFromHere: (() -> PlayQueue)?,
|
||||
// TODO possibly embed these two actions here
|
||||
onDelete: Runnable,
|
||||
onSetAsPlaylistThumbnail: Runnable,
|
||||
onSetAsPlaylistThumbnail: Runnable
|
||||
): List<LongPressAction> {
|
||||
return fromStreamEntity(item.streamEntity, queueFromHere) +
|
||||
listOf(
|
||||
@ -318,7 +326,7 @@ data class LongPressAction(
|
||||
item: PlaylistMetadataEntry,
|
||||
onRename: Runnable,
|
||||
onDelete: Runnable,
|
||||
unsetPlaylistThumbnail: Runnable?,
|
||||
unsetPlaylistThumbnail: Runnable?
|
||||
): List<LongPressAction> {
|
||||
return listOf(
|
||||
Type.Rename.buildAction { onRename.run() },
|
||||
@ -332,7 +340,7 @@ data class LongPressAction(
|
||||
@JvmStatic
|
||||
fun fromPlaylistRemoteEntity(
|
||||
item: PlaylistRemoteEntity,
|
||||
onDelete: Runnable,
|
||||
onDelete: Runnable
|
||||
): List<LongPressAction> {
|
||||
return buildPlayerActionList { PlaylistPlayQueue(item.serviceId, item.url) } +
|
||||
buildShareActionList(
|
||||
@ -341,14 +349,14 @@ data class LongPressAction(
|
||||
item.thumbnailUrl
|
||||
) +
|
||||
listOf(
|
||||
Type.Delete.buildAction { onDelete.run() },
|
||||
Type.Delete.buildAction { onDelete.run() }
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun fromChannelInfoItem(
|
||||
item: ChannelInfoItem,
|
||||
onUnsubscribe: Runnable?,
|
||||
onUnsubscribe: Runnable?
|
||||
): List<LongPressAction> {
|
||||
return buildPlayerActionList { ChannelTabPlayQueue(item.serviceId, item.url) } +
|
||||
buildShareActionList(item) +
|
||||
@ -358,7 +366,7 @@ data class LongPressAction(
|
||||
context.findFragmentActivity().supportFragmentManager,
|
||||
item.serviceId,
|
||||
item.url,
|
||||
item.name,
|
||||
item.name
|
||||
)
|
||||
},
|
||||
onUnsubscribe?.let { r -> Type.Unsubscribe.buildAction { r.run() } }
|
||||
|
||||
@ -79,6 +79,7 @@ import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import coil3.compose.AsyncImage
|
||||
import java.time.OffsetDateTime
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
@ -97,12 +98,11 @@ import org.schabi.newpipe.util.Either
|
||||
import org.schabi.newpipe.util.Localization
|
||||
import org.schabi.newpipe.util.text.FixedHeightCenteredText
|
||||
import org.schabi.newpipe.util.text.fadedMarquee
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
fun openLongPressMenuInActivity(
|
||||
activity: Activity,
|
||||
longPressable: LongPressable,
|
||||
longPressActions: List<LongPressAction>,
|
||||
longPressActions: List<LongPressAction>
|
||||
) {
|
||||
activity.addContentView(
|
||||
getLongPressMenuView(activity, longPressable, longPressActions),
|
||||
@ -113,7 +113,7 @@ fun openLongPressMenuInActivity(
|
||||
fun getLongPressMenuView(
|
||||
context: Context,
|
||||
longPressable: LongPressable,
|
||||
longPressActions: List<LongPressAction>,
|
||||
longPressActions: List<LongPressAction>
|
||||
): ComposeView {
|
||||
return ComposeView(context).apply {
|
||||
setContent {
|
||||
@ -121,7 +121,7 @@ fun getLongPressMenuView(
|
||||
LongPressMenu(
|
||||
longPressable = longPressable,
|
||||
longPressActions = longPressActions,
|
||||
onDismissRequest = { (this.parent as ViewGroup).removeView(this) },
|
||||
onDismissRequest = { (this.parent as ViewGroup).removeView(this) }
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -135,7 +135,7 @@ internal val ThumbnailHeight = 60.dp
|
||||
fun LongPressMenu(
|
||||
longPressable: LongPressable,
|
||||
longPressActions: List<LongPressAction>,
|
||||
onDismissRequest: () -> Unit,
|
||||
onDismissRequest: () -> Unit
|
||||
) {
|
||||
val viewModel: LongPressMenuViewModel = viewModel()
|
||||
val isHeaderEnabled by viewModel.isHeaderEnabled.collectAsState()
|
||||
@ -152,7 +152,7 @@ fun LongPressMenu(
|
||||
) {
|
||||
ScaffoldWithToolbar(
|
||||
title = stringResource(R.string.long_press_menu_actions_editor),
|
||||
onBackClick = { showEditor = false },
|
||||
onBackClick = { showEditor = false }
|
||||
) { paddingValues ->
|
||||
LongPressMenuEditor(modifier = Modifier.padding(paddingValues))
|
||||
}
|
||||
@ -179,7 +179,8 @@ fun LongPressMenu(
|
||||
action.action(ctx)
|
||||
} catch (t: Throwable) {
|
||||
ErrorUtil.showSnackbar(
|
||||
ctx, ErrorInfo(t, LONG_PRESS_MENU_ACTION, "Running action ${action.type}")
|
||||
ctx,
|
||||
ErrorInfo(t, LONG_PRESS_MENU_ACTION, "Running action ${action.type}")
|
||||
)
|
||||
}
|
||||
onDismissRequest()
|
||||
@ -199,14 +200,14 @@ fun LongPressMenu(
|
||||
ModalBottomSheet(
|
||||
sheetState = sheetState,
|
||||
onDismissRequest = onDismissRequest,
|
||||
dragHandle = { LongPressMenuDragHandle(onEditActions = { showEditor = true }) },
|
||||
dragHandle = { LongPressMenuDragHandle(onEditActions = { showEditor = true }) }
|
||||
) {
|
||||
Box(modifier = Modifier.discardAllTouchesIf(isLoading)) {
|
||||
LongPressMenuContent(
|
||||
header = longPressable.takeIf { isHeaderEnabled },
|
||||
onUploaderClick = onUploaderClick,
|
||||
actions = enabledLongPressActions,
|
||||
runActionAndDismiss = ::runActionAndDismiss,
|
||||
runActionAndDismiss = ::runActionAndDismiss
|
||||
)
|
||||
// importing makes the ColumnScope overload be resolved, so we use qualified path...
|
||||
androidx.compose.animation.AnimatedVisibility(
|
||||
@ -215,7 +216,7 @@ fun LongPressMenu(
|
||||
exit = fadeOut(),
|
||||
modifier = Modifier
|
||||
.matchParentSize()
|
||||
.background(MaterialTheme.colorScheme.surfaceContainerLow),
|
||||
.background(MaterialTheme.colorScheme.surfaceContainerLow)
|
||||
) {
|
||||
Box(contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator()
|
||||
@ -231,7 +232,7 @@ private fun LongPressMenuContent(
|
||||
header: LongPressable?,
|
||||
onUploaderClick: (() -> Unit)?,
|
||||
actions: List<LongPressAction>,
|
||||
runActionAndDismiss: (LongPressAction) -> Unit,
|
||||
runActionAndDismiss: (LongPressAction) -> Unit
|
||||
) {
|
||||
BoxWithConstraints(
|
||||
modifier = Modifier
|
||||
@ -251,7 +252,7 @@ private fun LongPressMenuContent(
|
||||
while (actionIndex < actions.size) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
var rowIndex = 0
|
||||
while (rowIndex < buttonsPerRow) {
|
||||
@ -263,7 +264,7 @@ private fun LongPressMenuContent(
|
||||
modifier = Modifier
|
||||
.height(buttonHeight)
|
||||
.fillMaxWidth()
|
||||
.weight((buttonsPerRow - rowIndex).toFloat()),
|
||||
.weight((buttonsPerRow - rowIndex).toFloat())
|
||||
)
|
||||
break
|
||||
} else if (actionIndex >= 0) {
|
||||
@ -276,7 +277,7 @@ private fun LongPressMenuContent(
|
||||
modifier = Modifier
|
||||
.height(buttonHeight)
|
||||
.fillMaxWidth()
|
||||
.weight(1F),
|
||||
.weight(1F)
|
||||
)
|
||||
rowIndex += 1
|
||||
} else if (maxHeaderWidthInButtonsFullSpan >= buttonsPerRow) {
|
||||
@ -290,7 +291,7 @@ private fun LongPressMenuContent(
|
||||
// leave the height as small as possible, since it's the
|
||||
// only item on the row anyway
|
||||
.fillMaxWidth()
|
||||
.weight(maxHeaderWidthInButtonsFullSpan.toFloat()),
|
||||
.weight(maxHeaderWidthInButtonsFullSpan.toFloat())
|
||||
)
|
||||
rowIndex += maxHeaderWidthInButtonsFullSpan
|
||||
} else {
|
||||
@ -306,7 +307,7 @@ private fun LongPressMenuContent(
|
||||
.padding(start = 8.dp, top = 11.dp, bottom = 11.dp)
|
||||
.heightIn(min = ThumbnailHeight)
|
||||
.fillMaxWidth()
|
||||
.weight(headerWidthInButtonsReducedSpan.toFloat()),
|
||||
.weight(headerWidthInButtonsReducedSpan.toFloat())
|
||||
)
|
||||
rowIndex += headerWidthInButtonsReducedSpan
|
||||
}
|
||||
@ -357,7 +358,7 @@ fun LongPressMenuDragHandle(onEditActions: () -> Unit) {
|
||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
modifier = Modifier
|
||||
.padding(2.dp)
|
||||
.size(16.dp),
|
||||
.size(16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -378,7 +379,7 @@ private fun LongPressMenuDragHandlePreview() {
|
||||
fun LongPressMenuHeader(
|
||||
item: LongPressable,
|
||||
onUploaderClick: (() -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val ctx = LocalContext.current
|
||||
|
||||
@ -386,7 +387,7 @@ fun LongPressMenuHeader(
|
||||
color = MaterialTheme.colorScheme.surfaceContainer,
|
||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
shape = MaterialTheme.shapes.large,
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Box {
|
||||
@ -413,12 +414,12 @@ fun LongPressMenuHeader(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(4.dp)
|
||||
.clip(MaterialTheme.shapes.medium),
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
) {
|
||||
Text(
|
||||
text = Localization.getDurationString(decoration.duration),
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
modifier = Modifier.padding(vertical = 2.dp, horizontal = 4.dp),
|
||||
modifier = Modifier.padding(vertical = 2.dp, horizontal = 4.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -433,7 +434,7 @@ fun LongPressMenuHeader(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomEnd)
|
||||
.padding(4.dp)
|
||||
.clip(MaterialTheme.shapes.medium),
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.duration_live).uppercase(),
|
||||
@ -451,16 +452,16 @@ fun LongPressMenuHeader(
|
||||
modifier = Modifier
|
||||
.align(Alignment.TopEnd)
|
||||
.size(width = 40.dp, height = ThumbnailHeight)
|
||||
.clip(MaterialTheme.shapes.large),
|
||||
.clip(MaterialTheme.shapes.large)
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Default.PlaylistPlay,
|
||||
contentDescription = null,
|
||||
contentDescription = null
|
||||
)
|
||||
Text(
|
||||
text = Localization.localizeStreamCountMini(
|
||||
@ -468,7 +469,7 @@ fun LongPressMenuHeader(
|
||||
decoration.itemCount
|
||||
),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
maxLines = 1,
|
||||
maxLines = 1
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -479,7 +480,7 @@ fun LongPressMenuHeader(
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.padding(vertical = 8.dp),
|
||||
modifier = Modifier.padding(vertical = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
text = item.title,
|
||||
@ -487,14 +488,14 @@ fun LongPressMenuHeader(
|
||||
maxLines = 1,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fadedMarquee(edgeWidth = 12.dp),
|
||||
.fadedMarquee(edgeWidth = 12.dp)
|
||||
)
|
||||
|
||||
val subtitle = getSubtitleAnnotatedString(
|
||||
item = item,
|
||||
showLink = onUploaderClick != null,
|
||||
linkColor = MaterialTheme.customColors.onSurfaceVariantLink,
|
||||
ctx = ctx,
|
||||
ctx = ctx
|
||||
)
|
||||
if (subtitle.isNotBlank()) {
|
||||
Spacer(Modifier.height(1.dp))
|
||||
@ -509,7 +510,7 @@ fun LongPressMenuHeader(
|
||||
Modifier.clickable(onClick = onUploaderClick)
|
||||
}
|
||||
.fillMaxWidth()
|
||||
.fadedMarquee(edgeWidth = 12.dp),
|
||||
.fadedMarquee(edgeWidth = 12.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -521,7 +522,7 @@ fun getSubtitleAnnotatedString(
|
||||
item: LongPressable,
|
||||
showLink: Boolean,
|
||||
linkColor: Color,
|
||||
ctx: Context,
|
||||
ctx: Context
|
||||
) = buildAnnotatedString {
|
||||
var shouldAddSeparator = false
|
||||
if (showLink) {
|
||||
@ -574,13 +575,13 @@ fun getSubtitleInlineContent() = mapOf(
|
||||
placeholder = Placeholder(
|
||||
width = MaterialTheme.typography.bodyMedium.fontSize,
|
||||
height = MaterialTheme.typography.bodyMedium.fontSize,
|
||||
placeholderVerticalAlign = PlaceholderVerticalAlign.Center,
|
||||
placeholderVerticalAlign = PlaceholderVerticalAlign.Center
|
||||
)
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.AutoMirrored.Filled.OpenInNew,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.customColors.onSurfaceVariantLink,
|
||||
tint = MaterialTheme.customColors.onSurfaceVariantLink
|
||||
)
|
||||
}
|
||||
)
|
||||
@ -591,7 +592,7 @@ fun LongPressMenuButton(
|
||||
text: String,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
// TODO possibly make it so that when you long-press on the button, the label appears on-screen
|
||||
// as a small popup, so in case the label text is cut off the users can still read it in full
|
||||
@ -601,18 +602,18 @@ fun LongPressMenuButton(
|
||||
shape = MaterialTheme.shapes.large,
|
||||
contentPadding = PaddingValues(start = 3.dp, top = 8.dp, end = 3.dp, bottom = 2.dp),
|
||||
border = null,
|
||||
modifier = modifier,
|
||||
modifier = modifier
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(32.dp),
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
FixedHeightCenteredText(
|
||||
text = text,
|
||||
lines = 2,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -650,7 +651,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = 8765432,
|
||||
streamType = null,
|
||||
uploadDate = Either.left("16 years ago"),
|
||||
decoration = LongPressable.Decoration.Playlist(12),
|
||||
decoration = LongPressable.Decoration.Playlist(12)
|
||||
),
|
||||
LongPressable(
|
||||
title = LoremIpsum().values.first(),
|
||||
@ -661,7 +662,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = 8765432,
|
||||
streamType = StreamType.VIDEO_STREAM,
|
||||
uploadDate = Either.left("16 years ago"),
|
||||
decoration = LongPressable.Decoration.Duration(500),
|
||||
decoration = LongPressable.Decoration.Duration(500)
|
||||
),
|
||||
LongPressable(
|
||||
title = LoremIpsum().values.first(),
|
||||
@ -672,7 +673,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = null,
|
||||
decoration = null
|
||||
),
|
||||
LongPressable(
|
||||
title = LoremIpsum().values.first(),
|
||||
@ -683,7 +684,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = null,
|
||||
streamType = StreamType.AUDIO_STREAM,
|
||||
uploadDate = null,
|
||||
decoration = LongPressable.Decoration.Duration(500),
|
||||
decoration = LongPressable.Decoration.Duration(500)
|
||||
),
|
||||
LongPressable(
|
||||
title = LoremIpsum().values.first(),
|
||||
@ -694,7 +695,7 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = null,
|
||||
streamType = StreamType.LIVE_STREAM,
|
||||
uploadDate = null,
|
||||
decoration = LongPressable.Decoration.Live,
|
||||
decoration = LongPressable.Decoration.Live
|
||||
),
|
||||
LongPressable(
|
||||
title = LoremIpsum().values.first(),
|
||||
@ -705,8 +706,8 @@ private class LongPressablePreviews : CollectionPreviewParameterProvider<LongPre
|
||||
viewCount = null,
|
||||
streamType = StreamType.AUDIO_LIVE_STREAM,
|
||||
uploadDate = Either.right(OffsetDateTime.now().minusSeconds(12)),
|
||||
decoration = LongPressable.Decoration.Playlist(1500),
|
||||
),
|
||||
decoration = LongPressable.Decoration.Playlist(1500)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -736,7 +737,7 @@ private fun LongPressMenuPreview(
|
||||
actions = LongPressAction.Type.entries
|
||||
// disable Enqueue actions just to show it off
|
||||
.map { t -> t.buildAction({ t != EnqueueNext }) { } },
|
||||
runActionAndDismiss = {},
|
||||
runActionAndDismiss = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,12 +64,12 @@ import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameter
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.toSize
|
||||
import kotlin.math.floor
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ktx.letIf
|
||||
import org.schabi.newpipe.ui.detectDragGestures
|
||||
import org.schabi.newpipe.ui.theme.AppTheme
|
||||
import org.schabi.newpipe.util.text.FixedHeightCenteredText
|
||||
import kotlin.math.floor
|
||||
|
||||
/**
|
||||
* When making changes to this composable and to [LongPressMenuEditorState], make sure to test the
|
||||
@ -112,7 +112,7 @@ fun LongPressMenuEditor(modifier: Modifier = Modifier) {
|
||||
.detectDragGestures(
|
||||
beginDragGesture = state::beginDragGesture,
|
||||
handleDragGestureChange = state::handleDragGestureChange,
|
||||
endDragGesture = state::completeDragGestureAndCleanUp,
|
||||
endDragGesture = state::completeDragGestureAndCleanUp
|
||||
)
|
||||
// `.focusTarget().onKeyEvent()` handles DPAD on Android TVs
|
||||
.focusTarget()
|
||||
@ -120,12 +120,12 @@ fun LongPressMenuEditor(modifier: Modifier = Modifier) {
|
||||
// same width as the LongPressMenu
|
||||
columns = GridCells.Adaptive(MinButtonWidth),
|
||||
userScrollEnabled = false,
|
||||
state = gridState,
|
||||
state = gridState
|
||||
) {
|
||||
itemsIndexed(
|
||||
state.items,
|
||||
key = { _, item -> item.stableUniqueKey() },
|
||||
span = { _, item -> GridItemSpan(item.columnSpan ?: maxLineSpan) },
|
||||
span = { _, item -> GridItemSpan(item.columnSpan ?: maxLineSpan) }
|
||||
) { i, item ->
|
||||
ItemInListUi(
|
||||
item = item,
|
||||
@ -151,7 +151,7 @@ fun LongPressMenuEditor(modifier: Modifier = Modifier) {
|
||||
.size(size)
|
||||
.offset { state.activeDragPosition }
|
||||
.offset(-size.width / 2, -size.height / 2)
|
||||
.offset((-24).dp, (-24).dp),
|
||||
.offset((-24).dp, (-24).dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -162,7 +162,7 @@ private fun Subheader(
|
||||
selected: Boolean,
|
||||
@StringRes title: Int,
|
||||
@StringRes description: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
@ -177,7 +177,7 @@ private fun Subheader(
|
||||
Text(
|
||||
text = stringResource(description),
|
||||
fontStyle = FontStyle.Italic,
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -190,7 +190,7 @@ private fun ActionOrHeaderBox(
|
||||
contentColor: Color,
|
||||
modifier: Modifier = Modifier,
|
||||
backgroundColor: Color = Color.Transparent,
|
||||
horizontalPadding: Dp = 3.dp,
|
||||
horizontalPadding: Dp = 3.dp
|
||||
) {
|
||||
Surface(
|
||||
color = backgroundColor,
|
||||
@ -199,19 +199,19 @@ private fun ActionOrHeaderBox(
|
||||
border = BorderStroke(2.dp, contentColor.copy(alpha = 1f)).takeIf { selected },
|
||||
modifier = modifier.padding(
|
||||
horizontal = horizontalPadding,
|
||||
vertical = 5.dp,
|
||||
),
|
||||
vertical = 5.dp
|
||||
)
|
||||
) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(32.dp),
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
FixedHeightCenteredText(
|
||||
text = stringResource(text),
|
||||
lines = 2,
|
||||
style = MaterialTheme.typography.bodySmall,
|
||||
style = MaterialTheme.typography.bodySmall
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -221,7 +221,7 @@ private fun ActionOrHeaderBox(
|
||||
private fun ItemInListUi(
|
||||
item: ItemInList,
|
||||
selected: Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
when (item) {
|
||||
ItemInList.EnabledCaption -> {
|
||||
@ -229,26 +229,29 @@ private fun ItemInListUi(
|
||||
modifier = modifier,
|
||||
selected = selected,
|
||||
title = R.string.long_press_menu_enabled_actions,
|
||||
description = R.string.long_press_menu_enabled_actions_description,
|
||||
description = R.string.long_press_menu_enabled_actions_description
|
||||
)
|
||||
}
|
||||
|
||||
ItemInList.HiddenCaption -> {
|
||||
Subheader(
|
||||
modifier = modifier,
|
||||
selected = selected,
|
||||
title = R.string.long_press_menu_hidden_actions,
|
||||
description = R.string.long_press_menu_hidden_actions_description,
|
||||
description = R.string.long_press_menu_hidden_actions_description
|
||||
)
|
||||
}
|
||||
|
||||
is ItemInList.Action -> {
|
||||
ActionOrHeaderBox(
|
||||
modifier = modifier,
|
||||
selected = selected,
|
||||
icon = item.type.icon,
|
||||
text = item.type.label,
|
||||
contentColor = MaterialTheme.colorScheme.onSurface,
|
||||
contentColor = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
}
|
||||
|
||||
ItemInList.HeaderBox -> {
|
||||
ActionOrHeaderBox(
|
||||
modifier = modifier,
|
||||
@ -257,9 +260,10 @@ private fun ItemInListUi(
|
||||
text = R.string.long_press_menu_header,
|
||||
contentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
backgroundColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||
horizontalPadding = 12.dp,
|
||||
horizontalPadding = 12.dp
|
||||
)
|
||||
}
|
||||
|
||||
ItemInList.NoneMarker -> {
|
||||
ActionOrHeaderBox(
|
||||
modifier = modifier,
|
||||
@ -267,16 +271,17 @@ private fun ItemInListUi(
|
||||
icon = Icons.Default.Close,
|
||||
text = R.string.none,
|
||||
// 0.38f is the same alpha that the Material3 library applies for disabled buttons
|
||||
contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f),
|
||||
contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
|
||||
)
|
||||
}
|
||||
|
||||
is ItemInList.DragMarker -> {
|
||||
ActionOrHeaderBox(
|
||||
modifier = modifier,
|
||||
selected = selected,
|
||||
icon = Icons.Default.DragHandle,
|
||||
text = R.string.detail_drag_description,
|
||||
contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f),
|
||||
contentColor = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.1f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,14 +20,14 @@ import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
private const val TAG = "LongPressMenuEditorStat"
|
||||
|
||||
@ -43,7 +43,7 @@ private const val TAG = "LongPressMenuEditorStat"
|
||||
class LongPressMenuEditorState(
|
||||
context: Context,
|
||||
val gridState: LazyGridState,
|
||||
val coroutineScope: CoroutineScope,
|
||||
val coroutineScope: CoroutineScope
|
||||
) {
|
||||
val items = run {
|
||||
// We get the current arrangement once and do not observe on purpose.
|
||||
@ -99,10 +99,10 @@ class LongPressMenuEditorState(
|
||||
private fun autoScrollSpeedFromTouchPos(
|
||||
touchPos: IntOffset,
|
||||
maxSpeed: Float = 20f,
|
||||
scrollIfCloseToBorderPercent: Float = 0.2f,
|
||||
scrollIfCloseToBorderPercent: Float = 0.2f
|
||||
): Float {
|
||||
val heightPosRatio = touchPos.y.toFloat() /
|
||||
(gridState.layoutInfo.viewportEndOffset - gridState.layoutInfo.viewportStartOffset)
|
||||
(gridState.layoutInfo.viewportEndOffset - gridState.layoutInfo.viewportStartOffset)
|
||||
// just a linear piecewise function, sets higher speeds the closer the finger is to the border
|
||||
return maxSpeed * max(
|
||||
// proportionally positive speed when close to the bottom border
|
||||
@ -390,11 +390,12 @@ class LongPressMenuEditorState(
|
||||
sealed class ItemInList(
|
||||
val isDraggable: Boolean = false,
|
||||
val isCaption: Boolean = false,
|
||||
open val columnSpan: Int? = 1,
|
||||
// if null, then the item will occupy all of the line
|
||||
open val columnSpan: Int? = 1
|
||||
) {
|
||||
// decoration items (i.e. text subheaders)
|
||||
object EnabledCaption : ItemInList(isCaption = true, columnSpan = null /* i.e. all line */)
|
||||
object HiddenCaption : ItemInList(isCaption = true, columnSpan = null /* i.e. all line */)
|
||||
object EnabledCaption : ItemInList(isCaption = true, columnSpan = null) // i.e. span all line
|
||||
object HiddenCaption : ItemInList(isCaption = true, columnSpan = null) // i.e. span all line
|
||||
|
||||
// actual draggable actions (+ a header)
|
||||
object HeaderBox : ItemInList(isDraggable = true, columnSpan = 2)
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package org.schabi.newpipe.ui.components.menu
|
||||
|
||||
import androidx.compose.runtime.Stable
|
||||
import java.time.OffsetDateTime
|
||||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry
|
||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity
|
||||
@ -14,7 +15,6 @@ import org.schabi.newpipe.extractor.stream.StreamType.LIVE_STREAM
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueueItem
|
||||
import org.schabi.newpipe.util.Either
|
||||
import org.schabi.newpipe.util.image.ImageStrategy
|
||||
import java.time.OffsetDateTime
|
||||
|
||||
@Stable
|
||||
data class LongPressable(
|
||||
@ -26,7 +26,7 @@ data class LongPressable(
|
||||
val viewCount: Long?,
|
||||
val streamType: StreamType?, // only used to format the view count properly
|
||||
val uploadDate: Either<String, OffsetDateTime>?,
|
||||
val decoration: Decoration?,
|
||||
val decoration: Decoration?
|
||||
) {
|
||||
sealed interface Decoration {
|
||||
data class Duration(val duration: Long) : Decoration
|
||||
@ -34,12 +34,11 @@ data class LongPressable(
|
||||
data class Playlist(val itemCount: Long) : Decoration
|
||||
|
||||
companion object {
|
||||
internal fun from(streamType: StreamType, duration: Long) =
|
||||
if (streamType == LIVE_STREAM || streamType == AUDIO_LIVE_STREAM) {
|
||||
Live
|
||||
} else {
|
||||
duration.takeIf { it > 0 }?.let { Duration(it) }
|
||||
}
|
||||
internal fun from(streamType: StreamType, duration: Long) = if (streamType == LIVE_STREAM || streamType == AUDIO_LIVE_STREAM) {
|
||||
Live
|
||||
} else {
|
||||
duration.takeIf { it > 0 }?.let { Duration(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,7 +54,7 @@ data class LongPressable(
|
||||
streamType = item.streamType,
|
||||
uploadDate = item.uploadDate?.let { Either.right(it.offsetDateTime()) }
|
||||
?: item.textualUploadDate?.let { Either.left(it) },
|
||||
decoration = Decoration.from(item.streamType, item.duration),
|
||||
decoration = Decoration.from(item.streamType, item.duration)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -69,7 +68,7 @@ data class LongPressable(
|
||||
streamType = item.streamType,
|
||||
uploadDate = item.uploadDate?.let { Either.right(it) }
|
||||
?: item.textualUploadDate?.let { Either.left(it) },
|
||||
decoration = Decoration.from(item.streamType, item.duration),
|
||||
decoration = Decoration.from(item.streamType, item.duration)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -82,7 +81,7 @@ data class LongPressable(
|
||||
viewCount = null,
|
||||
streamType = item.streamType,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.from(item.streamType, item.duration),
|
||||
decoration = Decoration.from(item.streamType, item.duration)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -96,7 +95,7 @@ data class LongPressable(
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(item.streamCount),
|
||||
decoration = Decoration.Playlist(item.streamCount)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -111,7 +110,7 @@ data class LongPressable(
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(
|
||||
item.streamCount ?: ListExtractor.ITEM_COUNT_UNKNOWN
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -124,7 +123,7 @@ data class LongPressable(
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = null,
|
||||
decoration = null
|
||||
)
|
||||
|
||||
@JvmStatic
|
||||
@ -137,7 +136,7 @@ data class LongPressable(
|
||||
viewCount = null,
|
||||
streamType = null,
|
||||
uploadDate = null,
|
||||
decoration = Decoration.Playlist(item.streamCount),
|
||||
decoration = Decoration.Playlist(item.streamCount)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ import org.schabi.newpipe.util.StreamTypeUtil
|
||||
@MainThread
|
||||
suspend fun fetchItemInfoIfSparse(
|
||||
context: Context,
|
||||
item: StreamInfoItem,
|
||||
item: StreamInfoItem
|
||||
): SinglePlayQueue {
|
||||
if ((StreamTypeUtil.isLiveStream(item.streamType) || item.duration >= 0) &&
|
||||
!Utils.isNullOrEmpty(item.uploaderUrl)
|
||||
@ -66,7 +66,7 @@ suspend fun fetchUploaderUrlIfSparse(
|
||||
context: Context,
|
||||
serviceId: Int,
|
||||
url: String,
|
||||
uploaderUrl: String?,
|
||||
uploaderUrl: String?
|
||||
): String? {
|
||||
if (!uploaderUrl.isNullOrEmpty()) {
|
||||
return uploaderUrl
|
||||
@ -89,7 +89,7 @@ suspend fun fetchUploaderUrlIfSparse(
|
||||
suspend fun fetchStreamInfoAndSaveToDatabase(
|
||||
context: Context,
|
||||
serviceId: Int,
|
||||
url: String,
|
||||
url: String
|
||||
): StreamInfo {
|
||||
Toast.makeText(context, R.string.loading_stream_details, Toast.LENGTH_SHORT).show()
|
||||
|
||||
|
||||
@ -146,6 +146,6 @@ private fun BackgroundFromHerePreview() {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.BackgroundFromHere,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(240.dp),
|
||||
modifier = Modifier.size(240.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@ -122,6 +122,6 @@ private fun PlayFromHerePreview() {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.PlayFromHere,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(240.dp),
|
||||
modifier = Modifier.size(240.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@ -158,6 +158,6 @@ private fun PopupFromHerePreview() {
|
||||
Icon(
|
||||
imageVector = Icons.Filled.PopupFromHere,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(240.dp),
|
||||
modifier = Modifier.size(240.dp)
|
||||
)
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@ import androidx.compose.ui.graphics.Color
|
||||
|
||||
@Immutable
|
||||
data class CustomColors(
|
||||
val onSurfaceVariantLink: Color = Color.Unspecified,
|
||||
val onSurfaceVariantLink: Color = Color.Unspecified
|
||||
)
|
||||
|
||||
val onSurfaceVariantLinkLight = Color(0xFF5060B0)
|
||||
|
||||
@ -9,7 +9,7 @@ import kotlin.reflect.safeCast
|
||||
data class Either<A : Any, B : Any>(
|
||||
val value: Any,
|
||||
val classA: KClass<A>,
|
||||
val classB: KClass<B>,
|
||||
val classB: KClass<B>
|
||||
) {
|
||||
inline fun <R> match(ifLeft: (A) -> R, ifRight: (B) -> R): R {
|
||||
return classA.safeCast(value)?.let { ifLeft(it) }
|
||||
@ -17,9 +17,7 @@ data class Either<A : Any, B : Any>(
|
||||
}
|
||||
|
||||
companion object {
|
||||
inline fun <reified A : Any, reified B : Any> left(a: A): Either<A, B> =
|
||||
Either(a, A::class, B::class)
|
||||
inline fun <reified A : Any, reified B : Any> right(b: B): Either<A, B> =
|
||||
Either(b, A::class, B::class)
|
||||
inline fun <reified A : Any, reified B : Any> left(a: A): Either<A, B> = Either(a, A::class, B::class)
|
||||
inline fun <reified A : Any, reified B : Any> right(b: B): Either<A, B> = Either(b, A::class, B::class)
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ fun FixedHeightCenteredText(
|
||||
text: String,
|
||||
lines: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
style: TextStyle = LocalTextStyle.current,
|
||||
style: TextStyle = LocalTextStyle.current
|
||||
) {
|
||||
Box(modifier = modifier) {
|
||||
// this allows making the box always the same height (i.e. the height of [lines] text
|
||||
@ -26,7 +26,7 @@ fun FixedHeightCenteredText(
|
||||
Text(
|
||||
text = "",
|
||||
style = style,
|
||||
minLines = lines,
|
||||
minLines = lines
|
||||
)
|
||||
Text(
|
||||
text = text,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user