mirror of
https://github.com/revanced/revanced-manager-compose-old.git
synced 2025-04-30 06:24:28 +02:00
feat: contributors screen
This commit is contained in:
parent
09b681cfe1
commit
d6b5a4e82f
@ -17,6 +17,7 @@ import app.revanced.manager.ui.navigation.AppDestination
|
||||
import app.revanced.manager.ui.screen.MainDashboardScreen
|
||||
import app.revanced.manager.ui.screen.PatchingScreen
|
||||
import app.revanced.manager.ui.screen.subscreens.AppSelectorSubscreen
|
||||
import app.revanced.manager.ui.screen.subscreens.ContributorsSubscreen
|
||||
import app.revanced.manager.ui.screen.subscreens.LicensesSubscreen
|
||||
import app.revanced.manager.ui.screen.subscreens.PatchesSelectorSubscreen
|
||||
import app.revanced.manager.ui.theme.ReVancedManagerTheme
|
||||
@ -52,6 +53,7 @@ class MainActivity : ComponentActivity() {
|
||||
is AppDestination.Dashboard -> MainDashboardScreen(navigator = navigator)
|
||||
is AppDestination.AppSelector -> AppSelectorSubscreen(navigator = navigator)
|
||||
is AppDestination.PatchSelector -> PatchesSelectorSubscreen(navigator = navigator)
|
||||
is AppDestination.Contributors -> ContributorsSubscreen(navigator = navigator)
|
||||
is AppDestination.Licenses -> LicensesSubscreen(navigator = navigator)
|
||||
is AppDestination.Patcher -> PatchingScreen(navigator = navigator)
|
||||
}
|
||||
|
@ -10,4 +10,5 @@ val viewModelModule = module {
|
||||
viewModelOf(::PatcherScreenViewModel)
|
||||
viewModelOf(::AppSelectorViewModel)
|
||||
viewModelOf(::PatchingScreenViewModel)
|
||||
viewModelOf(::ContributorsViewModel)
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package app.revanced.manager.ui.component
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.snapshots.SnapshotStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.dto.github.Contributor
|
||||
import coil.compose.AsyncImage
|
||||
|
||||
@Composable
|
||||
@ExperimentalMaterial3Api
|
||||
fun ContributorsCard(
|
||||
title: String,
|
||||
size: Int,
|
||||
data: SnapshotStateList<Contributor>,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
Column(
|
||||
Modifier
|
||||
.padding(horizontal = 8.dp, vertical = 8.dp)
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Text(
|
||||
text = title,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.align(Alignment.CenterHorizontally)
|
||||
.padding(8.dp),
|
||||
fontSize = MaterialTheme.typography.titleLarge.fontSize,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.titleLarge
|
||||
)
|
||||
|
||||
if (data.isNotEmpty()) {
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Adaptive(48.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
modifier = Modifier.height(size.dp),
|
||||
userScrollEnabled = false
|
||||
) {
|
||||
items(data) { contributor ->
|
||||
AsyncImage(
|
||||
model = contributor.avatarUrl,
|
||||
contentDescription = stringResource(id = R.string.contributor_image),
|
||||
Modifier
|
||||
.padding(4.dp)
|
||||
.size(40.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable {
|
||||
Toast
|
||||
.makeText(context, contributor.username, Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -27,6 +27,9 @@ sealed interface AppDestination : Destination {
|
||||
|
||||
@Parcelize
|
||||
object Licenses : AppDestination
|
||||
|
||||
@Parcelize
|
||||
object Contributors : AppDestination
|
||||
}
|
||||
|
||||
@Parcelize
|
||||
|
@ -73,6 +73,7 @@ fun MainDashboardScreen(navigator: BackstackNavigator<AppDestination>) {
|
||||
onClickPatch = { navigator.push(AppDestination.Patcher) },
|
||||
)
|
||||
DashboardDestination.SETTINGS -> SettingsScreen(
|
||||
onClickContributors = { navigator.push(AppDestination.Contributors) },
|
||||
onClickLicenses = { navigator.push(AppDestination.Licenses) }
|
||||
)
|
||||
}
|
||||
|
@ -38,7 +38,13 @@ fun PatcherScreen(
|
||||
Scaffold(floatingActionButton = {
|
||||
FloatingActionButton(
|
||||
enabled = hasAppSelected && viewModel.anyPatchSelected(),
|
||||
onClick = { if (viewModel.checkSplitApk()) { showDialog = true } else {onClickPatch(); viewModel.loadPatches0()}},
|
||||
onClick = {
|
||||
if (viewModel.checkSplitApk()) {
|
||||
showDialog = true
|
||||
} else {
|
||||
onClickPatch(); viewModel.loadPatches0()
|
||||
}
|
||||
}, // TODO: replace this with something better
|
||||
icon = { Icon(Icons.Default.Build, contentDescription = "Patch") },
|
||||
text = { Text(text = "Patch") }
|
||||
)
|
||||
@ -50,7 +56,7 @@ fun PatcherScreen(
|
||||
.padding(16.dp),
|
||||
) {
|
||||
if (showDialog)
|
||||
SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = onClickPatch) // TODO: replace this with something better
|
||||
SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = onClickPatch)
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.padding(4.dp)
|
||||
|
@ -50,7 +50,11 @@ fun PatchingScreen(
|
||||
) {
|
||||
|
||||
if (vm.patchingInProgress) {
|
||||
CircularProgressIndicator(modifier = Modifier.padding(vertical = 16.dp).size(30.dp))
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.size(30.dp)
|
||||
)
|
||||
Text(text = "Patching...", fontSize = 30.sp)
|
||||
}
|
||||
}
|
||||
@ -63,7 +67,9 @@ fun PatchingScreen(
|
||||
Card {
|
||||
Text(
|
||||
text = Logging.log,
|
||||
modifier = Modifier.padding(horizontal = 20.dp, vertical = 10.dp).fillMaxSize(),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 20.dp, vertical = 10.dp)
|
||||
.fillMaxSize(),
|
||||
fontSize = 20.sp,
|
||||
lineHeight = 35.sp
|
||||
)
|
||||
|
@ -6,10 +6,7 @@ import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Code
|
||||
import androidx.compose.material.icons.filled.LibraryBooks
|
||||
import androidx.compose.material.icons.filled.Palette
|
||||
import androidx.compose.material.icons.filled.Style
|
||||
import androidx.compose.material.icons.filled.*
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
@ -28,8 +25,9 @@ import org.koin.androidx.compose.getViewModel
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun SettingsScreen(
|
||||
viewModel: SettingsViewModel = getViewModel(),
|
||||
onClickContributors: () -> Unit,
|
||||
onClickLicenses: () -> Unit,
|
||||
viewModel: SettingsViewModel = getViewModel()
|
||||
) {
|
||||
val prefs = viewModel.prefs
|
||||
|
||||
@ -72,12 +70,13 @@ fun SettingsScreen(
|
||||
}
|
||||
|
||||
Divider()
|
||||
SocialItem(R.string.github, Icons.Default.Code, viewModel::openGitHub)
|
||||
ListItem(
|
||||
modifier = Modifier.clickable(onClick = onClickLicenses),
|
||||
headlineText = { Text(stringResource(R.string.opensource_licenses)) },
|
||||
leadingContent = { Icon(Icons.Default.LibraryBooks, contentDescription = null) },
|
||||
)
|
||||
SocialItem(R.string.github, Icons.Default.Code, viewModel::openGitHub)
|
||||
SocialItem(R.string.screen_contributors_title, Icons.Default.Group, onClickContributors)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,83 @@
|
||||
package app.revanced.manager.ui.screen.subscreens
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import app.revanced.manager.R
|
||||
import app.revanced.manager.ui.component.ContributorsCard
|
||||
import app.revanced.manager.ui.navigation.AppDestination
|
||||
import app.revanced.manager.ui.viewmodel.ContributorsViewModel
|
||||
import com.xinto.taxi.BackstackNavigator
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||
@Composable
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
fun ContributorsSubscreen(
|
||||
navigator: BackstackNavigator<AppDestination>,
|
||||
vm: ContributorsViewModel = getViewModel()
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
MediumTopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
text = stringResource(R.string.screen_contributors_title),
|
||||
style = MaterialTheme.typography.headlineLarge
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = navigator::pop) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(it)
|
||||
.height(1400.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
ContributorsCard(
|
||||
stringResource(R.string.cli_contributors),
|
||||
data = vm.cliContributorsList,
|
||||
size = 100
|
||||
)
|
||||
ContributorsCard(
|
||||
stringResource(R.string.patcher_contributors),
|
||||
data = vm.patcherContributorsList,
|
||||
size = 100
|
||||
)
|
||||
ContributorsCard(
|
||||
stringResource(R.string.patches_contributors),
|
||||
data = vm.patchesContributorsList,
|
||||
size = 200
|
||||
)
|
||||
ContributorsCard(
|
||||
stringResource(R.string.manager_contributors),
|
||||
data = vm.managerContributorsList,
|
||||
size = 100
|
||||
)
|
||||
ContributorsCard(
|
||||
stringResource(R.string.integrations_contributors),
|
||||
data = vm.integrationsContributorsList,
|
||||
size = 200
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package app.revanced.manager.ui.viewmodel
|
||||
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import app.revanced.manager.dto.github.Contributor
|
||||
import app.revanced.manager.repository.GitHubRepository
|
||||
import app.revanced.manager.util.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class ContributorsViewModel(private val repository: GitHubRepository) : ViewModel() {
|
||||
val patcherContributorsList = mutableStateListOf<Contributor>()
|
||||
val patchesContributorsList = mutableStateListOf<Contributor>()
|
||||
val cliContributorsList = mutableStateListOf<Contributor>()
|
||||
val managerContributorsList = mutableStateListOf<Contributor>()
|
||||
val integrationsContributorsList = mutableStateListOf<Contributor>()
|
||||
|
||||
private fun loadContributors() {
|
||||
viewModelScope.launch {
|
||||
val contributors = repository.fetchContributors()
|
||||
contributors.repositories.forEach { repo ->
|
||||
when (repo.name) {
|
||||
ghCli -> {
|
||||
repo.contributors.sortedByDescending {
|
||||
it.username
|
||||
}
|
||||
cliContributorsList.addAll(repo.contributors)
|
||||
}
|
||||
ghPatcher -> {
|
||||
repo.contributors.sortedByDescending {
|
||||
it.username
|
||||
}
|
||||
patcherContributorsList.addAll(repo.contributors)
|
||||
}
|
||||
ghPatches -> {
|
||||
repo.contributors.sortedByDescending {
|
||||
it.username
|
||||
}
|
||||
patchesContributorsList.addAll(repo.contributors)
|
||||
}
|
||||
ghIntegrations -> {
|
||||
repo.contributors.sortedByDescending {
|
||||
it.username
|
||||
}
|
||||
integrationsContributorsList.addAll(repo.contributors)
|
||||
}
|
||||
ghManager -> {
|
||||
repo.contributors.sortedByDescending {
|
||||
it.username
|
||||
}
|
||||
managerContributorsList.addAll(repo.contributors)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
loadContributors()
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
|
||||
loadPatches()
|
||||
}
|
||||
}
|
||||
|
||||
fun selectPatch(patchId: String, state: Boolean) {
|
||||
if (state) selectedPatches.add(patchId)
|
||||
else selectedPatches.remove(patchId)
|
||||
@ -72,12 +73,16 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
|
||||
else null
|
||||
|
||||
fun checkSplitApk(): Boolean {
|
||||
if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean("com.android.vending.splits.required", false)) {
|
||||
Log.d(tag, "APK is split.")
|
||||
return true
|
||||
}
|
||||
Log.d(tag, "APK is not split.")
|
||||
return false
|
||||
if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean(
|
||||
"com.android.vending.splits.required",
|
||||
false
|
||||
)
|
||||
) {
|
||||
Log.d(tag, "APK is split.")
|
||||
return true
|
||||
}
|
||||
Log.d(tag, "APK is not split.")
|
||||
return false
|
||||
}
|
||||
|
||||
private fun loadPatches() = viewModelScope.launch {
|
||||
|
@ -2,6 +2,7 @@ package app.revanced.manager.util
|
||||
|
||||
private const val team = "revanced"
|
||||
const val ghOrganization = "https://github.com/$team"
|
||||
const val ghCli = "$team/revanced-cli"
|
||||
const val ghPatches = "$team/revanced-patches"
|
||||
const val ghPatcher = "$team/revanced-patcher"
|
||||
const val ghManager = "$team/revanced-manager"
|
||||
|
Loading…
x
Reference in New Issue
Block a user