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" }