Skip to content

Commit

Permalink
Add open source licenses screen (#338)
Browse files Browse the repository at this point in the history
Recently, I found a great library that provides open-source licenses for all the project dependencies.
Thank you @mikepenz and all the contributors of https://github.com/mikepenz/AboutLibraries.
  • Loading branch information
igorescodro authored Oct 14, 2022
2 parents b8ff87f + 5b983b6 commit cb6c970
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 105 deletions.
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {
id("kotlin-android")
id("com.escodro.kotlin-quality")
id("kotlin-parcelize")
id("com.mikepenz.aboutlibraries.plugin")
}

android {
Expand Down
14 changes: 11 additions & 3 deletions app/src/main/java/com/escodro/alkaa/navigation/NavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.escodro.navigation.DestinationArgs
import com.escodro.navigation.DestinationDeepLink
import com.escodro.navigation.Destinations
import com.escodro.preference.presentation.About
import com.escodro.preference.presentation.OpenSource
import com.escodro.splitinstall.LoadFeature
import com.escodro.task.presentation.add.AddTaskBottomSheet
import com.escodro.task.presentation.detail.main.TaskDetailSection
Expand Down Expand Up @@ -68,6 +69,7 @@ fun NavGraph(startDestination: String = Destinations.Home) {
onTaskClick = actions.openTaskDetail,
onAboutClick = actions.openAbout,
onTrackerClick = actions.openTracker,
onOpenSourceClick = actions.openOpenSourceLicense,
onTaskSheetOpen = actions.openTaskBottomSheet,
onCategorySheetOpen = actions.openCategoryBottomSheet
)
Expand Down Expand Up @@ -101,12 +103,14 @@ fun NavGraph(startDestination: String = Destinations.Home) {
)
}

composable(
route = Destinations.About
) {
composable(route = Destinations.About) {
About(onUpPress = actions.navigateUp)
}

composable(route = Destinations.OpenSource) {
OpenSource(onUpPress = actions.navigateUp)
}

bottomSheet(Destinations.BottomSheet.Task) {
AddTaskBottomSheet(actions.navigateUp)
}
Expand Down Expand Up @@ -164,6 +168,10 @@ internal data class Actions(val navController: NavHostController, val context: C
navController.navigate(Destinations.Tracker)
}

val openOpenSourceLicense: () -> Unit = {
navController.navigate(Destinations.OpenSource)
}

val openTaskBottomSheet: () -> Unit = {
navController.navigate(Destinations.BottomSheet.Task)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ import com.escodro.task.presentation.list.TaskListSection
/**
* Alkaa Home screen.
*/
@Suppress("LongParameterList")
@Composable
fun Home(
onTaskClick: (Long) -> Unit,
onAboutClick: () -> Unit,
onTrackerClick: () -> Unit,
onOpenSourceClick: () -> Unit,
onTaskSheetOpen: () -> Unit,
onCategorySheetOpen: (Long?) -> Unit
) {
Expand All @@ -45,6 +47,7 @@ fun Home(
onTaskClick = onTaskClick,
onAboutClick = onAboutClick,
onTrackerClick = onTrackerClick,
onOpenSourceClick = onOpenSourceClick,
onTaskSheetOpen = onTaskSheetOpen,
onCategorySheetOpen = onCategorySheetOpen,
setCurrentSection = setCurrentSection
Expand Down Expand Up @@ -108,7 +111,8 @@ private fun AlkaaContent(
PreferenceSection(
modifier = modifier,
onAboutClick = actions.onAboutClick,
onTrackerClick = actions.onTrackerClick
onTrackerClick = actions.onTrackerClick,
onOpenSourceClick = actions.onOpenSourceClick
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ internal data class HomeActions(
val onTaskClick: (Long) -> Unit = {},
val onAboutClick: () -> Unit = {},
val onTrackerClick: () -> Unit = {},
val onOpenSourceClick: () -> Unit = {},
val onTaskSheetOpen: () -> Unit = {},
val onCategorySheetOpen: (Long?) -> Unit = {},
val setCurrentSection: (HomeSection) -> Unit = {}
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ buildscript {
dependencies {
classpath(libs.android.gradle.plugin)
classpath(libs.kotlin.gradle.plugin)
classpath(libs.aboutlibraries.plugin)
}
}

Expand Down
1 change: 1 addition & 0 deletions features/preference/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ dependencies {

implementation(libs.koin.android)
implementation(libs.koin.compose)
implementation(libs.aboutlibraries.ui)

testImplementation(projects.libraries.test)
androidTestImplementation(projects.libraries.test)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,13 @@ internal class PreferenceSectionTest {
val itemTracker = context.getString(R.string.preference_title_tracker)
val itemTheme = context.getString(R.string.preference_title_app_theme)
val itemAbout = context.getString(R.string.preference_title_about)
val itemOpenSource = context.getString(R.string.preference_title_open_source)
val itemVersion = context.getString(R.string.preference_title_version)

composeTestRule.onNodeWithText(text = itemTracker, useUnmergedTree = true).assertExists()
composeTestRule.onNodeWithText(text = itemAbout, useUnmergedTree = true).assertExists()
composeTestRule.onNodeWithText(text = itemVersion, useUnmergedTree = true).assertExists()
composeTestRule.onNodeWithText(text = itemOpenSource, useUnmergedTree = true).assertExists()
composeTestRule.onNodeWithText(text = itemTheme, useUnmergedTree = true).assertExists()
}

Expand All @@ -39,6 +41,7 @@ internal class PreferenceSectionTest {
PreferenceContent(
onAboutClick = { },
onTrackerClick = { },
onOpenSourceClick = { },
theme = AppThemeOptions.SYSTEM,
onThemeUpdate = { }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ internal class ThemePreferenceTest {
PreferenceContent(
onAboutClick = { },
onTrackerClick = { },
onOpenSourceClick = {},
theme = theme,
onThemeUpdate = { theme = it }
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.escodro.preference.presentation

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 com.escodro.designsystem.components.AlkaaToolbar
import com.mikepenz.aboutlibraries.ui.compose.LibrariesContainer
import com.mikepenz.aboutlibraries.ui.compose.LibraryDefaults

/**
* Alkaa open source licenses screen.
*/
@Composable
@OptIn(ExperimentalMaterial3Api::class)
fun OpenSource(onUpPress: () -> Unit) {
Scaffold(
topBar = { AlkaaToolbar(onUpPress = onUpPress) },
content = { paddingValues -> OpenSourceContent(modifier = Modifier.padding(paddingValues)) }
)
}

@Composable
private fun OpenSourceContent(modifier: Modifier) {
LibrariesContainer(
modifier = modifier.fillMaxSize(),
colors = LibraryDefaults.libraryColors(
backgroundColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
badgeContentColor = MaterialTheme.colorScheme.onPrimary,
badgeBackgroundColor = MaterialTheme.colorScheme.primary
),
onLibraryClick = {} // Library is not working properly and crashing when clicked
)
}
Original file line number Diff line number Diff line change
@@ -1,58 +1,46 @@
package com.escodro.preference.presentation

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.escodro.core.extension.getVersionName
import com.escodro.core.extension.openUrl
import com.escodro.designsystem.AlkaaTheme
import com.escodro.preference.R
import com.escodro.preference.model.AppThemeOptions
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter
import org.koin.androidx.compose.getViewModel
import java.util.Locale

/**
* Alkaa Preference Section.
*
* @param modifier the decorator
* @param onAboutClick function to be called when the about item is clicked
* @param onTrackerClick function to be called when the tracker item is clicked
* @param onOpenSourceClick function to be called when the open source item is clicked
*/
@Composable
fun PreferenceSection(
modifier: Modifier = Modifier,
onAboutClick: () -> Unit,
onTrackerClick: () -> Unit
onTrackerClick: () -> Unit,
onOpenSourceClick: () -> Unit
) {
PreferenceLoader(
modifier = modifier,
onAboutClick = onAboutClick,
onTrackerClick = onTrackerClick
onTrackerClick = onTrackerClick,
onOpenSourceClick = onOpenSourceClick
)
}

Expand All @@ -61,6 +49,7 @@ private fun PreferenceLoader(
modifier: Modifier = Modifier,
onAboutClick: () -> Unit,
onTrackerClick: () -> Unit,
onOpenSourceClick: () -> Unit,
viewModel: PreferenceViewModel = getViewModel()
) {
val theme by remember(viewModel) {
Expand All @@ -71,16 +60,19 @@ private fun PreferenceLoader(
modifier = modifier,
onAboutClick = onAboutClick,
onTrackerClick = onTrackerClick,
onOpenSourceClick = onOpenSourceClick,
theme = theme,
onThemeUpdate = viewModel::updateTheme
)
}

@Suppress("LongParameterList")
@Composable
internal fun PreferenceContent(
modifier: Modifier = Modifier,
onAboutClick: () -> Unit,
onTrackerClick: () -> Unit,
onOpenSourceClick: () -> Unit,
theme: AppThemeOptions,
onThemeUpdate: (AppThemeOptions) -> Unit
) {
Expand All @@ -90,90 +82,12 @@ internal fun PreferenceContent(
Separator()
PreferenceTitle(title = stringResource(id = R.string.preference_title_settings))
ThemeItem(currentTheme = theme, onThemeUpdate = onThemeUpdate)
AboutItem(onAboutClick)
AboutItem(onAboutClick = onAboutClick)
OpenSourceLibraryItem(onOpenSourceClick = onOpenSourceClick)
VersionItem()
}
}

@Composable
private fun PreferenceTitle(title: String) {
Box(
modifier = Modifier
.fillMaxWidth()
.padding(start = 32.dp, end = 16.dp)
.height(32.dp),
contentAlignment = Alignment.CenterStart
) {
Text(
text = title.uppercase(Locale.getDefault()),
style = MaterialTheme.typography.bodyMedium.copy(fontWeight = FontWeight.Bold),
color = MaterialTheme.colorScheme.primary
)
}
}

@Composable
private fun TrackerItem(onTrackerClick: () -> Unit) {
PreferenceItem(
title = stringResource(id = R.string.preference_title_tracker),
onItemClick = onTrackerClick
)
}

@Composable
@Suppress("MagicNumber")
private fun VersionItem() {
val title = stringResource(id = R.string.preference_title_version)
val context = LocalContext.current
val version = context.getVersionName()
var numberOfClicks by remember { mutableStateOf(0) }
val onClick = {
if (++numberOfClicks == 7) {
context.openUrl(EasterEggUrl)
}
}

LaunchedEffect(Unit) {
snapshotFlow { numberOfClicks }
.filter { it > 0 }
.collectLatest {
delay(1_000)
numberOfClicks = 0
}
}

PreferenceItem(title = title, description = version, onItemClick = onClick)
}

@Composable
private fun AboutItem(onAboutClick: () -> Unit) {
PreferenceItem(
title = stringResource(id = R.string.preference_title_about),
onItemClick = onAboutClick
)
}

@Composable
private fun ThemeItem(
currentTheme: AppThemeOptions,
onThemeUpdate: (AppThemeOptions) -> Unit
) {
var isDialogOpen by remember { mutableStateOf(false) }

PreferenceItem(
title = stringResource(id = R.string.preference_title_app_theme),
description = stringResource(id = currentTheme.titleRes),
onItemClick = { isDialogOpen = true }
)

AppThemeDialog(
isDialogOpen = isDialogOpen,
onDismissRequest = { isDialogOpen = false },
currentTheme = currentTheme,
onThemeUpdate = onThemeUpdate
)
}

@Composable
private fun Separator() {
Spacer(
Expand All @@ -185,13 +99,11 @@ private fun Separator() {
)
}

private const val EasterEggUrl = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

@Suppress("UndocumentedPublicFunction")
@Preview
@Composable
fun PreferencePreview() {
AlkaaTheme {
PreferenceSection(onAboutClick = {}, onTrackerClick = {})
PreferenceSection(onAboutClick = {}, onTrackerClick = {}, onOpenSourceClick = {})
}
}
Loading

0 comments on commit cb6c970

Please sign in to comment.