|
1 | 1 | package org.schabi.newpipe.ui.components.about |
2 | 2 |
|
3 | | -import androidx.compose.foundation.clickable |
| 3 | +import androidx.compose.foundation.layout.Arrangement |
4 | 4 | import androidx.compose.foundation.layout.Column |
5 | 5 | import androidx.compose.foundation.layout.fillMaxWidth |
6 | | -import androidx.compose.foundation.rememberScrollState |
7 | | -import androidx.compose.foundation.verticalScroll |
8 | | -import androidx.compose.material3.AlertDialog |
| 6 | +import androidx.compose.foundation.layout.padding |
| 7 | +import androidx.compose.foundation.lazy.rememberLazyListState |
9 | 8 | import androidx.compose.material3.MaterialTheme |
10 | 9 | import androidx.compose.material3.Text |
11 | | -import androidx.compose.material3.TextButton |
12 | 10 | import androidx.compose.runtime.Composable |
13 | | -import androidx.compose.runtime.LaunchedEffect |
14 | 11 | import androidx.compose.runtime.NonRestartableComposable |
15 | | -import androidx.compose.runtime.getValue |
16 | | -import androidx.compose.runtime.mutableStateOf |
17 | | -import androidx.compose.runtime.remember |
18 | | -import androidx.compose.runtime.setValue |
19 | 12 | import androidx.compose.ui.Modifier |
20 | | -import androidx.compose.ui.platform.LocalContext |
21 | 13 | import androidx.compose.ui.res.stringResource |
22 | | -import androidx.compose.ui.text.AnnotatedString |
23 | | -import androidx.compose.ui.text.SpanStyle |
24 | | -import androidx.compose.ui.text.TextLinkStyles |
25 | | -import androidx.compose.ui.text.fromHtml |
26 | | -import androidx.compose.ui.text.style.TextDecoration |
27 | | -import kotlinx.coroutines.Dispatchers |
28 | | -import kotlinx.coroutines.withContext |
| 14 | +import androidx.compose.ui.unit.dp |
| 15 | +import com.mikepenz.aboutlibraries.ui.compose.m3.LibrariesContainer |
| 16 | +import my.nanihadesuka.compose.LazyColumnScrollbar |
29 | 17 | import org.schabi.newpipe.R |
30 | | -import org.schabi.newpipe.util.external_communication.ShareUtils |
31 | | - |
32 | | -private val SOFTWARE_COMPONENTS = listOf( |
33 | | - SoftwareComponent( |
34 | | - "ACRA", "2013", "Kevin Gaudin", |
35 | | - "https://github.com/ACRA/acra", StandardLicenses.APACHE2 |
36 | | - ), |
37 | | - SoftwareComponent( |
38 | | - "AndroidX", "2005 - 2011", "The Android Open Source Project", |
39 | | - "https://developer.android.com/jetpack", StandardLicenses.APACHE2 |
40 | | - ), |
41 | | - SoftwareComponent( |
42 | | - "Coil", "2023", "Coil Contributors", |
43 | | - "https://coil-kt.github.io/coil/", StandardLicenses.APACHE2 |
44 | | - ), |
45 | | - SoftwareComponent( |
46 | | - "ExoPlayer", "2014 - 2020", "Google, Inc.", |
47 | | - "https://github.com/google/ExoPlayer", StandardLicenses.APACHE2 |
48 | | - ), |
49 | | - SoftwareComponent( |
50 | | - "GigaGet", "2014 - 2015", "Peter Cai", |
51 | | - "https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3 |
52 | | - ), |
53 | | - SoftwareComponent( |
54 | | - "Groupie", "2016", "Lisa Wray", |
55 | | - "https://github.com/lisawray/groupie", StandardLicenses.MIT |
56 | | - ), |
57 | | - SoftwareComponent( |
58 | | - "Icepick", "2015", "Frankie Sardo", |
59 | | - "https://github.com/frankiesardo/icepick", StandardLicenses.EPL1 |
60 | | - ), |
61 | | - SoftwareComponent( |
62 | | - "Jsoup", "2009 - 2020", "Jonathan Hedley", |
63 | | - "https://github.com/jhy/jsoup", StandardLicenses.MIT |
64 | | - ), |
65 | | - SoftwareComponent( |
66 | | - "LazyColumnScrollbar", "2024", "nani", |
67 | | - "https://github.com/nanihadesuka/LazyColumnScrollbar", StandardLicenses.MIT |
68 | | - ), |
69 | | - SoftwareComponent( |
70 | | - "Markwon", "2019", "Dimitry Ivanov", |
71 | | - "https://github.com/noties/Markwon", StandardLicenses.APACHE2 |
72 | | - ), |
73 | | - SoftwareComponent( |
74 | | - "Material Components for Android", "2016 - 2020", "Google, Inc.", |
75 | | - "https://github.com/material-components/material-components-android", |
76 | | - StandardLicenses.APACHE2 |
77 | | - ), |
78 | | - SoftwareComponent( |
79 | | - "NewPipe Extractor", "2017 - 2020", "Christian Schabesberger", |
80 | | - "https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3 |
81 | | - ), |
82 | | - SoftwareComponent( |
83 | | - "NoNonsense-FilePicker", "2016", "Jonas Kalderstam", |
84 | | - "https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2 |
85 | | - ), |
86 | | - SoftwareComponent( |
87 | | - "OkHttp", "2019", "Square, Inc.", |
88 | | - "https://square.github.io/okhttp/", StandardLicenses.APACHE2 |
89 | | - ), |
90 | | - SoftwareComponent( |
91 | | - "PrettyTime", "2012 - 2020", "Lincoln Baxter, III", |
92 | | - "https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2 |
93 | | - ), |
94 | | - SoftwareComponent( |
95 | | - "ProcessPhoenix", "2015", "Jake Wharton", |
96 | | - "https://github.com/JakeWharton/ProcessPhoenix", StandardLicenses.APACHE2 |
97 | | - ), |
98 | | - SoftwareComponent( |
99 | | - "RxAndroid", "2015", "The RxAndroid authors", |
100 | | - "https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2 |
101 | | - ), |
102 | | - SoftwareComponent( |
103 | | - "RxBinding", "2015", "Jake Wharton", |
104 | | - "https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2 |
105 | | - ), |
106 | | - SoftwareComponent( |
107 | | - "RxJava", "2016 - 2020", "RxJava Contributors", |
108 | | - "https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2 |
109 | | - ), |
110 | | - SoftwareComponent( |
111 | | - "SearchPreference", "2018", "ByteHamster", |
112 | | - "https://github.com/ByteHamster/SearchPreference", StandardLicenses.MIT |
113 | | - ) |
114 | | -) |
115 | 18 |
|
116 | 19 | @Composable |
117 | 20 | @NonRestartableComposable |
118 | 21 | fun LicenseTab() { |
119 | | - var selectedLicense by remember { mutableStateOf<SoftwareComponent?>(null) } |
120 | | - val onClick = remember { |
121 | | - { it: SoftwareComponent -> selectedLicense = it } |
122 | | - } |
123 | | - |
124 | | - Text( |
125 | | - text = stringResource(R.string.app_license_title), |
126 | | - style = MaterialTheme.typography.titleLarge |
127 | | - ) |
128 | | - Text( |
129 | | - text = stringResource(R.string.app_license), |
130 | | - style = MaterialTheme.typography.bodyMedium |
131 | | - ) |
132 | | - |
133 | | - Text( |
134 | | - text = stringResource(R.string.title_licenses), |
135 | | - style = MaterialTheme.typography.titleLarge, |
136 | | - ) |
137 | | - for (component in SOFTWARE_COMPONENTS) { |
138 | | - LicenseItem(component, onClick) |
139 | | - } |
140 | | - |
141 | | - selectedLicense?.let { |
142 | | - var formattedLicense by remember { mutableStateOf("") } |
143 | | - |
144 | | - val context = LocalContext.current |
145 | | - LaunchedEffect(key1 = it) { |
146 | | - formattedLicense = withContext(Dispatchers.IO) { |
147 | | - it.license.getFormattedLicense(context) |
148 | | - } |
149 | | - } |
150 | | - |
151 | | - AlertDialog( |
152 | | - onDismissRequest = { selectedLicense = null }, |
153 | | - confirmButton = { |
154 | | - TextButton(onClick = { ShareUtils.openUrlInApp(context, it.link) }) { |
155 | | - Text(text = stringResource(R.string.open_website_license)) |
156 | | - } |
157 | | - }, |
158 | | - dismissButton = { |
159 | | - TextButton(onClick = { selectedLicense = null }) { |
160 | | - Text(text = stringResource(R.string.done)) |
| 22 | + val lazyListState = rememberLazyListState() |
| 23 | + |
| 24 | + LazyColumnScrollbar(state = lazyListState) { |
| 25 | + LibrariesContainer( |
| 26 | + modifier = Modifier |
| 27 | + .fillMaxWidth() |
| 28 | + .padding(horizontal = 20.dp, vertical = 10.dp), |
| 29 | + lazyListState = lazyListState, |
| 30 | + header = { |
| 31 | + item { |
| 32 | + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { |
| 33 | + Text( |
| 34 | + text = stringResource(R.string.app_license_title), |
| 35 | + style = MaterialTheme.typography.titleLarge |
| 36 | + ) |
| 37 | + Text( |
| 38 | + text = stringResource(R.string.app_license), |
| 39 | + style = MaterialTheme.typography.bodyMedium |
| 40 | + ) |
| 41 | + Text( |
| 42 | + text = stringResource(R.string.title_licenses), |
| 43 | + style = MaterialTheme.typography.titleLarge, |
| 44 | + ) |
| 45 | + } |
161 | 46 | } |
162 | | - }, |
163 | | - title = { |
164 | | - Text(text = it.name, color = MaterialTheme.colorScheme.onBackground) |
165 | | - }, |
166 | | - text = { |
167 | | - val styles = TextLinkStyles(SpanStyle(textDecoration = TextDecoration.Underline)) |
168 | | - Text( |
169 | | - modifier = Modifier.verticalScroll(rememberScrollState()), |
170 | | - text = AnnotatedString.fromHtml(formattedLicense, styles) |
171 | | - ) |
172 | 47 | } |
173 | 48 | ) |
174 | 49 | } |
175 | 50 | } |
176 | | - |
177 | | -@Composable |
178 | | -@NonRestartableComposable |
179 | | -private fun LicenseItem( |
180 | | - softwareComponent: SoftwareComponent, |
181 | | - onClick: (SoftwareComponent) -> Unit |
182 | | -) { |
183 | | - Column( |
184 | | - modifier = Modifier |
185 | | - .fillMaxWidth() |
186 | | - .clickable { onClick(softwareComponent) } |
187 | | - ) { |
188 | | - Text(text = softwareComponent.name) |
189 | | - Text( |
190 | | - style = MaterialTheme.typography.bodyMedium, |
191 | | - text = stringResource( |
192 | | - R.string.copyright, softwareComponent.years, |
193 | | - softwareComponent.copyrightOwner, softwareComponent.license.abbreviation |
194 | | - ) |
195 | | - ) |
196 | | - } |
197 | | -} |
0 commit comments