Skip to content

Commit

Permalink
Merge pull request #12 from PopStackHack/release/4.1.1
Browse files Browse the repository at this point in the history
Release/4.1.1
  • Loading branch information
vincent-paing authored Oct 17, 2020
2 parents 6afb51b + 1c6ba7c commit 6a70e43
Show file tree
Hide file tree
Showing 55 changed files with 967 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import android.app.Application
import com.popstack.mvoter2015.MVoterApp
import com.popstack.mvoter2015.di.module.AppModule
import com.popstack.mvoter2015.feature.about.AboutFeatureModule
import com.popstack.mvoter2015.feature.analytics.location.SelectedLocationAnalyticsModule
import com.popstack.mvoter2015.feature.candidate.CandidateFeatureModule
import com.popstack.mvoter2015.feature.faq.FaqFeatureModule
import com.popstack.mvoter2015.feature.location.LocationUpdateFeatureModule
import com.popstack.mvoter2015.feature.news.NewsFeatureModule
import com.popstack.mvoter2015.feature.party.PartyFeatureModule
import com.popstack.mvoter2015.feature.settings.SettingsFeatureModule
import com.popstack.mvoter2015.feature.voterlist.VoterListFeatureModule
import com.popstack.mvoter2015.feature.votingguide.VotingGuideFeatureModule
import dagger.BindsInstance
import dagger.Component
Expand All @@ -30,7 +32,9 @@ import javax.inject.Singleton
VotingGuideFeatureModule::class,
NewsFeatureModule::class,
SettingsFeatureModule::class,
AboutFeatureModule::class
AboutFeatureModule::class,
VoterListFeatureModule::class,
SelectedLocationAnalyticsModule::class
]
)
interface AppComponent {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.popstack.mvoter2015.di.conductor.ConductorInjectionModule
import com.popstack.mvoter2015.di.viewmodel.ViewModelFactoryModule
import com.popstack.mvoter2015.domain.DispatcherProvider
import com.popstack.mvoter2015.feature.HostActivity
import com.popstack.mvoter2015.feature.home.BottomNavigationHostController
import com.popstack.mvoter2015.helper.AndroidDispatcherProvider
import dagger.Binds
import dagger.Module
Expand All @@ -26,6 +27,9 @@ abstract class AppModule {
@ContributesAndroidInjector
abstract fun hostActivity(): HostActivity

@ContributesAndroidInjector
abstract fun bottomNavigationHostController(): BottomNavigationHostController

companion object Provider {

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class AboutController : LifeCycleAwareController<ControllerAboutBinding>(), Inje
runCatching {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), "https://mvoterapp.com/terms")
.launchInBrowser(requireActivity(), "https://mvoterapp.com/terms")
}
}
}
Expand All @@ -53,7 +53,7 @@ class AboutController : LifeCycleAwareController<ControllerAboutBinding>(), Inje
runCatching {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), "https://mvoterapp.com/privacy")
.launchInBrowser(requireActivity(), "https://mvoterapp.com/privacy")
}
}
}
Expand Down Expand Up @@ -97,7 +97,7 @@ class AboutController : LifeCycleAwareController<ControllerAboutBinding>(), Inje
runCatching {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), "https://mvoterapp.com/")
.launchInBrowser(requireActivity(), "https://mvoterapp.com/")
}
}
}
Expand All @@ -115,7 +115,7 @@ class AboutController : LifeCycleAwareController<ControllerAboutBinding>(), Inje
runCatching {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), "https://www.facebook.com/mvoter2015")
.launchInBrowser(requireActivity(), "https://www.facebook.com/mvoter2015")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.popstack.mvoter2015.feature.analytics.location

import com.popstack.mvoter2015.domain.location.model.CombinedLocation
import timber.log.Timber
import javax.inject.Inject

class FakeLoggingSelectedLocationAnalyticsImpl @Inject constructor() : SelectedLocationAnalytics {

override fun logLocation(combinedLocation: CombinedLocation) {
Timber.i("state: ${combinedLocation.stateRegion}, township : ${combinedLocation.township}, ward : ${combinedLocation.ward ?: "N/A"} ")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.popstack.mvoter2015.feature.analytics.location

import android.content.Context
import com.google.firebase.analytics.FirebaseAnalytics
import com.popstack.mvoter2015.domain.location.model.CombinedLocation
import javax.inject.Inject

class RealSelectedLocationAnalyticsImpl @Inject constructor(
private val context: Context
) : SelectedLocationAnalytics {

companion object {
private const val PROPERTY_NAME_GEO = "geo"
}

override fun logLocation(combinedLocation: CombinedLocation) {
val property = with(combinedLocation) {
if (ward == null) {
"$stateRegion|$township"
} else {
"$ward|$township|$stateRegion"
}
}
FirebaseAnalytics.getInstance(context).setUserProperty(PROPERTY_NAME_GEO, property)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.popstack.mvoter2015.feature.analytics.location

import com.popstack.mvoter2015.domain.location.model.CombinedLocation

interface SelectedLocationAnalytics {

fun logLocation(combinedLocation: CombinedLocation)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.popstack.mvoter2015.feature.analytics.location

import android.content.Context
import com.popstack.mvoter2015.data.cache.BuildConfig
import dagger.Module
import dagger.Provides

@Module
abstract class SelectedLocationAnalyticsModule {

companion object {

@Provides
fun selectedLocationAnalytics(context: Context): SelectedLocationAnalytics {
return if (BuildConfig.DEBUG) {
FakeLoggingSelectedLocationAnalyticsImpl()
} else {
RealSelectedLocationAnalyticsImpl(context)
}
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import com.popstack.mvoter2015.helper.intent.Intents

interface OpenBrowserHandler {

fun launchNewsInBrowser(activity: Activity, url: String)
fun launchInBrowser(activity: Activity, url: String)

}

class InAppBrowserHandler() : OpenBrowserHandler {

override fun launchNewsInBrowser(activity: Activity, url: String) {
override fun launchInBrowser(activity: Activity, url: String) {
CustomTabsIntent.Builder()
.setToolbarColor(ContextCompat.getColor(activity, R.color.accent))
.build()
Expand All @@ -26,7 +26,7 @@ class InAppBrowserHandler() : OpenBrowserHandler {

class ExternalBrowserHandler() : OpenBrowserHandler {

override fun launchNewsInBrowser(activity: Activity, url: String) {
override fun launchInBrowser(activity: Activity, url: String) {
val intent = Intents.viewUrl(url)
activity.startActivity(intent)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.popstack.mvoter2015.feature.faq.search.FaqSearchController
import com.popstack.mvoter2015.feature.home.BottomNavigationHostViewModelStore
import com.popstack.mvoter2015.feature.settings.SettingsController
import com.popstack.mvoter2015.feature.share.ShareUrlFactory
import com.popstack.mvoter2015.feature.voterlist.VoterListController
import com.popstack.mvoter2015.helper.RecyclerViewMarginDecoration
import com.popstack.mvoter2015.helper.conductor.requireActivity
import com.popstack.mvoter2015.helper.conductor.requireActivityAsAppCompatActivity
Expand Down Expand Up @@ -60,10 +61,17 @@ class FaqController : MvvmController<ControllerFaqBinding>(), HasTag, CanTrackSc
private val faqPagingAdapter by lazy {
FaqPagingAdapter(
ballotExampleClick = { navigateToBallotExample() },
checkVoterListClick = {
router.pushController(
RouterTransaction.with(
VoterListController()
)
)
},
lawsAndUnfairPractice = {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), "https://mvoterapp.com/election-law")
.launchInBrowser(requireActivity(), "https://mvoterapp.com/election-law")
}
},
share = { faqId, _ ->
Expand Down Expand Up @@ -132,7 +140,7 @@ class FaqController : MvvmController<ControllerFaqBinding>(), HasTag, CanTrackSc

faqPagingAdapter.addLoadStateListener { loadStates ->
val refreshLoadState = loadStates.refresh
binding.rvFaq.isVisible = refreshLoadState is LoadState.NotLoading
binding.rvFaq.isVisible = refreshLoadState !is LoadState.Error
if (refreshLoadState is LoadState.Loading) binding.progressIndicator.show()
else binding.progressIndicator.hide()
binding.tvErrorMessage.isVisible = refreshLoadState is LoadState.Error
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.RecyclerView
import com.popstack.mvoter2015.databinding.ItemFaqBallotExampleBinding
import com.popstack.mvoter2015.databinding.ItemFaqBinding
import com.popstack.mvoter2015.databinding.ItemFaqCheckVoterListBinding
import com.popstack.mvoter2015.databinding.ItemFaqLawsAndUnfairPracticeBinding
import com.popstack.mvoter2015.databinding.ItemFaqPollingStationProhibitionBinding
import com.popstack.mvoter2015.domain.faq.model.FaqId
Expand All @@ -20,16 +21,18 @@ import com.popstack.mvoter2015.helper.extensions.withSafeAdapterPosition

class FaqPagingAdapter(
private val ballotExampleClick: () -> Unit,
private val checkVoterListClick: () -> Unit,
private val lawsAndUnfairPractice: () -> Unit,
private val share: (FaqId, @ParameterName("position") Int) -> Unit
) :
PagingDataAdapter<FaqViewItem, FaqPagingAdapter.InfoViewHolder>(
diffCallBackWith(
areItemTheSame = { item1, item2 ->
if (item1 is FaqViewItem.QuestionAndAnswer && item2 is FaqViewItem.QuestionAndAnswer) {
return@diffCallBackWith item1.faqId == item2.faqId
item1.faqId == item2.faqId
} else {
item1 == item2
}
item1 == item2
},
areContentsTheSame = { item1, item2 ->
item1 == item2
Expand All @@ -46,8 +49,9 @@ class FaqPagingAdapter(
companion object {
const val VIEW_TYPE_BALLOT_EXAMPLE = 1
const val VIEW_TYPE_PROHIBITION = 2
const val VIEW_TYPE_LAWS_AND_UNFAIR_PRACTICE = 3
const val VIEW_TYPE_FAQ = 4
const val VIEW_TYPE_CHECK_VOTER_LIST = 3
const val VIEW_TYPE_LAWS_AND_UNFAIR_PRACTICE = 4
const val VIEW_TYPE_FAQ = 5
}

override fun getItemViewType(position: Int): Int {
Expand All @@ -59,6 +63,7 @@ class FaqPagingAdapter(
return when (itemAtIndex) {
FaqViewItem.BallotExample -> VIEW_TYPE_BALLOT_EXAMPLE
FaqViewItem.PollingStationProhibition -> VIEW_TYPE_PROHIBITION
FaqViewItem.CheckVoterList -> VIEW_TYPE_CHECK_VOTER_LIST
is FaqViewItem.LawAndUnfairPractices -> VIEW_TYPE_LAWS_AND_UNFAIR_PRACTICE
is FaqViewItem.QuestionAndAnswer -> VIEW_TYPE_FAQ
}
Expand All @@ -81,6 +86,15 @@ class FaqPagingAdapter(
ItemFaqPollingStationProhibitionBinding.inflate(parent.inflater(), parent, false)
return InfoViewHolder.PollingStationProhibitionViewHolder(binding)
}
VIEW_TYPE_CHECK_VOTER_LIST -> {
val binding =
ItemFaqCheckVoterListBinding.inflate(parent.inflater(), parent, false)
return InfoViewHolder.CheckVoterListViewHolder(binding).also {
it.itemView.setOnClickListener {
checkVoterListClick.invoke()
}
}
}
VIEW_TYPE_LAWS_AND_UNFAIR_PRACTICE -> {
val binding =
ItemFaqLawsAndUnfairPracticeBinding.inflate(parent.inflater(), parent, false)
Expand Down Expand Up @@ -154,6 +168,9 @@ class FaqPagingAdapter(
class PollingStationProhibitionViewHolder(binding: ItemFaqPollingStationProhibitionBinding) :
InfoViewHolder(binding.root)

class CheckVoterListViewHolder(binding: ItemFaqCheckVoterListBinding) :
InfoViewHolder(binding.root)

class LawsAndUnfairPractices(binding: ItemFaqLawsAndUnfairPracticeBinding) :
InfoViewHolder(binding.root)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ sealed class FaqViewItem {

object PollingStationProhibition : FaqViewItem()

object CheckVoterList : FaqViewItem()

object LawAndUnfairPractices : FaqViewItem()

data class QuestionAndAnswer(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import androidx.paging.map
import com.popstack.mvoter2015.data.android.faq.FaqPagerFactory
import com.popstack.mvoter2015.domain.faq.model.Faq
import com.popstack.mvoter2015.domain.faq.model.FaqCategory
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject

class FaqViewModel @Inject constructor(
private val faqPagerFactory: FaqPagerFactory
Expand Down Expand Up @@ -48,6 +48,7 @@ class FaqViewModel @Inject constructor(

if (selectedFaqCategory == FaqCategory.VOTER_LIST) {
viewItemPagingData
.insertHeaderItem(FaqViewItem.CheckVoterList)
.insertHeaderItem(FaqViewItem.PollingStationProhibition)
.insertHeaderItem(FaqViewItem.BallotExample)
} else if (selectedFaqCategory == FaqCategory.CANDIDATE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,27 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.RecyclerView
import com.bluelinelabs.conductor.RouterTransaction
import com.popstack.mvoter2015.R
import com.popstack.mvoter2015.core.BaseController
import com.popstack.mvoter2015.core.LifeCycleAwareController
import com.popstack.mvoter2015.databinding.ControllerBottomNavHostBinding
import com.popstack.mvoter2015.di.Injectable
import com.popstack.mvoter2015.domain.location.usecase.GetUserSelectedLocation
import com.popstack.mvoter2015.feature.analytics.location.SelectedLocationAnalytics
import com.popstack.mvoter2015.feature.candidate.listing.CandidateListController
import com.popstack.mvoter2015.feature.faq.FaqController
import com.popstack.mvoter2015.feature.news.NewsController
import com.popstack.mvoter2015.feature.party.listing.PartyListController
import com.popstack.mvoter2015.feature.votingguide.VotingGuideController
import com.popstack.mvoter2015.helper.conductor.BNVRouterPagerAdapter
import com.popstack.mvoter2015.logging.HasTag
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

class BottomNavigationHostController : BaseController<ControllerBottomNavHostBinding>(), HasTag {
class BottomNavigationHostController : LifeCycleAwareController<ControllerBottomNavHostBinding>(), HasTag, Injectable {

override val tag: String = TAG

Expand All @@ -31,6 +38,12 @@ class BottomNavigationHostController : BaseController<ControllerBottomNavHostBin
override val bindingInflater: (LayoutInflater) -> ControllerBottomNavHostBinding =
ControllerBottomNavHostBinding::inflate

@Inject
lateinit var getUserSelectedLocation: GetUserSelectedLocation

@Inject
lateinit var selectedLocationAnalytics: SelectedLocationAnalytics

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup,
Expand Down Expand Up @@ -93,6 +106,14 @@ class BottomNavigationHostController : BaseController<ControllerBottomNavHostBin
}
}
}

lifecycleScope.launch {
getUserSelectedLocation.execute(Unit).collectLatest { combinedLocation ->
if (combinedLocation != null) {
selectedLocationAnalytics.logLocation(combinedLocation)
}
}
}
}

override fun onDestroyView(view: View) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ class NewsController : MvvmController<ControllerNewsBinding>(), HasTag, CanTrack
) {
lifecycleScope.launch {
openBrowserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), url)
.launchInBrowser(requireActivity(), url)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class NewsSearchController : MvvmController<ControllerNewsSearchBinding>(), HasT
) {
lifecycleScope.launch {
browserDelegate.browserHandler()
.launchNewsInBrowser(requireActivity(), url)
.launchInBrowser(requireActivity(), url)
}
}

Expand Down
Loading

0 comments on commit 6a70e43

Please sign in to comment.