Skip to content

Commit

Permalink
feat: show open source libraries licenses in settings (#256)
Browse files Browse the repository at this point in the history
  • Loading branch information
David Ly authored and lydavid committed Jul 18, 2023
1 parent c3f8d33 commit 68ff611
Show file tree
Hide file tree
Showing 14 changed files with 191 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.testing.HiltAndroidTest
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.test.runTest
import ly.david.data.network.MusicBrainzResource
import ly.david.data.network.resourceUri
Expand Down Expand Up @@ -52,7 +53,7 @@ internal class CollectionListScaffoldTest : MainActivityTest(), StringReferences
}

@Test
fun createCollections() = runTest {
fun createCollections() = runTest(timeout = 15.seconds) {
composeTestRule
.onNodeWithText(collections)
.performClick()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.testing.HiltAndroidTest
import javax.inject.Inject
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.test.runTest
import ly.david.data.network.MusicBrainzResource
import ly.david.data.network.collectableResources
Expand Down Expand Up @@ -66,7 +67,7 @@ internal class CollectionParameterizedTest(
}

@Test
fun onlyLocalCollections() = runTest {
fun onlyLocalCollections() = runTest(timeout = 15.seconds) {
composeTestRule
.onNodeWithText(collections)
.performClick()
Expand Down
14 changes: 13 additions & 1 deletion app/src/main/java/ly/david/mbjc/ui/navigation/NavigationGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import ly.david.mbjc.ui.series.SeriesScaffold
import ly.david.mbjc.ui.work.WorkScaffold
import ly.david.ui.common.R
import ly.david.ui.history.HistoryScaffold
import ly.david.ui.settings.SettingsScaffold
import ly.david.ui.settings.licenses.LicensesScaffold

private const val ID = "id"
private const val TITLE = "title"
Expand Down Expand Up @@ -355,6 +357,7 @@ internal fun NavigationGraph(

val onSettingsClick: (Destination) -> Unit = { destination ->
when (destination) {
Destination.SETTINGS_LICENSES,
Destination.EXPERIMENTAL_SPOTIFY -> {
navController.goTo(destination)
}
Expand All @@ -368,7 +371,7 @@ internal fun NavigationGraph(
composable(
Destination.SETTINGS.route
) {
ly.david.ui.settings.SettingsScaffold(
SettingsScaffold(
modifier = modifier,
onDestinationClick = { destination ->
onSettingsClick(destination)
Expand All @@ -382,6 +385,15 @@ internal fun NavigationGraph(
)
}

composable(
Destination.SETTINGS_LICENSES.route
) {
LicensesScaffold(
modifier = modifier,
onBack = navController::navigateUp
)
}

composable(
Destination.EXPERIMENTAL_SPOTIFY.route
) {
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ plugins {
id("com.google.firebase.crashlytics") version "2.9.6" apply false
id("dev.iurysouza.modulegraph") version "0.4.0"
id("app.cash.paparazzi") version "1.2.0" apply false
id("com.mikepenz.aboutlibraries.plugin") version "10.8.0" apply true
}

allprojects {
apply(plugin = "io.gitlab.arturbosch.detekt")
apply(plugin = "com.mikepenz.aboutlibraries.plugin")

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ private const val TOP_LEVEL_COLLECTIONS = "collections"
private const val TOP_LEVEL_SETTINGS = "settings"

private const val EXPERIMENTAL = "experimental"
private const val LICENSES = "licenses"

/**
* This divider should be the same used for dividing parameters such as {artistId} passed to navigation.
Expand Down Expand Up @@ -54,7 +55,7 @@ enum class Destination(val route: String) {
COLLECTIONS(TOP_LEVEL_COLLECTIONS),

SETTINGS(TOP_LEVEL_SETTINGS),

SETTINGS_LICENSES("$TOP_LEVEL_SETTINGS$DIVIDER$LICENSES"),
EXPERIMENTAL_SPOTIFY("$TOP_LEVEL_SETTINGS$DIVIDER$EXPERIMENTAL$DIVIDER" + "SPOTIFY")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ data class ReleaseForListItem(
@ColumnInfo("artist_credit_names")
val artistCreditNames: String?,

// TODO: we've lost the ability to filter on this field
@Relation(
entity = ReleaseFormatTrackCount::class,
parentColumn = "id",
Expand Down
4 changes: 4 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ dependencyResolutionManagement {
versionCatalogs {
create("libs") {

version("aboutlibraries", "10.8.0")
version("accompanist", "0.30.1")
version("coil", "2.4.0")
version("compose-compiler", "1.4.7")
Expand All @@ -29,6 +30,9 @@ dependencyResolutionManagement {
version("retrofit", "2.9.0")
version("room", "2.5.2")

library("aboutlibraries-compose", "com.mikepenz", "aboutlibraries-compose").versionRef("aboutlibraries")
library("aboutlibraries-core", "com.mikepenz", "aboutlibraries-core").versionRef("aboutlibraries")

library("accompanist-swiperefresh", "com.google.accompanist", "accompanist-swiperefresh").versionRef("accompanist")
library("accompanist-pager", "com.google.accompanist", "accompanist-pager").versionRef("accompanist")

Expand Down
2 changes: 2 additions & 0 deletions ui/common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,6 @@
<string name="name">Name</string>
<string name="collection_name_placeholder">Enter name</string>
<string name="add_to_collection">Add to collection</string>

<string name="open_source_licenses">Open source licenses</string>
</resources>
3 changes: 3 additions & 0 deletions ui/settings/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ dependencies {
implementation(projects.dataAndroid)
implementation(projects.ui.common)

implementation(libs.aboutlibraries.compose)
implementation(libs.aboutlibraries.core)

implementation(libs.androidx.paging.compose)
implementation(libs.androidx.datastore.preferences)
implementation(libs.androidx.paging.runtime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import ly.david.ui.common.preview.DefaultPreviews
import ly.david.ui.common.text.TextWithHeading
import ly.david.ui.common.theme.PreviewTheme
import ly.david.ui.common.topappbar.ScrollableTopAppBar
import ly.david.ui.settings.components.ClickableItem
import ly.david.ui.settings.components.ProfileCard
import ly.david.ui.settings.components.SettingSwitch
import ly.david.ui.settings.components.SettingWithDialogChoices
Expand Down Expand Up @@ -125,6 +126,13 @@ fun SettingsScreen(
onCheckedChange = onSortReleaseGroupListItemsChange
)

ClickableItem(
text = stringResource(id = R.string.open_source_licenses),
onClick = {
onDestinationClick(Destination.SETTINGS_LICENSES)
}
)

val versionKey = stringResource(id = R.string.app_version)
val versionName = BuildConfig.VERSION_NAME
val versionCode = BuildConfig.VERSION_CODE.toString()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ly.david.ui.settings.components

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material3.Icon
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import ly.david.ui.common.preview.DefaultPreviews
import ly.david.ui.common.theme.PreviewTheme
import ly.david.ui.common.theme.TextStyles

@Composable
internal fun ClickableItem(
text: String,
onClick: () -> Unit = {}
) {
Row(
modifier = Modifier
.fillMaxWidth()
.clickable { onClick() }
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = text,
style = TextStyles.getCardBodyTextStyle()
)

Spacer(modifier = Modifier.weight(1f))

Icon(imageVector = Icons.Default.ChevronRight, contentDescription = null)
}
}

@DefaultPreviews
@Composable
internal fun PreviewClickableItem() {
PreviewTheme {
Surface {
ClickableItem(
text = "Click me"
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal fun ProfileCard(

@DefaultPreviews
@Composable
private fun LoggedOut() {
internal fun PreviewProfileCardLoggedOut() {
PreviewTheme {
Surface {
ProfileCard(
Expand All @@ -95,7 +95,7 @@ private fun LoggedOut() {

@DefaultPreviews
@Composable
private fun LoggedIn() {
internal fun PreviewProfileCardLoggedIn() {
PreviewTheme {
Surface {
ProfileCard(
Expand All @@ -108,7 +108,7 @@ private fun LoggedIn() {

@DefaultPreviews
@Composable
private fun LoggedInWaitingForUsername() {
internal fun PreviewProfileCardLoggedInWaitingForUsername() {
PreviewTheme {
Surface {
ProfileCard(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ly.david.ui.settings.licenses

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer
import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults
import ly.david.ui.common.R
import ly.david.ui.common.topappbar.ScrollableTopAppBar

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LicensesScaffold(
modifier: Modifier = Modifier,
onBack: () -> Unit = {},
) {
Scaffold(
modifier = modifier,
topBar = {
ScrollableTopAppBar(
onBack = onBack,
title = stringResource(id = R.string.open_source_licenses),
)
},
) { innerPadding ->

LibrariesContainer(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
colors = LibraryDefaults.libraryColors(
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
badgeBackgroundColor = MaterialTheme.colorScheme.primary,
badgeContentColor = MaterialTheme.colorScheme.onPrimary
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package ly.david.ui.settings

import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Paparazzi
import com.android.ide.common.rendering.api.SessionParams
import com.android.resources.NightMode
import com.google.testing.junit.testparameterinjector.TestParameter
import com.google.testing.junit.testparameterinjector.TestParameterInjector
import ly.david.ui.common.theme.PreviewTheme
import org.junit.Rule
import org.junit.runner.RunWith

private const val PAPARAZZI_THEME = "android:Theme.Material.Light.NoActionBar"

/**
* Common setup for running screenshot tests on light and dark mode.
*/
@RunWith(TestParameterInjector::class)
abstract class PaparazziScreenshotTest(
private val isFullScreen: Boolean = false
) {

@TestParameter
private lateinit var nightMode: NightMode

// Note we cannot override junit Rule
@get:Rule
val paparazzi: Paparazzi by lazy {
Paparazzi(
deviceConfig = DeviceConfig.PIXEL_5.copy(nightMode = nightMode),
theme = PAPARAZZI_THEME,
renderingMode = if (isFullScreen) {
SessionParams.RenderingMode.NORMAL
} else {
SessionParams.RenderingMode.SHRINK
},
showSystemUi = false
)
}

protected fun snapshot(content: @Composable () -> Unit) {
paparazzi.snapshot {
PreviewTheme {
Surface {
content()
}
}
}
}
}

0 comments on commit 68ff611

Please sign in to comment.