feat: improve contributors screen

This commit is contained in:
Ushie 2022-10-10 21:33:22 +03:00
parent a63ca61905
commit e06b30cd7a
No known key found for this signature in database
GPG Key ID: 0EF73F1CA38B2D5F
5 changed files with 74 additions and 54 deletions

View File

@ -101,6 +101,7 @@ dependencies {
implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion")
implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion")
implementation("com.google.accompanist:accompanist-drawablepainter:$accompanistVersion") implementation("com.google.accompanist:accompanist-drawablepainter:$accompanistVersion")
implementation("com.google.accompanist:accompanist-flowlayout:$accompanistVersion")
// Coil (async image loading) // Coil (async image loading)
implementation("io.coil-kt:coil-compose:2.1.0") implementation("io.coil-kt:coil-compose:2.1.0")
@ -136,5 +137,6 @@ dependencies {
implementation("androidx.concurrent:concurrent-futures:1.1.0") implementation("androidx.concurrent:concurrent-futures:1.1.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.4") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.4")
// Networking
implementation("com.github.niusounds:cronet-engine:0.1.0") implementation("com.github.niusounds:cronet-engine:0.1.0")
} }

View File

@ -1,15 +1,11 @@
package app.revanced.manager.ui.component package app.revanced.manager.ui.component
import android.widget.Toast import android.widget.Toast
import androidx.compose.foundation.clickable import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.* 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.foundation.shape.CircleShape
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.*
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -17,23 +13,27 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.dto.github.Contributor import app.revanced.manager.dto.github.Contributor
import app.revanced.manager.ui.viewmodel.ContributorsViewModel
import coil.compose.AsyncImage import coil.compose.AsyncImage
import com.google.accompanist.flowlayout.FlowRow
import com.google.accompanist.flowlayout.SizeMode
import org.koin.androidx.compose.getViewModel
@OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
@ExperimentalMaterial3Api @ExperimentalMaterial3Api
fun ContributorsCard( fun ContributorsCard(
title: String, title: String,
size: Int,
data: SnapshotStateList<Contributor>, data: SnapshotStateList<Contributor>,
vm: ContributorsViewModel = getViewModel()
) { ) {
val context = LocalContext.current val context = LocalContext.current
Column( Column(
Modifier Modifier
.padding(horizontal = 8.dp, vertical = 8.dp) .padding(16.dp, 8.dp, 16.dp, 4.dp)
.fillMaxWidth() .fillMaxWidth()
) { ) {
Text( Text(
@ -41,37 +41,42 @@ fun ContributorsCard(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.CenterHorizontally) .align(Alignment.CenterHorizontally)
.padding(8.dp), .padding(bottom = 8.dp),
fontSize = MaterialTheme.typography.titleLarge.fontSize,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleLarge style = MaterialTheme.typography.titleLarge
) )
ElevatedCard {
if (data.isNotEmpty()) { if (data.isNotEmpty()) {
LazyVerticalGrid( FlowRow(
columns = GridCells.Adaptive(48.dp), mainAxisSize = SizeMode.Expand,
verticalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.padding(8.dp)
horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = Modifier.height(size.dp),
userScrollEnabled = false
) { ) {
items(data) { contributor -> data.forEach { contributor ->
AsyncImage( AsyncImage(
model = contributor.avatarUrl, model = contributor.avatarUrl,
contentDescription = stringResource(id = R.string.contributor_image), contentDescription = stringResource(id = R.string.contributor_image),
Modifier Modifier
.padding(4.dp) .padding(4.dp)
.size(40.dp) .size(48.dp)
.clip(CircleShape) .clip(CircleShape)
.clickable { .combinedClickable(
Toast onClick = { vm.openUserProfile(contributor.username) },
.makeText(context, contributor.username, Toast.LENGTH_SHORT) onLongClick = {
.show() Toast.makeText(context, contributor.username, Toast.LENGTH_SHORT).show()
} }
) )
)
}
}
} else {
Box(
modifier = Modifier
.padding(vertical = 24.dp)
.fillMaxWidth(),
contentAlignment = Alignment.Center,
content = { CircularProgressIndicator() }
)
} }
} }
} }
}
} }

View File

@ -9,9 +9,11 @@ import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import app.revanced.manager.R import app.revanced.manager.R
import app.revanced.manager.ui.component.ContributorsCard import app.revanced.manager.ui.component.ContributorsCard
import app.revanced.manager.ui.navigation.AppDestination import app.revanced.manager.ui.navigation.AppDestination
@ -27,10 +29,16 @@ fun ContributorsSubscreen(
navigator: BackstackNavigator<AppDestination>, navigator: BackstackNavigator<AppDestination>,
vm: ContributorsViewModel = getViewModel() vm: ContributorsViewModel = getViewModel()
) { ) {
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(
state = rememberTopAppBarState(),
canScroll = { true }
)
val ctx = LocalContext.current.applicationContext val ctx = LocalContext.current.applicationContext
Scaffold( Scaffold(
modifier = Modifier
.nestedScroll(scrollBehavior.nestedScrollConnection),
topBar = { topBar = {
MediumTopAppBar( LargeTopAppBar(
title = { title = {
Text( Text(
text = stringResource(R.string.screen_contributors_title) text = stringResource(R.string.screen_contributors_title)
@ -43,7 +51,8 @@ fun ContributorsSubscreen(
contentDescription = null contentDescription = null
) )
} }
} },
scrollBehavior = scrollBehavior
) )
}, },
floatingActionButton = { floatingActionButton = {
@ -55,32 +64,28 @@ fun ContributorsSubscreen(
Column( Column(
Modifier Modifier
.padding(paddingValues) .padding(paddingValues)
.padding(bottom = 8.dp)
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
) { ) {
ContributorsCard( ContributorsCard(
stringResource(R.string.cli_contributors), stringResource(R.string.cli_contributors),
data = vm.cliContributorsList, data = vm.cliContributorsList
size = 100
) )
ContributorsCard( ContributorsCard(
stringResource(R.string.patcher_contributors), stringResource(R.string.patcher_contributors),
data = vm.patcherContributorsList, data = vm.patcherContributorsList
size = 100
) )
ContributorsCard( ContributorsCard(
stringResource(R.string.patches_contributors), stringResource(R.string.patches_contributors),
data = vm.patchesContributorsList, data = vm.patchesContributorsList
size = 200
) )
ContributorsCard( ContributorsCard(
stringResource(R.string.manager_contributors), stringResource(R.string.manager_contributors),
data = vm.managerContributorsList, data = vm.managerContributorsList
size = 100
) )
ContributorsCard( ContributorsCard(
stringResource(R.string.integrations_contributors), stringResource(R.string.integrations_contributors),
data = vm.integrationsContributorsList, data = vm.integrationsContributorsList
size = 200
) )
} }
} }

View File

@ -1,5 +1,6 @@
package app.revanced.manager.ui.viewmodel package app.revanced.manager.ui.viewmodel
import android.app.Application
import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateListOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@ -8,7 +9,10 @@ import app.revanced.manager.repository.GitHubRepository
import app.revanced.manager.util.* import app.revanced.manager.util.*
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class ContributorsViewModel(private val repository: GitHubRepository) : ViewModel() { class ContributorsViewModel(
private val app: Application,
private val repository: GitHubRepository
) : ViewModel() {
val patcherContributorsList = mutableStateListOf<Contributor>() val patcherContributorsList = mutableStateListOf<Contributor>()
val patchesContributorsList = mutableStateListOf<Contributor>() val patchesContributorsList = mutableStateListOf<Contributor>()
val cliContributorsList = mutableStateListOf<Contributor>() val cliContributorsList = mutableStateListOf<Contributor>()
@ -55,6 +59,10 @@ class ContributorsViewModel(private val repository: GitHubRepository) : ViewMode
} }
} }
fun openUserProfile(username: String) {
app.openUrl("https://github.com/${username}")
}
init { init {
viewModelScope.launch { viewModelScope.launch {
loadContributors() loadContributors()

View File

@ -55,17 +55,17 @@
<string name="help_translate">Help translate</string> <string name="help_translate">Help translate</string>
<string name="whats_new">What\'s New</string> <string name="whats_new">What\'s New</string>
<string name="ic_non_selected">No patches are selected!</string> <string name="ic_non_selected">No patches are selected!</string>
<string name="patcher_contributors">Patcher Contributors</string>
<string name="contributor_image">Contributor image</string> <string name="contributor_image">Contributor image</string>
<string name="no_contributors">No contributors</string> <string name="no_contributors">No contributors</string>
<string name="screen_settings_title">Settings</string> <string name="screen_settings_title">Settings</string>
<string name="screen_about_title">About</string> <string name="screen_about_title">About</string>
<string name="about">About</string> <string name="about">About</string>
<string name="navigation_more">More</string> <string name="navigation_more">More</string>
<string name="cli_contributors">CLI Contributors</string> <string name="cli_contributors">CLI</string>
<string name="patches_contributors">Patches Contributors</string> <string name="patcher_contributors">Patcher</string>
<string name="manager_contributors">Manager Contributors</string> <string name="patches_contributors">Patches</string>
<string name="integrations_contributors">Integrations Contributors</string> <string name="manager_contributors">Manager</string>
<string name="integrations_contributors">Integrations</string>
<string name="dropdown_button">Dropdown Button</string> <string name="dropdown_button">Dropdown Button</string>
<string name="app_version">Version</string> <string name="app_version">Version</string>
<string name="faq">FAQ</string> <string name="faq">FAQ</string>