mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-02-02 12:19:16 +00:00
Use AboutLibraries to display library information
This commit is contained in:
parent
6d05af484e
commit
4758244cf5
@ -9,6 +9,8 @@ plugins {
|
||||
id "kotlin-parcelize"
|
||||
id "checkstyle"
|
||||
id "org.sonarqube" version "4.0.0.2929"
|
||||
id "org.jetbrains.kotlin.plugin.compose" version "${kotlin_version}"
|
||||
id 'com.mikepenz.aboutlibraries.plugin'
|
||||
}
|
||||
|
||||
android {
|
||||
@ -104,10 +106,6 @@ android {
|
||||
'META-INF/COPYRIGHT']
|
||||
}
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.5.14"
|
||||
}
|
||||
}
|
||||
|
||||
ext {
|
||||
@ -293,6 +291,9 @@ dependencies {
|
||||
implementation 'androidx.compose.ui:ui-text:1.7.0-beta05' // Needed for parsing HTML to AnnotatedString
|
||||
implementation 'com.github.nanihadesuka:LazyColumnScrollbar:2.2.0'
|
||||
|
||||
// Library loading for About screen
|
||||
implementation "com.mikepenz:aboutlibraries-compose-m3:$about_libs"
|
||||
|
||||
/** Debugging **/
|
||||
// Memory leak detection
|
||||
debugImplementation "com.squareup.leakcanary:leakcanary-object-watcher-android:${leakCanaryVersion}"
|
||||
|
@ -1,28 +0,0 @@
|
||||
package org.schabi.newpipe.ui.components.about
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
class AboutData(
|
||||
@StringRes val title: Int,
|
||||
@StringRes val description: Int,
|
||||
@StringRes val buttonText: Int,
|
||||
@StringRes val url: Int
|
||||
)
|
||||
|
||||
/**
|
||||
* Class for storing information about a software license.
|
||||
*/
|
||||
class License(val name: String, val abbreviation: String, val filename: String) {
|
||||
fun getFormattedLicense(context: Context): String {
|
||||
return context.assets.open(filename).bufferedReader().use { it.readText() }
|
||||
}
|
||||
}
|
||||
|
||||
class SoftwareComponent(
|
||||
val name: String,
|
||||
val years: String,
|
||||
val copyrightOwner: String,
|
||||
val link: String,
|
||||
val license: License
|
||||
)
|
@ -1,10 +1,15 @@
|
||||
package org.schabi.newpipe.ui.components.about
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
@ -15,6 +20,8 @@ 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.unit.dp
|
||||
import my.nanihadesuka.compose.ColumnScrollbar
|
||||
import org.schabi.newpipe.BuildConfig
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
@ -39,30 +46,49 @@ private val ABOUT_ITEMS = listOf(
|
||||
)
|
||||
)
|
||||
|
||||
private class AboutData(
|
||||
@StringRes val title: Int,
|
||||
@StringRes val description: Int,
|
||||
@StringRes val buttonText: Int,
|
||||
@StringRes val url: Int
|
||||
)
|
||||
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
fun AboutTab() {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.icon),
|
||||
contentDescription = stringResource(R.string.app_name)
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
text = stringResource(R.string.app_name)
|
||||
)
|
||||
Text(text = BuildConfig.VERSION_NAME)
|
||||
}
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
Text(text = stringResource(R.string.app_description))
|
||||
ColumnScrollbar(state = scrollState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 10.dp)
|
||||
.verticalScroll(scrollState),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(R.drawable.icon),
|
||||
contentDescription = stringResource(R.string.app_name)
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
text = stringResource(R.string.app_name)
|
||||
)
|
||||
Text(text = BuildConfig.VERSION_NAME)
|
||||
}
|
||||
|
||||
for (item in ABOUT_ITEMS) {
|
||||
AboutItem(item)
|
||||
Text(text = stringResource(R.string.app_description))
|
||||
|
||||
for (item in ABOUT_ITEMS) {
|
||||
AboutItem(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,197 +1,50 @@
|
||||
package org.schabi.newpipe.ui.components.about
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.NonRestartableComposable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.TextLinkStyles
|
||||
import androidx.compose.ui.text.fromHtml
|
||||
import androidx.compose.ui.text.style.TextDecoration
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer
|
||||
import my.nanihadesuka.compose.LazyColumnScrollbar
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
|
||||
private val SOFTWARE_COMPONENTS = listOf(
|
||||
SoftwareComponent(
|
||||
"ACRA", "2013", "Kevin Gaudin",
|
||||
"https://github.com/ACRA/acra", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"AndroidX", "2005 - 2011", "The Android Open Source Project",
|
||||
"https://developer.android.com/jetpack", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Coil", "2023", "Coil Contributors",
|
||||
"https://coil-kt.github.io/coil/", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"ExoPlayer", "2014 - 2020", "Google, Inc.",
|
||||
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"GigaGet", "2014 - 2015", "Peter Cai",
|
||||
"https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Groupie", "2016", "Lisa Wray",
|
||||
"https://github.com/lisawray/groupie", StandardLicenses.MIT
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Icepick", "2015", "Frankie Sardo",
|
||||
"https://github.com/frankiesardo/icepick", StandardLicenses.EPL1
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Jsoup", "2009 - 2020", "Jonathan Hedley",
|
||||
"https://github.com/jhy/jsoup", StandardLicenses.MIT
|
||||
),
|
||||
SoftwareComponent(
|
||||
"LazyColumnScrollbar", "2024", "nani",
|
||||
"https://github.com/nanihadesuka/LazyColumnScrollbar", StandardLicenses.MIT
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Markwon", "2019", "Dimitry Ivanov",
|
||||
"https://github.com/noties/Markwon", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"Material Components for Android", "2016 - 2020", "Google, Inc.",
|
||||
"https://github.com/material-components/material-components-android",
|
||||
StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"NewPipe Extractor", "2017 - 2020", "Christian Schabesberger",
|
||||
"https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3
|
||||
),
|
||||
SoftwareComponent(
|
||||
"NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
|
||||
"https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"OkHttp", "2019", "Square, Inc.",
|
||||
"https://square.github.io/okhttp/", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
|
||||
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"ProcessPhoenix", "2015", "Jake Wharton",
|
||||
"https://github.com/JakeWharton/ProcessPhoenix", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"RxAndroid", "2015", "The RxAndroid authors",
|
||||
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"RxBinding", "2015", "Jake Wharton",
|
||||
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"RxJava", "2016 - 2020", "RxJava Contributors",
|
||||
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2
|
||||
),
|
||||
SoftwareComponent(
|
||||
"SearchPreference", "2018", "ByteHamster",
|
||||
"https://github.com/ByteHamster/SearchPreference", StandardLicenses.MIT
|
||||
)
|
||||
)
|
||||
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
fun LicenseTab() {
|
||||
var selectedLicense by remember { mutableStateOf<SoftwareComponent?>(null) }
|
||||
val onClick = remember {
|
||||
{ it: SoftwareComponent -> selectedLicense = it }
|
||||
}
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.app_license_title),
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.app_license),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.title_licenses),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
for (component in SOFTWARE_COMPONENTS) {
|
||||
LicenseItem(component, onClick)
|
||||
}
|
||||
|
||||
selectedLicense?.let {
|
||||
var formattedLicense by remember { mutableStateOf("") }
|
||||
|
||||
val context = LocalContext.current
|
||||
LaunchedEffect(key1 = it) {
|
||||
formattedLicense = withContext(Dispatchers.IO) {
|
||||
it.license.getFormattedLicense(context)
|
||||
}
|
||||
}
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = { selectedLicense = null },
|
||||
confirmButton = {
|
||||
TextButton(onClick = { ShareUtils.openUrlInApp(context, it.link) }) {
|
||||
Text(text = stringResource(R.string.open_website_license))
|
||||
LazyColumnScrollbar(state = lazyListState) {
|
||||
LibrariesContainer(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 10.dp),
|
||||
lazyListState = lazyListState,
|
||||
header = {
|
||||
item {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Text(
|
||||
text = stringResource(R.string.app_license_title),
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.app_license),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.title_licenses),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { selectedLicense = null }) {
|
||||
Text(text = stringResource(R.string.done))
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(text = it.name, color = MaterialTheme.colorScheme.onBackground)
|
||||
},
|
||||
text = {
|
||||
val styles = TextLinkStyles(SpanStyle(textDecoration = TextDecoration.Underline))
|
||||
Text(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||
text = AnnotatedString.fromHtml(formattedLicense, styles)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@NonRestartableComposable
|
||||
private fun LicenseItem(
|
||||
softwareComponent: SoftwareComponent,
|
||||
onClick: (SoftwareComponent) -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onClick(softwareComponent) }
|
||||
) {
|
||||
Text(text = softwareComponent.name)
|
||||
Text(
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
text = stringResource(
|
||||
R.string.copyright, softwareComponent.years,
|
||||
softwareComponent.copyrightOwner, softwareComponent.license.abbreviation
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
package org.schabi.newpipe.ui.components.about
|
||||
|
||||
/**
|
||||
* Class containing information about standard software licenses.
|
||||
*/
|
||||
object StandardLicenses {
|
||||
@JvmField
|
||||
val GPL3 = License("GNU General Public License, Version 3.0", "GPLv3", "gpl_3.html")
|
||||
|
||||
@JvmField
|
||||
val APACHE2 = License("Apache License, Version 2.0", "ALv2", "apache2.html")
|
||||
|
||||
@JvmField
|
||||
val MPL2 = License("Mozilla Public License, Version 2.0", "MPL 2.0", "mpl2.html")
|
||||
|
||||
@JvmField
|
||||
val MIT = License("MIT License", "MIT", "mit.html")
|
||||
|
||||
@JvmField
|
||||
val EPL1 = License("Eclipse Public License, Version 1.0", "EPL 1.0", "epl1.html")
|
||||
}
|
@ -1,15 +1,12 @@
|
||||
package org.schabi.newpipe.ui.screens
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Tab
|
||||
@ -27,7 +24,6 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import my.nanihadesuka.compose.ColumnScrollbar
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.ui.components.about.AboutTab
|
||||
import org.schabi.newpipe.ui.components.about.LicenseTab
|
||||
@ -65,22 +61,10 @@ fun AboutScreen(padding: PaddingValues) {
|
||||
.fillMaxWidth()
|
||||
.weight(1f)
|
||||
) { page ->
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
ColumnScrollbar(state = scrollState) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 20.dp, vertical = 10.dp)
|
||||
.verticalScroll(scrollState),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
if (page == 0) {
|
||||
AboutTab()
|
||||
} else {
|
||||
LicenseTab()
|
||||
}
|
||||
}
|
||||
if (page == 0) {
|
||||
AboutTab()
|
||||
} else {
|
||||
LicenseTab()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.9.24'
|
||||
ext {
|
||||
kotlin_version = '2.0.0'
|
||||
about_libs = '11.2.2'
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url "https://plugins.gradle.org/m2/" }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libs"
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
Loading…
Reference in New Issue
Block a user