diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3d20ceab..9a7b0244 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.apollo) alias(libs.plugins.google.services) alias(libs.plugins.firebase.crashlytics) + alias(libs.plugins.aboutlibraries) } android { @@ -132,6 +133,8 @@ dependencies { implementation(libs.androidx.credentials) implementation(libs.androidx.credentials.play.services.auth) + implementation(libs.aboutlibraries.compose.m3) + testImplementation(libs.junit) testImplementation(libs.robolectric) testImplementation(libs.compose.ui.test.junit4) diff --git a/app/src/main/java/pub/hackers/android/ui/HackersPubApp.kt b/app/src/main/java/pub/hackers/android/ui/HackersPubApp.kt index 05ddb66a..021c2c78 100644 --- a/app/src/main/java/pub/hackers/android/ui/HackersPubApp.kt +++ b/app/src/main/java/pub/hackers/android/ui/HackersPubApp.kt @@ -52,6 +52,7 @@ import pub.hackers.android.ui.screens.editprofile.EditProfileScreen import pub.hackers.android.ui.screens.profile.ProfileScreen import pub.hackers.android.ui.screens.recommendedactors.RecommendedActorsScreen import pub.hackers.android.ui.screens.search.SearchScreen +import pub.hackers.android.ui.screens.licenses.LicensesScreen import pub.hackers.android.ui.screens.settings.SettingsScreen import pub.hackers.android.ui.screens.timeline.TimelineScreen import pub.hackers.android.ui.screens.webview.WebViewScreen @@ -150,6 +151,7 @@ sealed class DetailScreen(val route: String) { return "webview?url=$encoded" } } + data object Licenses : DetailScreen("licenses") } @Composable @@ -445,6 +447,9 @@ fun HackersPubApp( onDraftsClick = { navController.navigate(DetailScreen.Drafts.route) }, + onLicensesClick = { + navController.navigate(DetailScreen.Licenses.route) + }, isLoggedIn = isLoggedIn ) } @@ -667,6 +672,14 @@ fun HackersPubApp( } ) } + + composable(DetailScreen.Licenses.route) { + LicensesScreen( + onNavigateBack = { + navController.popBackStack() + } + ) + } } } } // CompositionLocalProvider diff --git a/app/src/main/java/pub/hackers/android/ui/screens/licenses/LicensesScreen.kt b/app/src/main/java/pub/hackers/android/ui/screens/licenses/LicensesScreen.kt new file mode 100644 index 00000000..78c862f4 --- /dev/null +++ b/app/src/main/java/pub/hackers/android/ui/screens/licenses/LicensesScreen.kt @@ -0,0 +1,54 @@ +package pub.hackers.android.ui.screens.licenses + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +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.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.mikepenz.aboutlibraries.ui.compose.android.produceLibraries +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer +import pub.hackers.android.R + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun LicensesScreen( + onNavigateBack: () -> Unit +) { + Scaffold( + contentWindowInsets = WindowInsets(0), + topBar = { + TopAppBar( + title = { Text(text = stringResource(R.string.licenses)) }, + navigationIcon = { + IconButton(onClick = onNavigateBack) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(R.string.back) + ) + } + } + ) + } + ) { innerPadding -> + val libraries by produceLibraries() + LibrariesContainer( + libraries = libraries, + modifier = Modifier + .fillMaxSize() + .padding(innerPadding), + contentPadding = PaddingValues(vertical = 8.dp) + ) + } +} diff --git a/app/src/main/java/pub/hackers/android/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/pub/hackers/android/ui/screens/settings/SettingsScreen.kt index 5675a1ae..64717636 100644 --- a/app/src/main/java/pub/hackers/android/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/pub/hackers/android/ui/screens/settings/SettingsScreen.kt @@ -17,6 +17,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.Logout import androidx.compose.material.icons.automirrored.outlined.Article +import androidx.compose.material.icons.automirrored.outlined.LibraryBooks import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Fingerprint @@ -66,6 +67,7 @@ fun SettingsScreen( onProfileClick: (String) -> Unit, onNavigateBack: () -> Unit, onDraftsClick: () -> Unit = {}, + onLicensesClick: () -> Unit = {}, isLoggedIn: Boolean, viewModel: SettingsViewModel = hiltViewModel() ) { @@ -386,6 +388,28 @@ fun SettingsScreen( HorizontalDivider(color = colors.divider, thickness = 1.dp) + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { onLicensesClick() } + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Icon( + imageVector = Icons.AutoMirrored.Outlined.LibraryBooks, + contentDescription = null, + tint = colors.textSecondary + ) + Spacer(modifier = Modifier.width(16.dp)) + Text( + text = stringResource(R.string.licenses), + style = typography.bodyLarge, + color = colors.textPrimary + ) + } + + HorizontalDivider(color = colors.divider, thickness = 1.dp) + Row( modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 40e1f422..994613d0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -155,6 +155,7 @@ Dark Dynamic color (Material You) Requires Android 12+ + Open-source Licenses Back diff --git a/build.gradle.kts b/build.gradle.kts index 3505160e..df2e5faa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,6 +6,7 @@ plugins { alias(libs.plugins.apollo) apply false alias(libs.plugins.google.services) apply false alias(libs.plugins.firebase.crashlytics) apply false + alias(libs.plugins.aboutlibraries) apply false } allprojects { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e1bf6f5d..1cc27919 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,6 +27,7 @@ firebaseBom = "34.12.0" paging = "3.4.2" mockk = "1.14.9" turbine = "1.2.1" +aboutLibraries = "14.0.1" [libraries] androidx-browser = { module = "androidx.browser:browser", version.ref = "browser" } @@ -84,6 +85,8 @@ mockk = { group = "io.mockk", name = "mockk", version.ref = "mockk" } turbine = { group = "app.cash.turbine", name = "turbine", version.ref = "turbine" } kotlinx-coroutines-test = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-test", version.ref = "coroutines" } +aboutlibraries-compose-m3 = { group = "com.mikepenz", name = "aboutlibraries-compose-m3", version.ref = "aboutLibraries" } + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } @@ -92,3 +95,4 @@ ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } apollo = { id = "com.apollographql.apollo", version.ref = "apollo" } google-services = { id = "com.google.gms.google-services", version.ref = "googleServices" } firebase-crashlytics = { id = "com.google.firebase.crashlytics", version.ref = "firebaseCrashlyticsPlugin" } +aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutLibraries" }