Cleanup and optimize RepositoryList

This commit is contained in:
Iamlooker 2022-06-29 19:31:53 +05:30
parent 555ebac697
commit c7ba399b53
No known key found for this signature in database
GPG Key ID: 16F53B972BAECA48
3 changed files with 92 additions and 81 deletions

View File

@ -0,0 +1,40 @@
package com.looker.droidify.ui.compose.pages.settings.repository
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.looker.droidify.ui.compose.RepositoriesRecycler
import com.looker.droidify.ui.viewmodels.RepositoriesViewModelX
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun RepositoryPage(viewModel: RepositoriesViewModelX) {
val repos by viewModel.repositories.collectAsState()
Scaffold(
modifier = Modifier.fillMaxSize(),
floatingActionButton = {
ExtendedFloatingActionButton(onClick = { viewModel.addRepository() }) {
Icon(imageVector = Icons.Rounded.Add, contentDescription = "Add Repository")
Text(text = "Add Repository")
}
}
) {
val sortedRepoList = remember { repos.sortedBy { !it.enabled } }
RepositoriesRecycler(
repositoriesList = sortedRepoList,
onClick = { viewModel.toggleRepository(it, it.enabled) },
onLongClick = { viewModel.showRepositorySheet(it.id) }
)
}
}

View File

@ -5,64 +5,47 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.fragment.app.viewModels
import com.looker.droidify.R
import androidx.lifecycle.lifecycleScope
import com.looker.droidify.content.Preferences
import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService
import com.looker.droidify.ui.activities.PrefsActivityX
import com.looker.droidify.ui.compose.RepositoriesRecycler
import com.looker.droidify.ui.compose.pages.settings.repository.RepositoryPage
import com.looker.droidify.ui.compose.theme.AppTheme
import com.looker.droidify.ui.viewmodels.RepositoriesViewModelX
import com.looker.droidify.utility.isDarkTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.flow.collectLatest
class PrefsRepositoriesFragment : BaseNavFragment() {
val viewModel: RepositoriesViewModelX by viewModels {
RepositoriesViewModelX.Factory(prefsActivityX.db)
RepositoriesViewModelX.Factory(prefsActivityX.db.repositoryDao)
}
private val prefsActivityX: PrefsActivityX
get() = requireActivity() as PrefsActivityX
private val syncConnection = Connection(SyncService::class.java)
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
super.onCreate(savedInstanceState)
lifecycleScope.launchWhenCreated {
viewModel.showSheet.collectLatest {
it?.let {
RepositorySheetX(it).showNow(childFragmentManager, "Repository $it")
}
}
}
return ComposeView(requireContext()).apply {
setContent { ReposPage() }
}
}
override fun setupLayout() {
syncConnection.bind(requireContext())
viewModel.bindConnection(requireContext())
viewModel.toLaunch.observe(viewLifecycleOwner) {
if (it?.first == true) {
EditRepositorySheetX(it.second)
@ -74,14 +57,11 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
override fun onDestroyView() {
super.onDestroyView()
syncConnection.unbind(requireContext())
viewModel.syncConnection.unbind(requireContext())
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReposPage() {
val repos by viewModel.repositories.observeAsState(null)
AppTheme(
darkTheme = when (Preferences[Preferences.Key.Theme]) {
is Preferences.Theme.System -> isSystemInDarkTheme()
@ -89,46 +69,7 @@ class PrefsRepositoriesFragment : BaseNavFragment() {
else -> isDarkTheme
}
) {
Scaffold { padding ->
Column(
modifier = Modifier.padding(padding)
) {
OutlinedButton(
modifier = Modifier
.padding(8.dp)
.fillMaxWidth(),
contentPadding = PaddingValues(12.dp),
colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colorScheme.primary,
containerColor = MaterialTheme.colorScheme.background
),
onClick = { viewModel.addRepository() }
) {
Text(
modifier = Modifier.weight(1f),
text = stringResource(id = R.string.add_repository),
textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleSmall
)
Icon(
painter = painterResource(id = R.drawable.ic_add),
contentDescription = stringResource(id = R.string.add_repository)
)
}
RepositoriesRecycler(
repositoriesList = repos?.sortedBy { repo -> !repo.enabled },
onClick = { repo ->
GlobalScope.launch(Dispatchers.IO) {
syncConnection.binder?.setEnabled(repo, repo.enabled)
}
},
onLongClick = { repo ->
RepositorySheetX(repo.id)
.showNow(parentFragmentManager, "Repository ${repo.id}")
})
}
}
RepositoryPage(viewModel = viewModel)
}
}
}

View File

@ -1,26 +1,56 @@
package com.looker.droidify.ui.viewmodels
import android.content.Context
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.looker.droidify.database.DatabaseX
import com.looker.droidify.database.dao.RepositoryDao
import com.looker.droidify.database.entity.Repository
import com.looker.droidify.database.entity.Repository.Companion.newRepository
import com.looker.droidify.service.Connection
import com.looker.droidify.service.SyncService
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class RepositoriesViewModelX(val db: DatabaseX) : ViewModel() {
class RepositoriesViewModelX(val repositoryDao: RepositoryDao) : ViewModel() {
val repositories: MediatorLiveData<List<Repository>> = MediatorLiveData()
val toLaunch: MediatorLiveData<Pair<Boolean, Long>?> = MediatorLiveData()
val syncConnection = Connection(SyncService::class.java)
private val _showSheet = MutableStateFlow<Long?>(null)
val showSheet = _showSheet.asStateFlow()
private val _repositories = MutableStateFlow<List<Repository>>(emptyList())
val repositories = _repositories.asStateFlow()
init {
repositories.addSource(db.repositoryDao.allLive, repositories::setValue)
viewModelScope.launch(Dispatchers.IO) {
_repositories.emit(repositoryDao.all)
}
toLaunch.value = null
}
fun bindConnection(context: Context) {
viewModelScope.launch { syncConnection.bind(context) }
}
fun showRepositorySheet(repositoryId: Long) {
viewModelScope.launch {
_showSheet.emit(repositoryId)
}
}
fun toggleRepository(repository: Repository, isEnabled: Boolean) {
viewModelScope.launch(Dispatchers.IO) {
syncConnection.binder?.setEnabled(repository, isEnabled)
}
}
fun addRepository() {
viewModelScope.launch {
toLaunch.value = Pair(true, addNewRepository())
@ -28,19 +58,19 @@ class RepositoriesViewModelX(val db: DatabaseX) : ViewModel() {
}
private suspend fun addNewRepository(): Long = withContext(Dispatchers.IO) {
db.repositoryDao.insert(newRepository(address = "new.Repository"))
db.repositoryDao.latestAddedId()
repositoryDao.insert(newRepository())
repositoryDao.latestAddedId()
}
fun emptyToLaunch() {
toLaunch.value = null
}
class Factory(val db: DatabaseX) : ViewModelProvider.Factory {
class Factory(private val repoDao: RepositoryDao) : ViewModelProvider.Factory {
@Suppress("unchecked_cast")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
if (modelClass.isAssignableFrom(RepositoriesViewModelX::class.java)) {
return RepositoriesViewModelX(db) as T
return RepositoriesViewModelX(repoDao) as T
}
throw IllegalArgumentException("Unknown ViewModel class")
}