add settings home ui

This commit is contained in:
Ida Delphine
2026-07-01 15:26:39 +01:00
parent 4f94cc72b7
commit 9ac308ac62
4 changed files with 197 additions and 0 deletions
@@ -34,4 +34,17 @@
<string name="open_in_browser">Open in browser</string>
<string name="done">Done</string>
<string name="not_available">Not available</string>
<!-- SettingsHomeScreen -->
<string name="settings">Settings</string>
<string name="search">Search</string>
<string name="content">Content</string>
<string name="notifications">Notifications</string>
<string name="settings_category_video_audio_title">Video and audio</string>
<string name="settings_category_downloads_title">Download</string>
<string name="settings_category_appearance_title">Appearance</string>
<string name="settings_category_history_title">History and cache</string>
<string name="settings_category_updates_title">Updates</string>
<string name="settings_category_backup_restore_title">Backup and restore</string>
<string name="settings_category_debug_title">Debug</string>
</resources>
@@ -1,2 +1,62 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.composable
import androidx.compose.foundation.clickable
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewWrapper
import net.newpipe.app.preview.ThemePreviewProvider
import newpipe.shared.generated.resources.Res
import newpipe.shared.generated.resources.ic_headset
import newpipe.shared.generated.resources.settings_category_video_audio_title
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
/**
* A row that mirrors the standard AndroidX preference item used in the legacy
* settings screens: 24dp leading icon, title, optional summary, ripple on tap.
*
* @param title Title text of the preference
* @param modifier Modifier applied to the row
* @param icon Leading icon painter; null hides the leading slot (parity with
* `app:iconSpaceReserved="false"`)
* @param summary Optional secondary line under the title (used on sub-screens;
* the settings home currently shows none)
* @param onClick Action executed when the row is tapped
*/
@Composable
fun PreferenceRow(
title: String,
modifier: Modifier = Modifier,
icon: Painter? = null,
summary: String? = null,
onClick: () -> Unit = {}
) {
ListItem(
modifier = modifier.clickable(onClick = onClick),
headlineContent = { Text(text = title) },
supportingContent = summary?.let { text -> { Text(text = text) } },
leadingContent = icon?.let { painter ->
{ Icon(painter = painter, contentDescription = null) }
}
)
}
@PreviewWrapper(ThemePreviewProvider::class)
@PreviewLightDark
@Composable
private fun PreferenceRowPreview() {
PreferenceRow(
title = stringResource(Res.string.settings_category_video_audio_title),
icon = painterResource(Res.drawable.ic_headset)
)
}
@@ -8,6 +8,7 @@ package net.newpipe.app.navigation
import androidx.compose.runtime.mutableStateListOf
import co.touchlab.kermit.Logger
import net.newpipe.app.screen.about.AboutScreen
import net.newpipe.app.screen.settings.SettingsHomeScreen
import org.koin.core.annotation.KoinExperimentalAPI
import org.koin.core.annotation.Provided
import org.koin.core.annotation.Singleton
@@ -1,2 +1,125 @@
/*
* SPDX-FileCopyrightText: 2026 NewPipe e.V. <https://newpipe-ev.de>
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package net.newpipe.app.screen.settings
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.navigationBars
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.tooling.preview.PreviewWrapper
import net.newpipe.app.composable.PreferenceRow
import net.newpipe.app.composable.TopAppBar
import net.newpipe.app.navigation.Navigator
import net.newpipe.app.preview.ThemePreviewProvider
import newpipe.shared.generated.resources.Res
import newpipe.shared.generated.resources.content
import newpipe.shared.generated.resources.ic_bug_report
import newpipe.shared.generated.resources.ic_cloud_download
import newpipe.shared.generated.resources.ic_file_download
import newpipe.shared.generated.resources.ic_headset
import newpipe.shared.generated.resources.ic_history
import newpipe.shared.generated.resources.ic_language
import newpipe.shared.generated.resources.ic_notifications
import newpipe.shared.generated.resources.ic_palette
import newpipe.shared.generated.resources.ic_search
import newpipe.shared.generated.resources.ic_settings_backup_restore
import newpipe.shared.generated.resources.notifications
import newpipe.shared.generated.resources.search
import newpipe.shared.generated.resources.settings
import newpipe.shared.generated.resources.settings_category_appearance_title
import newpipe.shared.generated.resources.settings_category_backup_restore_title
import newpipe.shared.generated.resources.settings_category_debug_title
import newpipe.shared.generated.resources.settings_category_downloads_title
import newpipe.shared.generated.resources.settings_category_history_title
import newpipe.shared.generated.resources.settings_category_updates_title
import newpipe.shared.generated.resources.settings_category_video_audio_title
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.koinInject
data class SettingsCategory(
val title: StringResource,
val icon: DrawableResource,
// TODO: Replace with a Destination once sub-screens are migrated
val onClick: () -> Unit = {}
)
@Composable
fun SettingsHomeScreen(navigator: Navigator = koinInject()) {
SettingsHomeScreenContent(
onNavigateUp = { navigator.navigateUp() }
)
}
@Composable
fun SettingsHomeScreenContent(
categories: List<SettingsCategory> = defaultCategories(),
onNavigateUp: () -> Unit = {},
onSearchClick: () -> Unit = {}
) {
Scaffold(
topBar = {
TopAppBar(
title = stringResource(Res.string.settings),
onNavigateUp = onNavigateUp,
actions = {
IconButton(onClick = onSearchClick) {
Icon(
painter = painterResource(Res.drawable.ic_search),
contentDescription = stringResource(Res.string.search)
)
}
}
)
}
) { paddingValues ->
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(top = paddingValues.calculateTopPadding()),
contentPadding = WindowInsets.navigationBars.asPaddingValues()
) {
items(items = categories) { category ->
PreferenceRow(
title = stringResource(category.title),
icon = painterResource(category.icon),
onClick = category.onClick
)
}
}
}
}
@Composable
private fun defaultCategories(): List<SettingsCategory> = listOf(
SettingsCategory(Res.string.settings_category_video_audio_title, Res.drawable.ic_headset),
SettingsCategory(Res.string.settings_category_downloads_title, Res.drawable.ic_file_download),
SettingsCategory(Res.string.settings_category_appearance_title, Res.drawable.ic_palette),
SettingsCategory(Res.string.settings_category_history_title, Res.drawable.ic_history),
SettingsCategory(Res.string.content, Res.drawable.ic_language),
SettingsCategory(Res.string.notifications, Res.drawable.ic_notifications),
SettingsCategory(Res.string.settings_category_updates_title, Res.drawable.ic_cloud_download),
SettingsCategory(Res.string.settings_category_backup_restore_title, Res.drawable.ic_settings_backup_restore),
SettingsCategory(Res.string.settings_category_debug_title, Res.drawable.ic_bug_report)
)
@PreviewWrapper(ThemePreviewProvider::class)
@PreviewLightDark
@Composable
private fun SettingsHomeScreenPreview() {
SettingsHomeScreenContent()
}