feat: contributors screen (#42)

* Contributors page
- https://github.com/revanced/revanced-manager-compose/issues/34

* feat: adding ContributorScreen as clickable icons like the website

* feat: adding ContributorScreen
- Made changes that were asked for in prev PR
- Currently just waiting on a git merge to get ArrowButton in

* feat: adding ContributorScreen
- Made changes that were asked for in prev PR
- ArrowButton is also in use

* feat: adding ContributorScreen
- Made changes that were asked for in prev PR
- ArrowButton is also in use
- Fixed other PR comment changes

* Apply suggestions from code review

* Remove unused string resources

---------

Co-authored-by: Ax333l <main@axelen.xyz>
This commit is contained in:
Tyff 2023-06-29 07:51:12 +12:00 committed by GitHub
parent 59a99c83a5
commit 99ddea270f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 181 additions and 5 deletions

View File

@ -13,4 +13,5 @@ val viewModelModule = module {
viewModelOf(::InstallerViewModel)
viewModelOf(::UpdateSettingsViewModel)
viewModelOf(::ImportExportViewModel)
viewModelOf(::ContributorViewModel)
}

View File

@ -26,4 +26,7 @@ sealed interface SettingsDestination : Parcelable {
@Parcelize
object UpdateProgress : SettingsDestination
@Parcelize
object Contributors: SettingsDestination
}

View File

@ -110,13 +110,18 @@ fun SettingsScreen(
)
is SettingsDestination.About -> AboutSettingsScreen(
onBackClick = { navController.pop() }
onBackClick = { navController.pop() },
onContributorsClick = { navController.navigate(SettingsDestination.Contributors) }
)
is SettingsDestination.UpdateProgress -> UpdateProgressScreen(
{ navController.pop() },
)
is SettingsDestination.Contributors -> ContributorScreen(
onBackClick = { navController.pop() },
)
is SettingsDestination.Settings -> {
Scaffold(
topBar = {

View File

@ -22,13 +22,17 @@ import androidx.compose.ui.unit.dp
import app.revanced.manager.BuildConfig
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.destination.SettingsDestination
import app.revanced.manager.util.openUrl
import com.google.accompanist.drawablepainter.rememberDrawablePainter
import dev.olshevski.navigation.reimagined.NavController
import dev.olshevski.navigation.reimagined.navigate
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AboutSettingsScreen(
onBackClick: () -> Unit
onBackClick: () -> Unit,
onContributorsClick: () -> Unit,
) {
val context = LocalContext.current
val icon = rememberDrawablePainter(context.packageManager.getApplicationIcon(context.packageName))
@ -52,9 +56,12 @@ fun AboutSettingsScreen(
)
val listItems = listOf(
Triple(stringResource(R.string.submit_feedback), stringResource(R.string.submit_feedback_description), third = { /*TODO*/ }),
Triple(stringResource(R.string.contributors), stringResource(R.string.contributors_description), third = { /*TODO*/ }),
Triple(stringResource(R.string.developer_options), stringResource(R.string.developer_options_description), third = { /*TODO*/ }),
Triple(stringResource(R.string.submit_feedback), stringResource(R.string.submit_feedback_description),
third = { /*TODO*/ }),
Triple(stringResource(R.string.contributors), stringResource(R.string.contributors_description),
third = onContributorsClick),
Triple(stringResource(R.string.developer_options), stringResource(R.string.developer_options_description),
third = { /*TODO*/ }),
)
Scaffold(

View File

@ -0,0 +1,136 @@
package app.revanced.manager.ui.screen.settings
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowDropDown
import androidx.compose.material.icons.outlined.ArrowDropUp
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
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.draw.clip
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R
import app.revanced.manager.network.dto.ReVancedContributor
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ArrowButton
import app.revanced.manager.ui.component.LoadingIndicator
import app.revanced.manager.ui.viewmodel.ContributorViewModel
import coil.compose.AsyncImage
import org.koin.androidx.compose.getViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ContributorScreen(
onBackClick: () -> Unit,
viewModel: ContributorViewModel = getViewModel()
) {
val repositories = viewModel.repositories
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.contributors),
onBackClick = onBackClick
)
},
) { paddingValues ->
Column(
modifier = Modifier
.fillMaxHeight()
.padding(paddingValues)
.fillMaxWidth()
.verticalScroll(rememberScrollState())
) {
if(repositories.isEmpty()) {
LoadingIndicator()
}
repositories.forEach {
ExpandableListCard(
title = it.name,
contributors = it.contributors
)
}
}
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ExpandableListCard(
title: String,
contributors: List<ReVancedContributor>
) {
var expanded by remember { mutableStateOf(false) }
Card(
shape = RoundedCornerShape(30.dp),
elevation = CardDefaults.outlinedCardElevation(),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
.border(
width = 2.dp,
color = MaterialTheme.colorScheme.outline,
shape = MaterialTheme.shapes.medium
),
colors = CardDefaults.outlinedCardColors(),
) {
Column() {
Row() {
ListItem(
headlineContent = {
Text(
text = processHeadlineText(title),
style = MaterialTheme.typography.titleMedium
)
},
trailingContent = {
if (contributors.isNotEmpty()) {
ArrowButton(
expanded = expanded,
onClick = { expanded = !expanded }
)
}
},
)
}
if (expanded) {
FlowRow(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.padding(8.dp),
) {
contributors.forEach {
AsyncImage(
model = it.avatarUrl,
contentDescription = it.avatarUrl,
contentScale = ContentScale.Crop,
modifier = Modifier
.padding(16.dp)
.size(45.dp)
.clip(CircleShape)
)
}
}
}
}
}
}
fun processHeadlineText(repositoryName: String): String {
return "Revanced " + repositoryName.replace("revanced/revanced-", "")
.replace("-", " ")
.split(" ")
.map { if (it.length > 3) it else it.uppercase() }
.joinToString(" ")
.replaceFirstChar { it.uppercase() }
}

View File

@ -0,0 +1,24 @@
package app.revanced.manager.ui.viewmodel
import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import app.revanced.manager.domain.repository.ReVancedRepository
import app.revanced.manager.network.utils.getOrNull
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class ContributorViewModel(private val repository: ReVancedRepository): ViewModel() {
val repositories = mutableStateListOf<app.revanced.manager.network.dto.ReVancedRepository>()
init {
viewModelScope.launch {
withContext(Dispatchers.IO) {
val repos = repository.getContributors().getOrNull()?.repositories
withContext(Dispatchers.Main) {
if (repos != null) { repositories.addAll(repos) }
}
}
}
}
}