feat: update aboutlibraries, refine oss screen
This commit is contained in:
parent
02050172f2
commit
779275ce62
|
|
@ -9,6 +9,7 @@ plugins {
|
||||||
alias(libs.plugins.kotlin.serialization)
|
alias(libs.plugins.kotlin.serialization)
|
||||||
alias(libs.plugins.kotlin.compose)
|
alias(libs.plugins.kotlin.compose)
|
||||||
alias(libs.plugins.aboutlibraries)
|
alias(libs.plugins.aboutlibraries)
|
||||||
|
alias(libs.plugins.aboutlibraries.android)
|
||||||
alias(libs.plugins.ksp)
|
alias(libs.plugins.ksp)
|
||||||
alias(libs.plugins.sentry.android)
|
alias(libs.plugins.sentry.android)
|
||||||
alias(libs.plugins.sqldelight)
|
alias(libs.plugins.sqldelight)
|
||||||
|
|
@ -130,6 +131,7 @@ android {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
compose = true
|
compose = true
|
||||||
buildConfig = true
|
buildConfig = true
|
||||||
|
resValues = true
|
||||||
}
|
}
|
||||||
packaging {
|
packaging {
|
||||||
resources {
|
resources {
|
||||||
|
|
@ -279,10 +281,9 @@ dependencies {
|
||||||
}
|
}
|
||||||
|
|
||||||
aboutLibraries {
|
aboutLibraries {
|
||||||
additionalLicenses += listOf("ofl")
|
license {
|
||||||
includePlatform = true
|
|
||||||
strictMode = StrictMode.FAIL
|
strictMode = StrictMode.FAIL
|
||||||
allowedLicenses += listOf(
|
allowedLicenses.addAll(
|
||||||
"Apache-2.0",
|
"Apache-2.0",
|
||||||
"ASDKL",
|
"ASDKL",
|
||||||
"BSD-2-Clause",
|
"BSD-2-Clause",
|
||||||
|
|
@ -295,7 +296,13 @@ aboutLibraries {
|
||||||
"OFL",
|
"OFL",
|
||||||
"Public Domain"
|
"Public Domain"
|
||||||
)
|
)
|
||||||
configPath = "compliance"
|
additionalLicenses.addAll("ofl")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect {
|
||||||
|
includePlatform = true
|
||||||
|
configPath = file("../compliance")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sqldelight {
|
sqldelight {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,24 @@
|
||||||
package chat.stoat.composables.screens.settings
|
package chat.stoat.composables.screens.settings
|
||||||
|
|
||||||
|
import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.core.net.toUri
|
||||||
import chat.stoat.R
|
import chat.stoat.R
|
||||||
import chat.stoat.screens.about.Library
|
import chat.stoat.screens.about.Library
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AttributionItem(library: Library, onClick: () -> Unit) {
|
fun AttributionItem(library: Library, onClick: () -> Unit) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -22,6 +30,21 @@ fun AttributionItem(library: Library, onClick: () -> Unit) {
|
||||||
text = stringResource(id = R.string.oss_attribution_tap_to_view_license)
|
text = stringResource(id = R.string.oss_attribution_tap_to_view_license)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
trailingContent = {
|
||||||
|
library.website?.let { website ->
|
||||||
|
IconButton(onClick = {
|
||||||
|
val customTab = CustomTabsIntent
|
||||||
|
.Builder()
|
||||||
|
.build()
|
||||||
|
customTab.launchUrl(context, website.toUri())
|
||||||
|
}) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(id = R.drawable.ic_open_in_new_24dp),
|
||||||
|
contentDescription = stringResource(id = R.string.oss_attribution_open_library_website)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable(onClick = onClick)
|
.clickable(onClick = onClick)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package chat.stoat.screens.about
|
package chat.stoat.screens.about
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
|
@ -30,17 +31,18 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
import androidx.compose.runtime.mutableIntStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.platform.ClipboardManager
|
import androidx.compose.ui.platform.LocalClipboard
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.platform.toClipEntry
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
|
@ -134,22 +136,9 @@ fun DebugInfo(viewModel: AboutViewModel) {
|
||||||
@Composable
|
@Composable
|
||||||
fun AboutScreen(navController: NavController, viewModel: AboutViewModel = viewModel()) {
|
fun AboutScreen(navController: NavController, viewModel: AboutViewModel = viewModel()) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val clipboardManager: ClipboardManager =
|
val resources = LocalResources.current
|
||||||
LocalClipboardManager.current
|
val clipboard = LocalClipboard.current
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
fun copyDebugInformation() {
|
|
||||||
clipboardManager.setText(
|
|
||||||
AnnotatedString(StoatJson.encodeToString(viewModel.getDebugInformation()))
|
|
||||||
)
|
|
||||||
|
|
||||||
if (Platform.needsShowClipboardNotification()) {
|
|
||||||
Toast.makeText(
|
|
||||||
context,
|
|
||||||
context.getString(R.string.copied),
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = {
|
topBar = {
|
||||||
|
|
@ -248,7 +237,24 @@ fun AboutScreen(navController: NavController, viewModel: AboutViewModel = viewMo
|
||||||
|
|
||||||
1 -> {
|
1 -> {
|
||||||
DebugInfo(viewModel)
|
DebugInfo(viewModel)
|
||||||
TextButton(onClick = ::copyDebugInformation) {
|
TextButton(onClick = {
|
||||||
|
scope.launch {
|
||||||
|
clipboard.setClipEntry(
|
||||||
|
ClipData.newPlainText(
|
||||||
|
"Stoat Debug Information",
|
||||||
|
StoatJson.encodeToString(viewModel.getDebugInformation())
|
||||||
|
).toClipEntry()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (Platform.needsShowClipboardNotification()) {
|
||||||
|
Toast.makeText(
|
||||||
|
context,
|
||||||
|
resources.getString(R.string.copied),
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) {
|
||||||
Text(text = stringResource(id = R.string.copy))
|
Text(text = stringResource(id = R.string.copy))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,8 @@
|
||||||
package chat.stoat.screens.about
|
package chat.stoat.screens.about
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
|
@ -16,7 +13,6 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.LargeTopAppBar
|
import androidx.compose.material3.LargeTopAppBar
|
||||||
import androidx.compose.material3.LocalContentColor
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.ModalBottomSheet
|
import androidx.compose.material3.ModalBottomSheet
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
|
@ -30,12 +26,10 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalResources
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
|
@ -47,16 +41,10 @@ import kotlinx.serialization.json.JsonArray
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AboutLibraries(
|
data class AboutLibraries(
|
||||||
val metadata: Metadata,
|
|
||||||
val libraries: List<Library>,
|
val libraries: List<Library>,
|
||||||
val licenses: Map<String, License>
|
val licenses: Map<String, License>
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Metadata(
|
|
||||||
val generated: String
|
|
||||||
)
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class License(
|
data class License(
|
||||||
val content: String? = null,
|
val content: String? = null,
|
||||||
|
|
@ -105,13 +93,13 @@ data class Scm(
|
||||||
fun AttributionScreen(navController: NavController) {
|
fun AttributionScreen(navController: NavController) {
|
||||||
var libraries by remember { mutableStateOf<AboutLibraries?>(null) }
|
var libraries by remember { mutableStateOf<AboutLibraries?>(null) }
|
||||||
|
|
||||||
val context = LocalContext.current
|
val resources = LocalResources.current
|
||||||
|
|
||||||
var licenceSheetOpen by remember { mutableStateOf(false) }
|
var licenceSheetOpen by remember { mutableStateOf(false) }
|
||||||
var licenseSheetTarget by remember { mutableStateOf("") }
|
var licenseSheetTarget by remember { mutableStateOf("") }
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
context.resources.openRawResource(R.raw.aboutlibraries).use { stream ->
|
resources.openRawResource(R.raw.aboutlibraries).use { stream ->
|
||||||
val text = stream.bufferedReader().use { it.readText() }
|
val text = stream.bufferedReader().use { it.readText() }
|
||||||
libraries = Json.decodeFromString(AboutLibraries.serializer(), text)
|
libraries = Json.decodeFromString(AboutLibraries.serializer(), text)
|
||||||
}
|
}
|
||||||
|
|
@ -181,37 +169,6 @@ fun AttributionScreen(navController: NavController) {
|
||||||
Box(Modifier.padding(pv)) {
|
Box(Modifier.padding(pv)) {
|
||||||
libraries?.let {
|
libraries?.let {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
item {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(16.dp)
|
|
||||||
.clip(MaterialTheme.shapes.medium)
|
|
||||||
.background(MaterialTheme.colorScheme.surfaceContainer)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.oss_attribution_body)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.oss_attribution_body_2)
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.oss_attribution_warning),
|
|
||||||
color = MaterialTheme.colorScheme.error
|
|
||||||
)
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = stringResource(
|
|
||||||
R.string.oss_attribution_generation_date,
|
|
||||||
libraries?.metadata?.generated ?: ""
|
|
||||||
),
|
|
||||||
color = LocalContentColor.current.copy(alpha = 0.6f)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
items(
|
items(
|
||||||
items = it.libraries.sortedBy { library -> library.name }
|
items = it.libraries.sortedBy { library -> library.name }
|
||||||
) { library ->
|
) { library ->
|
||||||
|
|
@ -220,16 +177,6 @@ fun AttributionScreen(navController: NavController) {
|
||||||
licenseSheetTarget = library.licenses.firstOrNull() ?: ""
|
licenseSheetTarget = library.licenses.firstOrNull() ?: ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item(key = "cat") {
|
|
||||||
Text(
|
|
||||||
text = "🐈",
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(16.dp),
|
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="960"
|
||||||
|
android:viewportHeight="960"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:autoMirrored="true">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M200,840Q167,840 143.5,816.5Q120,793 120,760L120,200Q120,167 143.5,143.5Q167,120 200,120L480,120L480,200L200,200Q200,200 200,200Q200,200 200,200L200,760Q200,760 200,760Q200,760 200,760L760,760Q760,760 760,760Q760,760 760,760L760,480L840,480L840,760Q840,793 816.5,816.5Q793,840 760,840L200,840ZM388,628L332,572L704,200L560,200L560,120L840,120L840,400L760,400L760,256L388,628Z"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -90,12 +90,9 @@
|
||||||
<string name="about_tab_version">Version</string>
|
<string name="about_tab_version">Version</string>
|
||||||
<string name="about_tab_details">Details</string>
|
<string name="about_tab_details">Details</string>
|
||||||
|
|
||||||
<string name="oss_attribution">OSS Attribution</string>
|
<string name="oss_attribution">OSS Licenses</string>
|
||||||
<string name="oss_attribution_body">Stoat is built with the help of these awesome open-source projects.</string>
|
|
||||||
<string name="oss_attribution_body_2">We\'re grateful to the developers of these projects for making their work available to the world.</string>
|
|
||||||
<string name="oss_attribution_warning">The list below is automatically generated. It may be incomplete or inaccurate.</string>
|
|
||||||
<string name="oss_attribution_generation_date">Last updated: %1$s</string>
|
|
||||||
<string name="oss_attribution_tap_to_view_license">Tap to view license</string>
|
<string name="oss_attribution_tap_to_view_license">Tap to view license</string>
|
||||||
|
<string name="oss_attribution_open_library_website">Open library website</string>
|
||||||
|
|
||||||
<string name="comingsoon_toast">Sorry, this feature is not ready yet.</string>
|
<string name="comingsoon_toast">Sorry, this feature is not ready yet.</string>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ plugins {
|
||||||
alias(libs.plugins.kotlin.compose) apply false
|
alias(libs.plugins.kotlin.compose) apply false
|
||||||
alias(libs.plugins.kotlin.jvm) apply false
|
alias(libs.plugins.kotlin.jvm) apply false
|
||||||
alias(libs.plugins.aboutlibraries) apply false
|
alias(libs.plugins.aboutlibraries) apply false
|
||||||
|
alias(libs.plugins.aboutlibraries.android) apply false
|
||||||
alias(libs.plugins.ksp) apply false
|
alias(libs.plugins.ksp) apply false
|
||||||
alias(libs.plugins.google.services) apply false
|
alias(libs.plugins.google.services) apply false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ lifecycle = "2.10.0"
|
||||||
accompanist = "0.37.3"
|
accompanist = "0.37.3"
|
||||||
ktor = "3.4.1"
|
ktor = "3.4.1"
|
||||||
glide = "5.0.5"
|
glide = "5.0.5"
|
||||||
aboutlibraries = "11.3.0-rc02"
|
aboutlibraries = "15.0.0-a02"
|
||||||
media3 = "1.9.2"
|
media3 = "1.9.2"
|
||||||
telephoto = "1.0.0-alpha02"
|
telephoto = "1.0.0-alpha02"
|
||||||
haze = "1.7.2"
|
haze = "1.7.2"
|
||||||
|
|
@ -110,6 +110,7 @@ kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi
|
||||||
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" }
|
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin", version.ref = "aboutlibraries" }
|
||||||
|
aboutlibraries-android = { id = "com.mikepenz.aboutlibraries.plugin.android", version.ref = "aboutlibraries" }
|
||||||
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
|
||||||
google-services = { id = "com.google.gms.google-services", version.ref = "google-services" }
|
google-services = { id = "com.google.gms.google-services", version.ref = "google-services" }
|
||||||
sentry-android = { id = "io.sentry.android.gradle", version = "6.5.0" }
|
sentry-android = { id = "io.sentry.android.gradle", version = "6.5.0" }
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue