Skip to content

Commit

Permalink
Gsoc 2023 migrating ballot list fragment to compose (#52)
Browse files Browse the repository at this point in the history
* Update for some issue In Deploy to Appetize

* removed Github Token from ci file

* Migrated fragment_election_details.xml to ElectionDetailsScreen.kt in compose

* Migrated fragment_ballot.xml to BallotsListScreen.kt in compose

* Migrated fragment_voters.xml.xml to VotersListScreen.kt in compose

* Migrated fragment_ballot.xml to BallotsListScreen.kt in compose
  • Loading branch information
narendraanjana09 authored Aug 31, 2023
1 parent cf45233 commit 42e93e8
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 201 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import org.aossie.agoraandroid.domain.model.ElectionModel
import org.aossie.agoraandroid.domain.useCases.displayElection.DisplayElectionsUseCases
import org.aossie.agoraandroid.ui.screens.common.Util.ScreensState
import org.aossie.agoraandroid.utilities.AppConstants
import org.aossie.agoraandroid.utilities.lazyDeferred
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
Expand Down Expand Up @@ -71,6 +70,7 @@ constructor(
showMessage(R.string.something_went_wrong_please_try_again_later)
}
}
}

fun getPendingElectionsState(query:String) {
viewModelScope.launch {
Expand Down Expand Up @@ -112,69 +112,6 @@ constructor(
)
}

val finishedElections = MutableStateFlow<List<ElectionModel>>(emptyList())
val search = mutableStateOf("")

private val _progressAndErrorState = MutableStateFlow (ScreensState())
val progressAndErrorState = _progressAndErrorState.asStateFlow()

fun getFinishedElectionsState(query:String){
viewModelScope.launch {
try {
displayElectionsUseCases.getFinishedElections(date).collectLatest { list ->
search.value = query
if(query.isEmpty()) {
finishedElections.emit(list)
}else{
finishedElections.emit(filter(list, query))
}
}
} catch (e: IllegalStateException) {
showMessage(R.string.something_went_wrong_please_try_again_later)
}
}
}

fun getActiveElectionsState(query:String) {
viewModelScope.launch {
try {
displayElectionsUseCases.getActiveElections(date).collectLatest { list ->
search.value = query
if(query.isEmpty()) {
activeElections.emit(list)
}else{
activeElections.emit(filter(list, query))
}
}
} catch (e: IllegalStateException) {
showMessage(R.string.something_went_wrong_please_try_again_later)
}
}
}

private fun showLoading(message: Any) {
_progressAndErrorState.value = progressAndErrorState.value.copy(
loading = Pair(message,true)
)
}

fun showMessage(message: Any) {
_progressAndErrorState.value = progressAndErrorState.value.copy(
message = Pair(message,true),
loading = Pair("",false)
)
viewModelScope.launch {
delay(AppConstants.SNACKBAR_DURATION)
hideSnackBar()
}
}

private fun hideSnackBar() {
_progressAndErrorState.value = progressAndErrorState.value.copy(
message = Pair("",false)
)
}

private fun hideLoading() {
_progressAndErrorState.value = progressAndErrorState.value.copy(
loading = Pair("",false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.coroutines.launch
import org.aossie.agoraandroid.R
import org.aossie.agoraandroid.data.adapters.BallotsAdapter
import org.aossie.agoraandroid.databinding.FragmentBallotBinding
import org.aossie.agoraandroid.domain.model.BallotDtoModel
import org.aossie.agoraandroid.ui.fragments.BaseFragment
import org.aossie.agoraandroid.utilities.ResponseUI
import org.aossie.agoraandroid.utilities.hide
import org.aossie.agoraandroid.utilities.show
import org.aossie.agoraandroid.ui.screens.ballotslist.BallotsListScreen
import org.aossie.agoraandroid.ui.theme.AgoraTheme
import javax.inject.Inject

/**
Expand All @@ -35,84 +29,36 @@ constructor(
}

private var id: String? = null
private lateinit var binding: FragmentBallotBinding
private lateinit var composeView: ComposeView

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentBallotBinding.inflate(inflater)
return binding.root
return ComposeView(requireContext()).also {
composeView = it
}
}

override fun onFragmentInitiated() {

binding.tvEmptyBallots.hide()
electionDetailsViewModel.sessionExpiredListener = this

binding.recyclerViewBallots.apply {
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
val arr = ArrayList<BallotDtoModel>()
adapter = BallotsAdapter(arr)
}

id = VotersFragmentArgs.fromBundle(
requireArguments()
).id
electionDetailsViewModel.getBallot(id)
}

override fun onNetworkConnected() {
electionDetailsViewModel.getBallot(id)
}

override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)

lifecycleScope.launch {
electionDetailsViewModel.getBallotResponseStateFlow.collect { responseUI ->
if (responseUI != null) {
when (responseUI.status) {
ResponseUI.Status.LOADING -> binding.progressBar.hide()
ResponseUI.Status.SUCCESS -> {
binding.progressBar.hide()
responseUI.dataList?.let {
initRecyclerView(it)
} ?: binding.tvEmptyBallots.show()
}
ResponseUI.Status.ERROR -> {
if (responseUI.message == getString(R.string.no_network)) getBallotsFromDb()
else {
notify(responseUI.message)
binding.progressBar.hide()
}
}
else -> {}
}
}
composeView.setContent {
val progressErrorState by electionDetailsViewModel.progressAndErrorState
val ballotsList by electionDetailsViewModel.ballotsListState.collectAsState()
AgoraTheme() {
BallotsListScreen(
ballotsList = ballotsList,
progressErrorState = progressErrorState)
}
}
}

private fun initRecyclerView(ballots: List<BallotDtoModel>) {
if (ballots.isEmpty()) {
binding.tvEmptyBallots.show()
}
val ballotsAdapter = BallotsAdapter(ballots)
binding.recyclerViewBallots.apply {
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
adapter = ballotsAdapter
}
}

private fun getBallotsFromDb() {
lifecycleScope.launch {
electionDetailsViewModel.getElectionById(id!!)
.collect {
initRecyclerView(it.ballot as List<BallotDtoModel>)
binding.progressBar.hide()
}
}
override fun onNetworkConnected() {
electionDetailsViewModel.getBallot(id)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,6 @@ constructor(
private val electionDetailsUseCases: ElectionDetailsUseCases
) : ViewModel() {

private val _getBallotResponseStateFlow = MutableStateFlow<ResponseUI<BallotDtoModel>?>(null)
var getBallotResponseStateFlow: StateFlow<ResponseUI<BallotDtoModel>?> =
_getBallotResponseStateFlow
private val _getShareResponseStateFlow = MutableStateFlow<ResponseUI<Uri>?>(null)
var getShareResponseStateFlow: StateFlow<ResponseUI<Uri>?> = _getShareResponseStateFlow
private val _getResultResponseStateFlow = MutableStateFlow<ResponseUI<WinnerDtoModel>?>(null)
Expand All @@ -77,6 +74,9 @@ constructor(
private val _votersListState = MutableStateFlow<List<VotersDtoModel>>(emptyList())
val votersListState = _votersListState.asStateFlow()

private val _ballotsListState = MutableStateFlow<List<BallotDtoModel>>(emptyList())
val ballotsListState = _ballotsListState.asStateFlow()

private var _electionState = mutableStateOf<ElectionModel?>(null)
val electionState: State<ElectionModel?> = _electionState

Expand Down Expand Up @@ -106,24 +106,41 @@ constructor(
fun getBallot(
id: String?
) {
_getBallotResponseStateFlow.value = ResponseUI.loading()
showLoading("Listing ballots...")
viewModelScope.launch {
try {
val response: List<BallotDtoModel> = electionDetailsUseCases.getBallots(id)
Timber.d(response.toString())
_getBallotResponseStateFlow.value = ResponseUI.success(response)
_ballotsListState.value = response
hideLoading()
} catch (e: ApiException) {
_getBallotResponseStateFlow.value = ResponseUI.error(e.message)
showMessage(e.message!!)
getBallotsFromDb(id)
} catch (e: SessionExpirationException) {
sessionExpiredListener.onSessionExpired()
} catch (e: NoInternetException) {
_getBallotResponseStateFlow.value = ResponseUI.error(e.message)
showMessage(e.message!!)
getBallotsFromDb(id)
} catch (e: Exception) {
_getBallotResponseStateFlow.value = ResponseUI.error(e.message)
showMessage(e.message!!)
getBallotsFromDb(id)
}
}
}

private fun getBallotsFromDb(id: String?) {
showLoading("Listing ballots...")
viewModelScope.launch {
getElectionById(id!!)
.collect {
if (it != null) {
_ballotsListState.value = (it.ballot as List<BallotDtoModel>)
}
hideLoading()
}
}
}

fun getVoter(
id: String?
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.aossie.agoraandroid.data.db.PreferenceProvider
Expand Down Expand Up @@ -45,9 +44,6 @@ constructor(
.time
private val date: String = formatter.format(currentDate)

private val _progressAndErrorState = MutableStateFlow (ScreensState())
val progressAndErrorState = _progressAndErrorState.asStateFlow()

private val _countMediatorLiveData = MediatorLiveData<MutableMap<String, Int>>()
val countMediatorLiveData = _countMediatorLiveData

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.aossie.agoraandroid.ui.screens.ballotslist

import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import org.aossie.agoraandroid.R
import org.aossie.agoraandroid.domain.model.BallotDtoModel
import org.aossie.agoraandroid.ui.screens.common.Util.ScreensState
import org.aossie.agoraandroid.ui.screens.common.component.PrimaryProgressSnackView

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BallotsListScreen(
ballotsList: List<BallotDtoModel>,
progressErrorState: ScreensState,
){
Scaffold(
modifier = Modifier.fillMaxSize(),
containerColor = MaterialTheme.colorScheme.background,
) {
Box {
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(it),
contentPadding = PaddingValues(20.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(ballotsList) {
BallotItem(it)
}
}
if(ballotsList.isEmpty() && !progressErrorState.loading.second){
Text(
text = stringResource(id = R.string.empty_ballots),
modifier = Modifier
.align(Alignment.Center)
)
}
PrimaryProgressSnackView(screenState = progressErrorState)
}
}
}

@Composable
fun BallotItem(ballotDtoModel: BallotDtoModel) {
Column(
modifier = Modifier
.fillMaxWidth()
.border(
width = 1.dp,
shape = RoundedCornerShape(8.dp),
color = MaterialTheme.colorScheme.outline
)
.padding(10.dp)
) {
Text(text = ballotDtoModel.voteBallot!!, style = MaterialTheme.typography.titleLarge)
Text(text = ballotDtoModel.hash!!, style = MaterialTheme.typography.titleSmall)
}
}
Loading

0 comments on commit 42e93e8

Please sign in to comment.