diff --git a/app/build.gradle b/app/build.gradle
index 97c13b726a..6de1814b36 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,6 +4,7 @@ plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.protobuf'
+ id 'com.google.android.gms.oss-licenses-plugin'
id 'androidx.navigation.safeargs'
id 'org.jlleitschuh.gradle.ktlint'
id 'org.jetbrains.kotlin.android'
@@ -467,6 +468,7 @@ dependencies {
implementation libs.androidx.legacy.preference
implementation libs.androidx.gridlayout
implementation libs.androidx.exifinterface
+ implementation libs.androidx.compose.rxjava3
implementation libs.androidx.constraintlayout
implementation libs.androidx.multidex
implementation libs.androidx.navigation.fragment.ktx
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/HelpSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/HelpSettingsFragment.kt
index 18fdb91cde..3f673a5f29 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/HelpSettingsFragment.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/HelpSettingsFragment.kt
@@ -44,6 +44,13 @@ class HelpSettingsFragment : DSLSettingsFragment(R.string.preferences__help) {
}
)
+ clickPref(
+ title = DSLSettingsText.from(R.string.HelpSettingsFragment__licenses),
+ onClick = {
+ Navigation.findNavController(requireView()).safeNavigate(R.id.action_helpSettingsFragment_to_licenseFragment)
+ }
+ )
+
externalLinkPref(
title = DSLSettingsText.from(R.string.HelpSettingsFragment__terms_amp_privacy_policy),
linkId = R.string.terms_and_privacy_policy_url
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/LicenseFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/LicenseFragment.kt
new file mode 100644
index 0000000000..700c4fe212
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/help/LicenseFragment.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2023 Signal Messenger, LLC
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+package org.thoughtcrime.securesms.components.settings.app.help
+
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.rememberScrollState
+import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.rxjava3.subscribeAsState
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.painterResource
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.navigation.fragment.findNavController
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
+import io.reactivex.rxjava3.core.Single
+import io.reactivex.rxjava3.schedulers.Schedulers
+import org.signal.core.ui.Scaffolds
+import org.signal.core.util.logging.Log
+import org.thoughtcrime.securesms.R
+import org.thoughtcrime.securesms.compose.ComposeFragment
+
+class LicenseFragment : ComposeFragment() {
+ private val TAG = Log.tag(LicenseFragment::class.java)
+
+ @Composable
+ override fun FragmentContent() {
+ val textState: State = Single.fromCallable {
+ requireContext().resources.openRawResource(R.raw.third_party_licenses).bufferedReader().use { it.readText() }
+ }
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribeAsState(initial = "")
+ Scaffolds.Settings(
+ title = stringResource(id = R.string.HelpSettingsFragment__licenses),
+ onNavigationClick = findNavController()::popBackStack,
+ navigationIconPainter = painterResource(id = R.drawable.ic_arrow_left_24),
+ navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
+ ) {
+ LicenseScreen(licenseText = textState.value, modifier = Modifier.padding(it))
+ }
+ }
+}
+
+@Composable
+fun LicenseScreen(licenseText: String, modifier: Modifier = Modifier) {
+ Column(
+ modifier = modifier
+ .padding(horizontal = 24.dp)
+ .verticalScroll(rememberScrollState())
+ ) {
+ Text(
+ text = licenseText,
+ style = MaterialTheme.typography.bodyMedium,
+ modifier = Modifier.padding(vertical = 16.dp)
+ )
+ }
+}
+
+@Preview
+@Composable
+fun LicenseFragmentPreview() {
+ LicenseScreen("Lorem ipsum")
+}
diff --git a/app/src/main/res/navigation/app_settings.xml b/app/src/main/res/navigation/app_settings.xml
index fed1e0d2bf..779d0bff96 100644
--- a/app/src/main/res/navigation/app_settings.xml
+++ b/app/src/main/res/navigation/app_settings.xml
@@ -409,6 +409,13 @@
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
+
+
+
Contact us
Version
Debug log
+
+ Licenses
Terms & Privacy Policy
Copyright Signal Messenger
Licensed under the GNU AGPLv3
diff --git a/build.gradle b/build.gradle
index a825500cdb..8e3c50d86c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -21,6 +21,7 @@ buildscript {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.5.3'
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.17'
+ classpath 'com.google.android.gms:oss-licenses-plugin:0.10.6'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath libs.ktlint
classpath 'app.cash.exhaustive:exhaustive-gradle:0.1.1'
diff --git a/dependencies.gradle b/dependencies.gradle
index 3ef870618f..94db4f98b5 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -27,6 +27,7 @@ dependencyResolutionManagement {
alias('androidx-compose-material3').to('androidx.compose.material3', 'material3').withoutVersion()
alias('androidx-compose-ui-tooling-preview').to('androidx.compose.ui', 'ui-tooling-preview').withoutVersion()
alias('androidx-compose-ui-tooling-core').to('androidx.compose.ui', 'ui-tooling').withoutVersion()
+ alias('androidx-compose-rxjava3').to('androidx.compose.runtime:runtime-rxjava3:1.4.2')
alias('ktlint-twitter-compose').to('com.twitter.compose.rules:ktlint:0.0.26')
// Accompanist
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 92d0306b48..560fb0028e 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -572,6 +572,22 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -593,6 +609,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
+
+
+
+
+
+
+
+
@@ -3103,6 +3127,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
+
+
+
+
+
@@ -3416,6 +3445,11 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
+
+
+
+
+