1
0
Fork 0
mirror of https://github.com/TeamNewPipe/NewPipe.git synced 2025-10-03 01:39:38 +02:00
This commit is contained in:
Siddhesh Naik 2025-09-24 18:36:15 +00:00 committed by GitHub
commit c19355916c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 143 additions and 68 deletions

View file

@ -1,23 +1,31 @@
package org.schabi.newpipe.settings
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import org.schabi.newpipe.R
import org.schabi.newpipe.ui.SettingsRoutes
import org.schabi.newpipe.ui.TextPreference
import org.schabi.newpipe.ui.theme.SizeTokens.SpacingExtraSmall
@Composable
fun SettingsScreen(
onSelectSettingOption: (SettingsScreenKey) -> Unit,
onSelectSettingOption: (settingsRoute: SettingsRoutes) -> Unit,
modifier: Modifier = Modifier
) {
Column(modifier = modifier) {
TextPreference(
title = R.string.settings_category_debug_title,
onClick = { onSelectSettingOption(SettingsScreenKey.DEBUG) }
onClick = { onSelectSettingOption(SettingsRoutes.SettingsDebugRoute) }
)
HorizontalDivider(
color = MaterialTheme.colorScheme.onBackground,
thickness = 0.6.dp,
modifier = Modifier.padding(horizontal = SpacingExtraSmall)
)
HorizontalDivider(color = Color.Black)
}
}

View file

@ -10,21 +10,19 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import dagger.hilt.android.AndroidEntryPoint
import org.schabi.newpipe.R
import org.schabi.newpipe.settings.viewmodel.SettingsViewModel
import org.schabi.newpipe.ui.SettingsRoutes
import org.schabi.newpipe.ui.Toolbar
import org.schabi.newpipe.ui.theme.AppTheme
const val SCREEN_TITLE_KEY = "SCREEN_TITLE_KEY"
@AndroidEntryPoint
class SettingsV2Activity : ComponentActivity() {
@ -35,37 +33,44 @@ class SettingsV2Activity : ComponentActivity() {
setContent {
val navController = rememberNavController()
var screenTitle by remember { mutableIntStateOf(SettingsScreenKey.ROOT.screenTitle) }
navController.addOnDestinationChangedListener { _, _, arguments ->
screenTitle =
arguments?.getInt(SCREEN_TITLE_KEY) ?: SettingsScreenKey.ROOT.screenTitle
val navBackStackEntry by navController.currentBackStackEntryAsState()
@StringRes val screenTitleRes by remember(navBackStackEntry) {
mutableIntStateOf(
when (navBackStackEntry?.destination?.route) {
SettingsRoutes.SettingsMainRoute::class.java.canonicalName -> SettingsRoutes.SettingsMainRoute.screenTitleRes
SettingsRoutes.SettingsDebugRoute::class.java.canonicalName -> SettingsRoutes.SettingsDebugRoute.screenTitleRes
else -> R.string.settings
}
)
}
AppTheme {
Scaffold(topBar = {
Toolbar(
title = stringResource(id = screenTitle),
title = stringResource(screenTitleRes),
onNavigateBack = {
if (!navController.popBackStack()) {
finish()
}
},
hasSearch = true,
onSearchQueryChange = null // TODO: Add suggestions logic
onSearch = {
// TODO: Add suggestions logic
},
searchResults = emptyList()
)
}) { padding ->
NavHost(
navController = navController,
startDestination = SettingsScreenKey.ROOT.name,
startDestination = SettingsRoutes.SettingsMainRoute,
modifier = Modifier.padding(padding)
) {
composable(
SettingsScreenKey.ROOT.name,
listOf(createScreenTitleArg(SettingsScreenKey.ROOT.screenTitle))
) {
SettingsScreen(onSelectSettingOption = { screen ->
navController.navigate(screen.name)
composable<SettingsRoutes.SettingsMainRoute> {
SettingsScreen(onSelectSettingOption = { route ->
navController.navigate(route)
})
}
composable(
SettingsScreenKey.DEBUG.name,
listOf(createScreenTitleArg(SettingsScreenKey.DEBUG.screenTitle))
) {
composable<SettingsRoutes.SettingsDebugRoute> {
DebugScreen(settingsViewModel)
}
}
@ -74,12 +79,3 @@ class SettingsV2Activity : ComponentActivity() {
}
}
}
fun createScreenTitleArg(@StringRes screenTitle: Int) = navArgument(SCREEN_TITLE_KEY) {
defaultValue = screenTitle
}
enum class SettingsScreenKey(@StringRes val screenTitle: Int) {
ROOT(R.string.settings),
DEBUG(R.string.settings_category_debug_title)
}

View file

@ -0,0 +1,17 @@
package org.schabi.newpipe.ui
import androidx.annotation.StringRes
import kotlinx.serialization.Serializable
import org.schabi.newpipe.R
// Settings screens
@Serializable
sealed class SettingsRoutes(
@get:StringRes
val screenTitleRes: Int
) {
@Serializable
object SettingsMainRoute : SettingsRoutes(R.string.settings)
@Serializable
object SettingsDebugRoute : SettingsRoutes(R.string.settings_category_debug_title)
}

View file

@ -1,45 +1,60 @@
package org.schabi.newpipe.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SearchBar
import androidx.compose.material3.SearchBarDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.isTraversalGroup
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.traversalIndex
import androidx.compose.ui.tooling.preview.Preview
import org.schabi.newpipe.R
import org.schabi.newpipe.ui.theme.AppTheme
import org.schabi.newpipe.ui.theme.SizeTokens
import org.schabi.newpipe.ui.theme.SizeTokens.SpacingExtraSmall
@Composable
fun TextAction(text: String, modifier: Modifier = Modifier) {
Text(text = text, color = MaterialTheme.colorScheme.onSurface, modifier = modifier)
Text(text = text, color = MaterialTheme.colorScheme.onPrimary, modifier = modifier)
}
@Composable
fun NavigationIcon() {
fun NavigationIcon(navigateBack: () -> Unit) {
IconButton(onClick = navigateBack) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back",
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back",
modifier = Modifier.padding(horizontal = SizeTokens.SpacingExtraSmall)
)
}
}
@Composable
@ -53,19 +68,27 @@ fun SearchSuggestionItem(text: String) {
fun Toolbar(
title: String,
modifier: Modifier = Modifier,
hasNavigationIcon: Boolean = true,
onNavigateBack: (() -> Unit)? = null,
hasSearch: Boolean = false,
onSearchQueryChange: ((String) -> List<String>)? = null,
onSearch: (String) -> Unit,
searchResults: List<String>,
actions: @Composable RowScope.() -> Unit = {}
) {
var isSearchActive by remember { mutableStateOf(false) }
var query by remember { mutableStateOf("") }
var expanded by rememberSaveable { mutableStateOf(false) }
val textFieldState = rememberTextFieldState()
Column {
TopAppBar(
title = { Text(text = title) },
modifier = modifier,
navigationIcon = { if (hasNavigationIcon) NavigationIcon() },
colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primary,
titleContentColor = MaterialTheme.colorScheme.onPrimary,
),
navigationIcon = {
onNavigateBack?.let { NavigationIcon(onNavigateBack) }
},
actions = {
actions()
if (hasSearch) {
@ -73,39 +96,66 @@ fun Toolbar(
Icon(
painterResource(id = R.drawable.ic_search),
contentDescription = stringResource(id = R.string.search),
tint = MaterialTheme.colorScheme.onSurface
tint = MaterialTheme.colorScheme.onPrimary
)
}
}
}
)
if (isSearchActive) {
SearchBar(
query = query,
onQueryChange = { query = it },
onSearch = {},
placeholder = {
Text(text = stringResource(id = R.string.search))
},
active = true,
onActiveChange = {
isSearchActive = it
}
Box(
modifier
.fillMaxSize()
.semantics { isTraversalGroup = true }
) {
onSearchQueryChange?.invoke(query)?.takeIf { it.isNotEmpty() }
?.map { suggestionText -> SearchSuggestionItem(text = suggestionText) }
?: run {
SearchBar(
modifier = Modifier
.align(Alignment.TopCenter)
.semantics { traversalIndex = 0f },
inputField = {
SearchBarDefaults.InputField(
query = textFieldState.text.toString(),
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
onSearch = {
onSearch(textFieldState.text.toString())
expanded = false
},
expanded = expanded,
onExpandedChange = { expanded = it },
placeholder = { Text(text = stringResource(id = R.string.search)) },
modifier = Modifier.padding(horizontal = SpacingExtraSmall)
)
},
expanded = expanded,
onExpandedChange = { expanded = it },
) {
if (searchResults.isEmpty()) {
Box(
modifier = Modifier
.fillMaxHeight()
.fillMaxWidth(),
contentAlignment = Alignment.Center
.fillMaxSize()
.padding(SpacingExtraSmall),
contentAlignment = Alignment.Center,
) {
Column {
Text(text = "╰(°●°╰)")
Text(text = stringResource(id = R.string.search_no_results))
}
}
} else {
LazyColumn {
items(searchResults) { result ->
ListItem(
headlineContent = { SearchSuggestionItem(result) },
modifier = Modifier
.clickable {
textFieldState.edit { replace(0, length, result) }
expanded = false
}
.fillMaxWidth()
)
}
}
}
}
}
}
@ -119,7 +169,8 @@ fun ToolbarPreview() {
Toolbar(
title = "Title",
hasSearch = true,
onSearchQueryChange = { emptyList() },
onSearch = {},
searchResults = emptyList(),
actions = {
TextAction(text = "Action1")
TextAction(text = "Action2")

View file

@ -1,8 +1,11 @@
package org.schabi.newpipe.ui.theme
// Color.kt is generated using the Material theme builder https://material-foundation.github.io/material-theme-builder/
// TODO: Update the colors to properly match the existing color scheme + also add colors schemes for other services
import androidx.compose.ui.graphics.Color
val primaryLight = Color(0xFF904A45)
val primaryLight = Color(0xFFE53935)
val onPrimaryLight = Color(0xFFFFFFFF)
val primaryContainerLight = Color(0xFFFFDAD6)
val onPrimaryContainerLight = Color(0xFF3B0908)
@ -38,8 +41,8 @@ val surfaceContainerLight = Color(0xFFFCEAE8)
val surfaceContainerHighLight = Color(0xFFF6E4E2)
val surfaceContainerHighestLight = Color(0xFFF1DEDC)
val primaryDark = Color(0xFFFFB3AC)
val onPrimaryDark = Color(0xFF571E1B)
val primaryDark = Color(0xFF992722)
val onPrimaryDark = Color(0xFFF4D2D2)
val primaryContainerDark = Color(0xFF73332F)
val onPrimaryContainerDark = Color(0xFFFFDAD6)
val secondaryDark = Color(0xFFE7BDB8)

View file

@ -137,7 +137,7 @@ kotlin-gradle-plugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-p
kotlin-stdlib = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib", version.ref = "kotlin" }
kotlinx-coroutines-rx3 = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-rx3", version.ref = "kotlinxCoroutinesRx3" }
kotlinx-serialization = { group = "org.jetbrains.kotlin", name = "kotlin-serialization", version.ref = "kotlin" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
lazycolumnscrollbar = { group = "com.github.nanihadesuka", name = "LazyColumnScrollbar", version.ref = "lazycolumnscrollbar" }
leakcanary-android-core = { module = "com.squareup.leakcanary:leakcanary-android-core", version.ref = "leakcanary" }
leakcanary-object-watcher = { group = "com.squareup.leakcanary", name = "leakcanary-object-watcher-android", version.ref = "leakcanary" }