Skip to content

Commit 2476136

Browse files
Merge pull request #2 from PopStackHack/release/4.0.1
Release/4.0.1
2 parents ea1b23f + fa6dddc commit 2476136

94 files changed

Lines changed: 2203 additions & 1131 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

app/build.gradle.kts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ dependencies {
110110
implementation(AndroidXPaging.common)
111111
implementation(AndroidXPaging.runtime)
112112
implementation(AndroidXDataStore.preferences)
113-
implementation("androidx.browser:browser:1.3.0-alpha05")
113+
implementation("androidx.browser:browser:1.3.0-alpha06")
114114

115115
implementation(Conductor.core)
116116
implementation(Conductor.viewpager)
@@ -133,6 +133,8 @@ dependencies {
133133
//Coil
134134
implementation(Coil.coil)
135135

136+
implementation("com.github.chrisbanes:PhotoView:2.3.0")
137+
136138
//Firebase
137139
implementation(Firebase.analytics)
138140
implementation(Firebase.crashlytics)

app/src/main/AndroidManifest.xml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33
xmlns:tools="http://schemas.android.com/tools"
44
package="com.popstack.mvoter2015">
55

6-
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
76
<uses-permission
87
android:name="android.permission.READ_PHONE_STATE"
98
tools:node="remove" />
109

1110
<application
1211
android:name=".MVoterApp"
13-
android:allowBackup="true"
12+
android:allowBackup="false"
1413
android:icon="@mipmap/ic_launcher"
1514
android:label="@string/app_name"
1615
android:roundIcon="@mipmap/ic_launcher_round"
1716
android:supportsRtl="true"
18-
android:theme="@style/AppTheme"
19-
android:usesCleartextTraffic="true">
17+
android:theme="@style/AppTheme">
2018

2119
<activity android:name=".feature.HostActivity">
2220
<intent-filter>
@@ -70,8 +68,6 @@
7068
</intent-filter>
7169

7270

73-
74-
7571
</activity>
7672

7773
<activity
@@ -82,6 +78,8 @@
8278
android:name=".feature.faq.ballot.BallotExampleSelectActivity"
8379
android:theme="@style/AppTheme.Transparent" />
8480

81+
<activity android:name=".feature.image.FullScreenImageViewActivity" />
82+
8583
<meta-data
8684
android:name="firebase_crashlytics_collection_enabled"
8785
android:value="false" />

app/src/main/java/com/popstack/mvoter2015/di/module/AppModule.kt

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ package com.popstack.mvoter2015.di.module
22

33
import android.app.Application
44
import android.content.Context
5-
import coil.ImageLoader
6-
import coil.ImageLoaderBuilder
7-
import com.popstack.mvoter2015.R
85
import com.popstack.mvoter2015.data.android.AndroidDataModule
96
import com.popstack.mvoter2015.data.android.appupdate.AppUpdateModule
107
import com.popstack.mvoter2015.di.conductor.ConductorInjectionModule
@@ -17,7 +14,6 @@ import dagger.Module
1714
import dagger.Provides
1815
import dagger.android.ContributesAndroidInjector
1916
import java.time.Clock
20-
import javax.inject.Singleton
2117

2218
@Module(
2319
includes = [ViewModelFactoryModule::class, ConductorInjectionModule::class, AndroidDataModule::class, AppUpdateModule::class]
@@ -41,14 +37,6 @@ abstract class AppModule {
4137
fun context(application: Application): Context {
4238
return application.applicationContext
4339
}
44-
45-
@Provides
46-
@Singleton
47-
fun imageLoader(context: Context): ImageLoader {
48-
return ImageLoaderBuilder(context)
49-
.placeholder(R.drawable.placeholder_rect)
50-
.build()
51-
}
5240
}
5341

5442
}

app/src/main/java/com/popstack/mvoter2015/feature/candidate/detail/CandidateDetailController.kt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import androidx.core.view.isVisible
1414
import androidx.core.widget.NestedScrollView
1515
import androidx.lifecycle.Observer
1616
import androidx.recyclerview.widget.LinearLayoutManager
17-
import coil.api.load
17+
import coil.load
1818
import coil.size.Scale
1919
import coil.transform.CircleCropTransformation
2020
import com.bluelinelabs.conductor.RouterTransaction
@@ -24,6 +24,7 @@ import com.popstack.mvoter2015.databinding.ControllerCandidateDetailBinding
2424
import com.popstack.mvoter2015.domain.candidate.model.CandidateId
2525
import com.popstack.mvoter2015.feature.analytics.screen.CanTrackScreen
2626
import com.popstack.mvoter2015.feature.candidate.listing.CandidateListRecyclerViewAdapter
27+
import com.popstack.mvoter2015.feature.image.FullScreenImageViewActivity
2728
import com.popstack.mvoter2015.feature.party.PartySharedElementTransitionChangeHandler
2829
import com.popstack.mvoter2015.feature.party.detail.PartyDetailController
2930
import com.popstack.mvoter2015.feature.share.ShareUrlFactory
@@ -190,24 +191,29 @@ class CandidateDetailController(
190191
binding.tvFatherReligion.text = fatherReligion
191192
binding.groupElectedBadge.isVisible = isElected
192193

193-
binding.tvResidentialTitle.isVisible = residentialAddress != null
194-
binding.tvResidential.isVisible = residentialAddress != null
195-
196-
if (residentialAddress != null) {
197-
binding.tvResidential.text = residentialAddress
198-
}
199-
200194
binding.ivCandidatePartySeal.load(partySealImageUrl) {
201195
placeholder(R.drawable.party_seal_placeholder_rect)
202196
error(R.drawable.party_seal_placeholder_rect)
203197
scale(Scale.FIT)
204198
}
199+
partySealImageUrl?.let { imageUrl ->
200+
binding.ivCandidatePartySeal.setOnClickListener {
201+
val imageViewerIntent = FullScreenImageViewActivity.intent(requireContext(), imageUrl)
202+
startActivity(imageViewerIntent)
203+
}
204+
}
205+
205206
binding.ivCandidate.load(photo) {
206207
transformations(CircleCropTransformation())
207208
scale(Scale.FILL)
208209
placeholder(R.drawable.placeholder_oval)
209210
error(R.drawable.placeholder_oval)
210211
}
212+
213+
binding.ivCandidate.setOnClickListener {
214+
val imageViewerIntent = FullScreenImageViewActivity.intent(requireContext(), photo)
215+
startActivity(imageViewerIntent)
216+
}
211217
}
212218
candidateListAdapter.submitList(viewState.value.rivals)
213219
}

app/src/main/java/com/popstack/mvoter2015/feature/candidate/detail/CandidateDetailsViewItem.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ data class CandidateInfoViewItem(
3333
val fatherName: String,
3434
val fatherEthnicity: String,
3535
val fatherReligion: String,
36-
val residentialAddress: String?,
3736
val isElected: Boolean
3837
)
3938

@@ -56,8 +55,7 @@ fun Candidate.toCandidateInfoViewItem() = CandidateInfoViewItem(
5655
.orEmpty()
5756
)
5857
.toString(),
59-
birthday = BurmeseNumberUtils.convertEnglishToBurmeseNumber(birthDate.format(dateFormatter))
60-
.toString(),
58+
birthday = if (birthDate != null) BurmeseNumberUtils.convertEnglishToBurmeseNumber(birthDate!!.format(dateFormatter)).toString() else "-",
6159
education = education,
6260
job = occupation,
6361
ethnicity = ethnicity,
@@ -68,6 +66,5 @@ fun Candidate.toCandidateInfoViewItem() = CandidateInfoViewItem(
6866
fatherName = father?.name.orEmpty(),
6967
fatherEthnicity = father?.ethnicity.orEmpty(),
7068
fatherReligion = father?.religion.orEmpty(),
71-
residentialAddress = residentialAddress,
7269
isElected = isElected
7370
)

app/src/main/java/com/popstack/mvoter2015/feature/candidate/listing/CandidateListRecyclerViewAdapter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import android.view.View
44
import android.view.ViewGroup
55
import androidx.core.view.isVisible
66
import androidx.recyclerview.widget.ListAdapter
7-
import coil.api.load
7+
import coil.load
88
import coil.size.Scale
99
import coil.transform.CircleCropTransformation
1010
import com.popstack.mvoter2015.R

app/src/main/java/com/popstack/mvoter2015/feature/candidate/listing/lowerhouse/LowerHouseCandidateListController.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.view.LayoutInflater
55
import androidx.core.view.isVisible
66
import androidx.lifecycle.Observer
7+
import androidx.recyclerview.widget.GridLayoutManager
78
import androidx.recyclerview.widget.LinearLayoutManager
89
import com.bluelinelabs.conductor.RouterTransaction
910
import com.popstack.mvoter2015.R
@@ -17,6 +18,8 @@ import com.popstack.mvoter2015.feature.candidate.listing.CandidateListResult
1718
import com.popstack.mvoter2015.feature.home.BottomNavigationHostViewModelStore
1819
import com.popstack.mvoter2015.helper.asyncviewstate.AsyncViewState
1920
import com.popstack.mvoter2015.helper.conductor.requireContext
21+
import com.popstack.mvoter2015.helper.extensions.isLandScape
22+
import com.popstack.mvoter2015.helper.extensions.isTablet
2023
import com.popstack.mvoter2015.logging.HasTag
2124

2225
class LowerHouseCandidateListController : MvvmController<ControllerLowerHouseCandidateListBinding>(), HasTag {
@@ -45,7 +48,11 @@ class LowerHouseCandidateListController : MvvmController<ControllerLowerHouseCan
4548
super.onBindView(savedViewState)
4649
binding.rvCandidate.apply {
4750
adapter = candidateListAdapter
48-
layoutManager = LinearLayoutManager(requireContext())
51+
layoutManager = if (requireContext().isTablet() && requireContext().isLandScape()) {
52+
GridLayoutManager(requireContext(), 2)
53+
} else {
54+
LinearLayoutManager(requireContext())
55+
}
4956
}
5057

5158
binding.tvConstituencyName.text = viewModel.data.constituencyName

app/src/main/java/com/popstack/mvoter2015/feature/candidate/listing/regionalhouse/RegionalHouseCandidateListController.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.view.LayoutInflater
55
import androidx.core.view.isVisible
66
import androidx.lifecycle.Observer
7+
import androidx.recyclerview.widget.GridLayoutManager
78
import androidx.recyclerview.widget.LinearLayoutManager
89
import com.bluelinelabs.conductor.RouterTransaction
910
import com.popstack.mvoter2015.R
@@ -18,6 +19,8 @@ import com.popstack.mvoter2015.feature.candidate.listing.CandidateListResult
1819
import com.popstack.mvoter2015.feature.home.BottomNavigationHostViewModelStore
1920
import com.popstack.mvoter2015.helper.asyncviewstate.AsyncViewState
2021
import com.popstack.mvoter2015.helper.conductor.requireContext
22+
import com.popstack.mvoter2015.helper.extensions.isLandScape
23+
import com.popstack.mvoter2015.helper.extensions.isTablet
2124
import com.popstack.mvoter2015.helper.recyclerview.StickyHeaderDecoration
2225
import com.popstack.mvoter2015.logging.HasTag
2326

@@ -47,7 +50,21 @@ class RegionalHouseCandidateListController() : MvvmController<ControllerRegional
4750
super.onBindView(savedViewState)
4851
binding.rvCandidate.apply {
4952
adapter = candidateListAdapter
50-
layoutManager = LinearLayoutManager(requireContext())
53+
layoutManager = if (requireContext().isTablet() && requireContext().isLandScape()) {
54+
GridLayoutManager(requireContext(), 2).also {
55+
it.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
56+
override fun getSpanSize(position: Int): Int {
57+
return when (candidateListAdapter.getItemViewType(position)) {
58+
CandidateListRecyclerViewAdapter.VIEW_TYPE_CANDIDATE_SECTION_TITLE -> 2
59+
CandidateListRecyclerViewAdapter.VIEW_TYPE_CANDIDATE -> 1
60+
else -> 1
61+
}
62+
}
63+
}
64+
}
65+
} else {
66+
LinearLayoutManager(requireContext())
67+
}
5168
addItemDecoration(StickyHeaderDecoration(candidateListAdapter))
5269
}
5370

app/src/main/java/com/popstack/mvoter2015/feature/candidate/listing/upperhouse/UpperHouseCandidateListController.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.os.Bundle
44
import android.view.LayoutInflater
55
import androidx.core.view.isVisible
66
import androidx.lifecycle.Observer
7+
import androidx.recyclerview.widget.GridLayoutManager
78
import androidx.recyclerview.widget.LinearLayoutManager
89
import com.bluelinelabs.conductor.RouterTransaction
910
import com.popstack.mvoter2015.R
@@ -17,6 +18,8 @@ import com.popstack.mvoter2015.feature.candidate.listing.CandidateListResult
1718
import com.popstack.mvoter2015.feature.home.BottomNavigationHostViewModelStore
1819
import com.popstack.mvoter2015.helper.asyncviewstate.AsyncViewState
1920
import com.popstack.mvoter2015.helper.conductor.requireContext
21+
import com.popstack.mvoter2015.helper.extensions.isLandScape
22+
import com.popstack.mvoter2015.helper.extensions.isTablet
2023
import com.popstack.mvoter2015.logging.HasTag
2124

2225
class UpperHouseCandidateListController : MvvmController<ControllerUpperHouseCandidateListBinding>(), HasTag {
@@ -46,7 +49,11 @@ class UpperHouseCandidateListController : MvvmController<ControllerUpperHouseCan
4649

4750
binding.rvCandidate.apply {
4851
adapter = candidateListAdapter
49-
layoutManager = LinearLayoutManager(requireContext())
52+
layoutManager = if (requireContext().isTablet() && requireContext().isLandScape()) {
53+
GridLayoutManager(requireContext(), 2)
54+
} else {
55+
LinearLayoutManager(requireContext())
56+
}
5057
}
5158

5259
viewModel.viewItemLiveData.observe(this, Observer(::observeViewItem))

app/src/main/java/com/popstack/mvoter2015/feature/candidate/search/CandidateSearchController.kt

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import androidx.core.view.isVisible
66
import androidx.lifecycle.lifecycleScope
77
import androidx.paging.ExperimentalPagingApi
88
import androidx.paging.LoadState
9+
import androidx.recyclerview.widget.GridLayoutManager
910
import androidx.recyclerview.widget.LinearLayoutManager
10-
import androidx.recyclerview.widget.RecyclerView
1111
import com.bluelinelabs.conductor.RouterTransaction
1212
import com.popstack.mvoter2015.R
1313
import com.popstack.mvoter2015.core.mvp.MvvmController
@@ -17,9 +17,10 @@ import com.popstack.mvoter2015.exception.GlobalExceptionHandler
1717
import com.popstack.mvoter2015.feature.analytics.screen.CanTrackScreen
1818
import com.popstack.mvoter2015.feature.candidate.detail.CandidateDetailController
1919
import com.popstack.mvoter2015.helper.RecyclerViewMarginDecoration
20-
import com.popstack.mvoter2015.helper.ViewVisibilityDebounceHandler
2120
import com.popstack.mvoter2015.helper.conductor.requireActivityAsAppCompatActivity
2221
import com.popstack.mvoter2015.helper.conductor.requireContext
22+
import com.popstack.mvoter2015.helper.extensions.isLandScape
23+
import com.popstack.mvoter2015.helper.extensions.isTablet
2324
import com.popstack.mvoter2015.helper.extensions.showKeyboard
2425
import com.popstack.mvoter2015.helper.search.DebounceSearchQueryListener
2526
import com.popstack.mvoter2015.logging.HasTag
@@ -41,8 +42,6 @@ class CandidateSearchController : MvvmController<ControllerCandidateSearchBindin
4142

4243
private val searchPagingAdapter = CandidateSearchPagingAdapter(this::onItemClick)
4344

44-
private val placeholderAdapter = CandidateSearchPlaceholderRecyclerViewAdapter()
45-
4645
private var searchJob: Job? = null
4746

4847
private val globalExceptionHandler by lazy {
@@ -64,35 +63,34 @@ class CandidateSearchController : MvvmController<ControllerCandidateSearchBindin
6463
)
6564
)
6665

67-
binding.rvPlaceholder.apply {
68-
adapter = placeholderAdapter
69-
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
70-
val dimen =
71-
context.resources.getDimensionPixelSize(R.dimen.recycler_view_item_margin)
72-
addItemDecoration(RecyclerViewMarginDecoration(dimen, 1))
73-
}
74-
7566
binding.rvCandidate.apply {
7667
adapter = searchPagingAdapter.withLoadStateHeaderAndFooter(
7768
header = CommonLoadStateAdapter(searchPagingAdapter::retry),
7869
footer = CommonLoadStateAdapter(searchPagingAdapter::retry)
7970
)
80-
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, false)
71+
layoutManager = if (requireContext().isTablet() && requireContext().isLandScape()) {
72+
GridLayoutManager(requireContext(), 2)
73+
} else {
74+
LinearLayoutManager(requireContext())
75+
}
8176
val dimen =
8277
context.resources.getDimensionPixelSize(R.dimen.recycler_view_item_margin)
83-
addItemDecoration(RecyclerViewMarginDecoration(dimen, 0))
78+
if (requireContext().isTablet() && requireContext().isLandScape()) {
79+
addItemDecoration(RecyclerViewMarginDecoration(dimen, 2))
80+
} else {
81+
addItemDecoration(RecyclerViewMarginDecoration(dimen, 0))
82+
}
8483
}
8584

8685
binding.btnRetry.setOnClickListener {
8786
searchPagingAdapter.retry()
8887
}
8988

90-
val placeHolderVisibilityHandler = ViewVisibilityDebounceHandler(binding.rvPlaceholder)
91-
9289
searchPagingAdapter.addLoadStateListener { loadStates ->
9390
val refreshLoadState = loadStates.refresh
9491
binding.rvCandidate.isVisible = refreshLoadState is LoadState.NotLoading
95-
placeHolderVisibilityHandler.setVisible(refreshLoadState is LoadState.Loading)
92+
if (refreshLoadState is LoadState.Loading) binding.progressIndicator.show()
93+
else binding.progressIndicator.hide()
9694
binding.tvErrorMessage.isVisible = refreshLoadState is LoadState.Error
9795
binding.btnRetry.isVisible = refreshLoadState is LoadState.Error
9896
if (viewModel.currentQueryValue != null) {

0 commit comments

Comments
 (0)