From 8e454dcb71ea2adb6accaa2ab4d15366b10e0047 Mon Sep 17 00:00:00 2001 From: Stypox Date: Tue, 11 Feb 2025 15:03:37 +0100 Subject: [PATCH] Click on long press menu subtitle opens channel details --- .../ui/components/menu/LongPressMenu.kt | 77 ++++++++++++++++--- .../schabi/newpipe/ui/theme/CustomColors.kt | 32 ++++++++ .../java/org/schabi/newpipe/ui/theme/Theme.kt | 25 +++--- 3 files changed, 114 insertions(+), 20 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/ui/theme/CustomColors.kt diff --git a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt index ee1531573..b870f72b1 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/components/menu/LongPressMenu.kt @@ -2,8 +2,10 @@ package org.schabi.newpipe.ui.components.menu +import android.content.Context import android.content.res.Configuration import androidx.compose.foundation.basicMarquee +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxWithConstraints @@ -57,9 +59,12 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.contentDescription -import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.text.withStyle import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider @@ -72,6 +77,7 @@ import org.schabi.newpipe.R import org.schabi.newpipe.player.playqueue.PlayQueue import org.schabi.newpipe.player.playqueue.SinglePlayQueue import org.schabi.newpipe.ui.theme.AppTheme +import org.schabi.newpipe.ui.theme.customColors import org.schabi.newpipe.util.Either import org.schabi.newpipe.util.Localization import java.time.OffsetDateTime @@ -346,20 +352,24 @@ fun LongPressMenuHeader( modifier = Modifier.basicMarquee(iterations = Int.MAX_VALUE), ) - val subtitle = Localization.concatenateStrings( - item.uploader, - item.uploadDate?.match( - { it }, - { Localization.relativeTime(it) } - ), - item.viewCount?.let { Localization.localizeViewCount(ctx, it) } + val subtitle = getSubtitleAnnotatedString( + item = item, + linkColor = MaterialTheme.customColors.onSurfaceVariantLink, + ctx = ctx, ) if (subtitle.isNotBlank()) { Spacer(Modifier.height(1.dp)) + Text( text = subtitle, style = MaterialTheme.typography.bodyMedium, - modifier = Modifier.basicMarquee(iterations = Int.MAX_VALUE), + modifier = if (item.uploaderUrl.isNullOrBlank()) { + Modifier + } else { + Modifier.clickable { + // TODO handle click on uploader URL + } + }.basicMarquee(iterations = Int.MAX_VALUE) ) } } @@ -367,6 +377,53 @@ fun LongPressMenuHeader( } } +fun getSubtitleAnnotatedString( + item: LongPressable, + linkColor: Color, + ctx: Context, +) = buildAnnotatedString { + var shouldAddSeparator = false + if (!item.uploaderUrl.isNullOrBlank()) { + withStyle( + SpanStyle( + fontWeight = FontWeight.Bold, + color = linkColor, + textDecoration = TextDecoration.Underline + ) + ) { + if (item.uploader.isNullOrBlank()) { + append(ctx.getString(R.string.show_channel_details)) + } else { + append(item.uploader) + } + } + shouldAddSeparator = true + } else if (!item.uploader.isNullOrBlank()) { + append(item.uploader) + shouldAddSeparator = true + } + + val uploadDate = item.uploadDate?.match( + { it }, + { Localization.relativeTime(it) } + ) + if (!uploadDate.isNullOrBlank()) { + if (shouldAddSeparator) { + append(Localization.DOT_SEPARATOR) + } + shouldAddSeparator = true + append(uploadDate) + } + + val viewCount = item.viewCount?.let { Localization.localizeViewCount(ctx, it) } + if (!viewCount.isNullOrBlank()) { + if (shouldAddSeparator) { + append(Localization.DOT_SEPARATOR) + } + append(viewCount) + } +} + @Composable fun LongPressMenuButton( icon: ImageVector, diff --git a/app/src/main/java/org/schabi/newpipe/ui/theme/CustomColors.kt b/app/src/main/java/org/schabi/newpipe/ui/theme/CustomColors.kt new file mode 100644 index 000000000..aac91ee04 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/ui/theme/CustomColors.kt @@ -0,0 +1,32 @@ +package org.schabi.newpipe.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color + +@Immutable +data class CustomColors( + val onSurfaceVariantLink: Color = Color.Unspecified, +) + +val onSurfaceVariantLinkLight = Color(0xFF5060B0) + +val onSurfaceVariantLinkDark = Color(0xFFC0D0FF) + +val lightCustomColors = CustomColors( + onSurfaceVariantLink = onSurfaceVariantLinkLight +) + +val darkCustomColors = CustomColors( + onSurfaceVariantLink = onSurfaceVariantLinkDark +) + +val LocalCustomColors = staticCompositionLocalOf { CustomColors() } + +val MaterialTheme.customColors: CustomColors + @Composable + @ReadOnlyComposable + get() = LocalCustomColors.current diff --git a/app/src/main/java/org/schabi/newpipe/ui/theme/Theme.kt b/app/src/main/java/org/schabi/newpipe/ui/theme/Theme.kt index 208dbc895..fbc88b64a 100644 --- a/app/src/main/java/org/schabi/newpipe/ui/theme/Theme.kt +++ b/app/src/main/java/org/schabi/newpipe/ui/theme/Theme.kt @@ -5,6 +5,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.preference.PreferenceManager @@ -93,14 +94,18 @@ fun AppTheme(useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable val theme = sharedPreferences.getString("theme", "auto_device_theme") val nightTheme = sharedPreferences.getString("night_theme", "dark_theme") - MaterialTheme( - colorScheme = if (!useDarkTheme) { - lightScheme - } else if (theme == "black_theme" || nightTheme == "black_theme") { - blackScheme - } else { - darkScheme - }, - content = content - ) + CompositionLocalProvider( + LocalCustomColors provides if (!useDarkTheme) lightCustomColors else darkCustomColors + ) { + MaterialTheme( + colorScheme = if (!useDarkTheme) { + lightScheme + } else if (theme == "black_theme" || nightTheme == "black_theme") { + blackScheme + } else { + darkScheme + }, + content = content + ) + } }