Skip to content

Commit

Permalink
Gsoc 2023 home screen migrartion (#25)
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_login.xml to LoginScreen.kt Compose and Updated
facebook Sdk version to latest and added code changes according to new
methods in doc and updated gitlab-ci.yml for fbClientSecret

* Migrated fragment_home.xml to HomeScreen.kt in compose
  • Loading branch information
narendraanjana09 authored Aug 29, 2023
1 parent 2cc3536 commit 3146332
Show file tree
Hide file tree
Showing 16 changed files with 349 additions and 503 deletions.
4 changes: 4 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ dependencies {
implementation composeBom
androidTestImplementation composeBom
implementation 'androidx.compose.material3:material3'
implementation 'androidx.compose.material:material'
implementation 'androidx.compose.ui:ui-tooling-preview'
debugImplementation 'androidx.compose.ui:ui-tooling'
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
Expand All @@ -213,4 +214,7 @@ dependencies {

//extended Material Icons
implementation "androidx.compose.material:material-icons-extended:1.4.3"

//for live data to state
implementation("androidx.compose.runtime:runtime-livedata:$rootProject.composeLiveData")
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import org.aossie.agoraandroid.data.network.dto.ElectionDto
import org.aossie.agoraandroid.data.network.dto.VotersDto
import org.aossie.agoraandroid.data.network.dto.WinnerDto
import org.aossie.agoraandroid.data.network.responses.Ballots
import org.aossie.agoraandroid.data.network.responses.ElectionListResponse
import org.aossie.agoraandroid.data.network.responses.ElectionResponse
import org.aossie.agoraandroid.domain.repository.ElectionsRepository
import org.aossie.agoraandroid.utilities.ApiException
Expand Down Expand Up @@ -107,7 +108,7 @@ constructor(
db.getElectionDao()
.getPendingElections(currentDate)

override suspend fun fetchElections() {
override suspend fun fetchElections(): ElectionListResponse {
val isNeeded = prefs.getUpdateNeeded().first()
if (isNeeded) {
try {
Expand All @@ -117,12 +118,14 @@ constructor(
elections.postValue(it)
}
Timber.d(response.toString())
return response
} catch (e: NoInternetException) {
} catch (e: ApiException) {
} catch (e: SessionExpirationException) {
} catch (e: IOException) {
}
}
return ElectionListResponse(elections.value!!)
}

override fun getFinishedElections(currentDate: String): Flow<List<Election>> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@ import org.aossie.agoraandroid.data.network.dto.ElectionDto
import org.aossie.agoraandroid.data.network.dto.VotersDto
import org.aossie.agoraandroid.data.network.dto.WinnerDto
import org.aossie.agoraandroid.data.network.responses.Ballots
import org.aossie.agoraandroid.data.network.responses.ElectionListResponse
import org.aossie.agoraandroid.data.network.responses.ElectionResponse

interface ElectionsRepository {
suspend fun fetchAndSaveElections()
suspend fun fetchAndSaveElections(): ElectionListResponse
fun getElections(): Flow<List<Election>>
fun getFinishedElectionsCount(currentDate: String): LiveData<Int>
fun getPendingElectionsCount(currentDate: String): LiveData<Int>
fun getTotalElectionsCount(): LiveData<Int>
fun getActiveElectionsCount(currentDate: String): LiveData<Int>
suspend fun saveElections(elections: List<ElectionResponse>)
fun getPendingElections(currentDate: String): Flow<List<Election>>
suspend fun fetchElections()
suspend fun fetchElections(): ElectionListResponse
fun getFinishedElections(currentDate: String): Flow<List<Election>>
fun getActiveElections(currentDate: String): Flow<List<Election>>
fun getElectionById(id: String): Flow<Election>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package org.aossie.agoraandroid.domain.useCases.homeFragment

import org.aossie.agoraandroid.data.network.responses.ElectionListResponse
import org.aossie.agoraandroid.domain.repository.ElectionsRepository
import javax.inject.Inject

class FetchAndSaveElectionUseCase @Inject constructor(
private val electionsRepository: ElectionsRepository
) {
suspend operator fun invoke() {
suspend operator fun invoke(): ElectionListResponse {
return electionsRepository.fetchAndSaveElections()
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
package org.aossie.agoraandroid.ui.fragments.home

import android.content.res.Configuration
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.doOnLayout
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.viewModels
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.Navigation
import com.takusemba.spotlight.Spotlight
import androidx.navigation.fragment.findNavController
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import org.aossie.agoraandroid.R.color
import org.aossie.agoraandroid.R.string
import org.aossie.agoraandroid.data.db.PreferenceProvider
import org.aossie.agoraandroid.databinding.FragmentHomeBinding
import org.aossie.agoraandroid.ui.fragments.BaseFragment
import org.aossie.agoraandroid.ui.fragments.auth.login.LoginViewModel
import org.aossie.agoraandroid.utilities.ResponseUI
import org.aossie.agoraandroid.utilities.TargetData
import org.aossie.agoraandroid.utilities.getSpotlight
import org.aossie.agoraandroid.utilities.scrollToView
import org.aossie.agoraandroid.ui.screens.auth.login.events.LoginUiEvent.UserLoggedIn
import org.aossie.agoraandroid.ui.screens.common.Util.ScreensState
import org.aossie.agoraandroid.ui.screens.home.HomeScreen
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.ActiveElectionClick
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.CreateElectionClick
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.FinishedElectionClick
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.PendingElectionClick
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.Refresh
import org.aossie.agoraandroid.ui.screens.home.events.HomeScreenEvents.TotalElectionClick
import org.aossie.agoraandroid.ui.theme.AgoraTheme
import timber.log.Timber
import java.text.ParseException
import java.text.SimpleDateFormat
Expand All @@ -45,64 +52,68 @@ constructor(
viewModelFactory
}

private lateinit var binding: FragmentHomeBinding

private var spotlight: Spotlight? = null
private var spotlightTargets: ArrayList<TargetData>? = null
private var currentSpotlightIndex = 0
private lateinit var composeView: ComposeView

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

override fun onFragmentInitiated() {
loginViewModel.sessionExpiredListener = this
binding.swipeRefresh.setColorSchemeResources(color.logo_yellow, color.logo_green)
composeView.setContent {
val homeScreenDataState by homeViewModel.countMediatorLiveData.observeAsState()

binding.cardViewActiveElections.setOnClickListener {
Navigation.findNavController(binding.root)
.navigate(HomeFragmentDirections.actionHomeFragmentToActiveElectionsFragment())
}
binding.cardViewPendingElections.setOnClickListener {
Navigation.findNavController(binding.root)
.navigate(HomeFragmentDirections.actionHomeFragmentToPendingElectionsFragment())
}
binding.cardViewFinishedElections.setOnClickListener {
Navigation.findNavController(binding.root)
.navigate(HomeFragmentDirections.actionHomeFragmentToFinishedElectionsFragment())
}
binding.cardViewTotalElections.setOnClickListener {
Navigation.findNavController(binding.root)
.navigate(HomeFragmentDirections.actionHomeFragmentToElectionsFragment())
}
binding.buttonCreateElection.setOnClickListener {
Navigation.findNavController(binding.root)
.navigate(HomeFragmentDirections.actionHomeFragmentToCreateElectionFragment())
}
binding.swipeRefresh.setOnRefreshListener { updateUi() }
val progressErrorState1 = loginViewModel.progressAndErrorState
val progressErrorState2 = homeViewModel.progressAndErrorState

lifecycleScope.launch {
loginViewModel.getLoginStateFlow.collect {
if (it != null) {
when (it.status) {
ResponseUI.Status.LOADING -> {
// Do Nothing
}
ResponseUI.Status.SUCCESS -> {
val progressErrorState by merge(progressErrorState1,progressErrorState2).collectAsState(initial = ScreensState())

LaunchedEffect(key1 = Unit) {
loginViewModel.uiEvents.collectLatest { event ->
when(event) {
UserLoggedIn -> {
updateUi()
}
ResponseUI.Status.ERROR -> {
notify(it.message)
}
else -> {}
}
}
}

AgoraTheme {
HomeScreen(homeScreenDataState,progressErrorState){ event ->
when(event){
ActiveElectionClick -> {
findNavController()
.navigate(HomeFragmentDirections.actionHomeFragmentToActiveElectionsFragment())
}
CreateElectionClick -> {
findNavController()
.navigate(HomeFragmentDirections.actionHomeFragmentToCreateElectionFragment())
}
FinishedElectionClick -> {
findNavController()
.navigate(HomeFragmentDirections.actionHomeFragmentToFinishedElectionsFragment())
}
PendingElectionClick -> {
findNavController()
.navigate(HomeFragmentDirections.actionHomeFragmentToPendingElectionsFragment())
}
TotalElectionClick -> {
findNavController()
.navigate(HomeFragmentDirections.actionHomeFragmentToElectionsFragment())
}
Refresh -> {
updateUi()
}
}
}
}
}

lifecycleScope.launch {
Expand Down Expand Up @@ -141,31 +152,14 @@ constructor(
}
}

homeViewModel.countMediatorLiveData.observe(
viewLifecycleOwner,
{
binding.textViewActiveCount.text = it[ACTIVE_ELECTION_COUNT].toString()
binding.textViewTotalCount.text = it[TOTAL_ELECTION_COUNT].toString()
binding.textViewPendingCount.text = it[PENDING_ELECTION_COUNT].toString()
binding.textViewFinishedCount.text = it[FINISHED_ELECTION_COUNT].toString()
binding.shimmerViewContainer.stopShimmer()
binding.shimmerViewContainer.visibility = View.GONE
binding.constraintLayout.visibility = View.VISIBLE
binding.swipeRefresh.isRefreshing = false // Disables the refresh icon
}
)
updateUi()
binding.root.doOnLayout {
checkIsFirstOpen()
}
}

override fun onNetworkConnected() {
updateUi()
}

override fun onDestroyView() {
binding.swipeRefresh.setOnRefreshListener(null)
homeViewModel.sessionExpiredListener = null
loginViewModel.sessionExpiredListener = null
super.onDestroyView()
Expand All @@ -176,70 +170,5 @@ constructor(
preferenceProvider.setUpdateNeeded(true)
homeViewModel.getElections()
}
binding.shimmerViewContainer.startShimmer()
binding.shimmerViewContainer.visibility = View.VISIBLE
binding.constraintLayout.visibility = View.GONE
}

private fun checkIsFirstOpen() {
lifecycleScope.launch {
if (!preferenceProvider.isDisplayed(binding.root.id.toString())
.first()
) {
spotlightTargets = getSpotlightTargets()
preferenceProvider.setDisplayed(binding.root.id.toString())
showSpotlight()
}
}
}

private fun showSpotlight() {
spotlightTargets?.let {
if (currentSpotlightIndex in it.indices) {
scrollToView(binding.scrollView, it[currentSpotlightIndex].targetView)
spotlight = requireActivity().getSpotlight(
it[currentSpotlightIndex++],
{
destroySpotlight()
},
{
it.clear()
destroySpotlight()
},
{
if (isAdded) {
showSpotlight()
}
}
)
spotlight?.start()
}
}
}

private fun getSpotlightTargets(): ArrayList<TargetData> {
val targetData = ArrayList<TargetData>()
targetData.add(
TargetData(
binding.buttonCreateElection, getString(string.Create_Election),
getString(string.create_election_spotlight)
)
)
return targetData
}

private fun destroySpotlight() {
spotlight?.finish()
spotlight = null
}

override fun onPause() {
super.onPause()
destroySpotlight()
}

override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
destroySpotlight()
}
}
Loading

0 comments on commit 3146332

Please sign in to comment.