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.MainDashboardScreen
|
||||||
import app.revanced.manager.ui.screen.PatchingScreen
|
import app.revanced.manager.ui.screen.PatchingScreen
|
||||||
import app.revanced.manager.ui.screen.subscreens.AppSelectorSubscreen
|
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.LicensesSubscreen
|
||||||
import app.revanced.manager.ui.screen.subscreens.PatchesSelectorSubscreen
|
import app.revanced.manager.ui.screen.subscreens.PatchesSelectorSubscreen
|
||||||
import app.revanced.manager.ui.theme.ReVancedManagerTheme
|
import app.revanced.manager.ui.theme.ReVancedManagerTheme
|
||||||
@ -52,6 +53,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
is AppDestination.Dashboard -> MainDashboardScreen(navigator = navigator)
|
is AppDestination.Dashboard -> MainDashboardScreen(navigator = navigator)
|
||||||
is AppDestination.AppSelector -> AppSelectorSubscreen(navigator = navigator)
|
is AppDestination.AppSelector -> AppSelectorSubscreen(navigator = navigator)
|
||||||
is AppDestination.PatchSelector -> PatchesSelectorSubscreen(navigator = navigator)
|
is AppDestination.PatchSelector -> PatchesSelectorSubscreen(navigator = navigator)
|
||||||
|
is AppDestination.Contributors -> ContributorsSubscreen(navigator = navigator)
|
||||||
is AppDestination.Licenses -> LicensesSubscreen(navigator = navigator)
|
is AppDestination.Licenses -> LicensesSubscreen(navigator = navigator)
|
||||||
is AppDestination.Patcher -> PatchingScreen(navigator = navigator)
|
is AppDestination.Patcher -> PatchingScreen(navigator = navigator)
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,5 @@ val viewModelModule = module {
|
|||||||
viewModelOf(::PatcherScreenViewModel)
|
viewModelOf(::PatcherScreenViewModel)
|
||||||
viewModelOf(::AppSelectorViewModel)
|
viewModelOf(::AppSelectorViewModel)
|
||||||
viewModelOf(::PatchingScreenViewModel)
|
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
|
@Parcelize
|
||||||
object Licenses : AppDestination
|
object Licenses : AppDestination
|
||||||
|
|
||||||
|
@Parcelize
|
||||||
|
object Contributors : AppDestination
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
@ -73,6 +73,7 @@ fun MainDashboardScreen(navigator: BackstackNavigator<AppDestination>) {
|
|||||||
onClickPatch = { navigator.push(AppDestination.Patcher) },
|
onClickPatch = { navigator.push(AppDestination.Patcher) },
|
||||||
)
|
)
|
||||||
DashboardDestination.SETTINGS -> SettingsScreen(
|
DashboardDestination.SETTINGS -> SettingsScreen(
|
||||||
|
onClickContributors = { navigator.push(AppDestination.Contributors) },
|
||||||
onClickLicenses = { navigator.push(AppDestination.Licenses) }
|
onClickLicenses = { navigator.push(AppDestination.Licenses) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,13 @@ fun PatcherScreen(
|
|||||||
Scaffold(floatingActionButton = {
|
Scaffold(floatingActionButton = {
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
enabled = hasAppSelected && viewModel.anyPatchSelected(),
|
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") },
|
icon = { Icon(Icons.Default.Build, contentDescription = "Patch") },
|
||||||
text = { Text(text = "Patch") }
|
text = { Text(text = "Patch") }
|
||||||
)
|
)
|
||||||
@ -50,7 +56,7 @@ fun PatcherScreen(
|
|||||||
.padding(16.dp),
|
.padding(16.dp),
|
||||||
) {
|
) {
|
||||||
if (showDialog)
|
if (showDialog)
|
||||||
SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = onClickPatch) // TODO: replace this with something better
|
SplitAPKDialog(onDismiss = { showDialog = false }, onConfirm = onClickPatch)
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(4.dp)
|
.padding(4.dp)
|
||||||
|
@ -50,7 +50,11 @@ fun PatchingScreen(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
if (vm.patchingInProgress) {
|
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)
|
Text(text = "Patching...", fontSize = 30.sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,7 +67,9 @@ fun PatchingScreen(
|
|||||||
Card {
|
Card {
|
||||||
Text(
|
Text(
|
||||||
text = Logging.log,
|
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,
|
fontSize = 20.sp,
|
||||||
lineHeight = 35.sp
|
lineHeight = 35.sp
|
||||||
)
|
)
|
||||||
|
@ -6,10 +6,7 @@ import androidx.compose.foundation.layout.*
|
|||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Code
|
import androidx.compose.material.icons.filled.*
|
||||||
import androidx.compose.material.icons.filled.LibraryBooks
|
|
||||||
import androidx.compose.material.icons.filled.Palette
|
|
||||||
import androidx.compose.material.icons.filled.Style
|
|
||||||
import androidx.compose.material3.*
|
import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
@ -28,8 +25,9 @@ import org.koin.androidx.compose.getViewModel
|
|||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(
|
fun SettingsScreen(
|
||||||
|
viewModel: SettingsViewModel = getViewModel(),
|
||||||
|
onClickContributors: () -> Unit,
|
||||||
onClickLicenses: () -> Unit,
|
onClickLicenses: () -> Unit,
|
||||||
viewModel: SettingsViewModel = getViewModel()
|
|
||||||
) {
|
) {
|
||||||
val prefs = viewModel.prefs
|
val prefs = viewModel.prefs
|
||||||
|
|
||||||
@ -72,12 +70,13 @@ fun SettingsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Divider()
|
Divider()
|
||||||
|
SocialItem(R.string.github, Icons.Default.Code, viewModel::openGitHub)
|
||||||
ListItem(
|
ListItem(
|
||||||
modifier = Modifier.clickable(onClick = onClickLicenses),
|
modifier = Modifier.clickable(onClick = onClickLicenses),
|
||||||
headlineText = { Text(stringResource(R.string.opensource_licenses)) },
|
headlineText = { Text(stringResource(R.string.opensource_licenses)) },
|
||||||
leadingContent = { Icon(Icons.Default.LibraryBooks, contentDescription = null) },
|
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()
|
loadPatches()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun selectPatch(patchId: String, state: Boolean) {
|
fun selectPatch(patchId: String, state: Boolean) {
|
||||||
if (state) selectedPatches.add(patchId)
|
if (state) selectedPatches.add(patchId)
|
||||||
else selectedPatches.remove(patchId)
|
else selectedPatches.remove(patchId)
|
||||||
@ -72,12 +73,16 @@ class PatcherScreenViewModel(private val app: Application, private val api: API)
|
|||||||
else null
|
else null
|
||||||
|
|
||||||
fun checkSplitApk(): Boolean {
|
fun checkSplitApk(): Boolean {
|
||||||
if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean("com.android.vending.splits.required", false)) {
|
if (getSelectedPackageInfo()!!.applicationInfo!!.metaData!!.getBoolean(
|
||||||
Log.d(tag, "APK is split.")
|
"com.android.vending.splits.required",
|
||||||
return true
|
false
|
||||||
}
|
)
|
||||||
Log.d(tag, "APK is not split.")
|
) {
|
||||||
return false
|
Log.d(tag, "APK is split.")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
Log.d(tag, "APK is not split.")
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadPatches() = viewModelScope.launch {
|
private fun loadPatches() = viewModelScope.launch {
|
||||||
|
@ -2,6 +2,7 @@ package app.revanced.manager.util
|
|||||||
|
|
||||||
private const val team = "revanced"
|
private const val team = "revanced"
|
||||||
const val ghOrganization = "https://github.com/$team"
|
const val ghOrganization = "https://github.com/$team"
|
||||||
|
const val ghCli = "$team/revanced-cli"
|
||||||
const val ghPatches = "$team/revanced-patches"
|
const val ghPatches = "$team/revanced-patches"
|
||||||
const val ghPatcher = "$team/revanced-patcher"
|
const val ghPatcher = "$team/revanced-patcher"
|
||||||
const val ghManager = "$team/revanced-manager"
|
const val ghManager = "$team/revanced-manager"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user