From 36fdf2b48c20055447b74befe81822496632934b Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Mon, 16 Sep 2019 21:01:02 +0300 Subject: [PATCH 01/10] Initial version of Redux pattern for Contests. --- app/build.gradle | 3 +- .../bogdan/codeforceswatcher/CwApplication.kt | 8 +++++ .../activity/MainActivity.kt | 6 ++-- .../contests/ContestDao.kt} | 2 +- .../contests}/ContestResponse.kt | 2 +- .../contests}/ContestsFragment.kt | 35 ++++++++++++++----- .../feature/contests/redux/ContestsActions.kt | 11 ++++++ .../feature/contests/redux/ContestsReducer.kt | 18 ++++++++++ .../feature/contests/redux/ContestsState.kt | 8 +++++ .../network/CodeforcesApi.kt | 2 +- .../codeforceswatcher/redux/AppReducer.kt | 11 ++++++ .../codeforceswatcher/redux/AppState.kt | 8 +++++ .../bogdan/codeforceswatcher/room/Database.kt | 1 + 13 files changed, 100 insertions(+), 15 deletions(-) rename app/src/main/java/com/bogdan/codeforceswatcher/{room/ContestDb.kt => feature/contests/ContestDao.kt} (90%) rename app/src/main/java/com/bogdan/codeforceswatcher/{network/model => feature/contests}/ContestResponse.kt (71%) rename app/src/main/java/com/bogdan/codeforceswatcher/{fragment => feature/contests}/ContestsFragment.kt (74%) create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/redux/AppReducer.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/redux/AppState.kt diff --git a/app/build.gradle b/app/build.gradle index 6b854adda..9dbea0cf4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -69,6 +69,7 @@ dependencies { implementation 'com.github.PhilJay:MPAndroidChart:v3.0.3' implementation 'androidx.cardview:cardview:1.0.0' implementation 'com.google.firebase:firebase-analytics:17.1.0' + implementation 'org.rekotlin:rekotlin:1.0.4' } -apply plugin: 'com.google.gms.google-services' \ No newline at end of file +apply plugin: 'com.google.gms.google-services' diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt index 66a5753ba..d841dfe8c 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt @@ -1,7 +1,15 @@ package com.bogdan.codeforceswatcher import android.app.Application +import com.bogdan.codeforceswatcher.redux.AppState +import com.bogdan.codeforceswatcher.redux.appReducer import com.google.firebase.analytics.FirebaseAnalytics +import org.rekotlin.Store + +val store = Store( + reducer = ::appReducer, + state = AppState() +) class CwApp : Application() { diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt b/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt index 9115c029d..83ca7a59c 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt @@ -12,7 +12,7 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentPagerAdapter import androidx.viewpager.widget.ViewPager import com.bogdan.codeforceswatcher.R -import com.bogdan.codeforceswatcher.fragment.ContestsFragment +import com.bogdan.codeforceswatcher.feature.contests.ContestsFragment import com.bogdan.codeforceswatcher.fragment.UsersFragment import com.bogdan.codeforceswatcher.receiver.StartAlarm import com.bogdan.codeforceswatcher.ui.AppRateDialog @@ -122,7 +122,9 @@ class MainActivity : AppCompatActivity() { } class ViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) { - private val mFragmentList = listOf(UsersFragment(), ContestsFragment()) + private val mFragmentList = listOf(UsersFragment(), + ContestsFragment() + ) private val mFragmentTitleList = listOf("Users", "Contests") override fun getItem(position: Int): Fragment { diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/room/ContestDb.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt similarity index 90% rename from app/src/main/java/com/bogdan/codeforceswatcher/room/ContestDb.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt index bfe25303c..6b3a5f38f 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/room/ContestDb.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt @@ -1,4 +1,4 @@ -package com.bogdan.codeforceswatcher.room +package com.bogdan.codeforceswatcher.feature.contests import androidx.lifecycle.LiveData import androidx.room.Dao diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/network/model/ContestResponse.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt similarity index 71% rename from app/src/main/java/com/bogdan/codeforceswatcher/network/model/ContestResponse.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt index cdd26c420..10c2be4ec 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/network/model/ContestResponse.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt @@ -1,4 +1,4 @@ -package com.bogdan.codeforceswatcher.network.model +package com.bogdan.codeforceswatcher.feature.contests import com.bogdan.codeforceswatcher.model.Contest diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/fragment/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt similarity index 74% rename from app/src/main/java/com/bogdan/codeforceswatcher/fragment/ContestsFragment.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index 589cf2e45..8c30b0093 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/fragment/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -1,4 +1,4 @@ -package com.bogdan.codeforceswatcher.fragment +package com.bogdan.codeforceswatcher.feature.contests import android.os.Bundle import android.view.LayoutInflater @@ -6,27 +6,43 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.bogdan.codeforceswatcher.CwApp import com.bogdan.codeforceswatcher.R import com.bogdan.codeforceswatcher.adapter.ContestAdapter +import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsActions +import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.network.RestClient -import com.bogdan.codeforceswatcher.network.model.ContestResponse -import com.bogdan.codeforceswatcher.room.DatabaseClient +import com.bogdan.codeforceswatcher.store import com.bogdan.codeforceswatcher.util.Analytics import kotlinx.android.synthetic.main.fragment_contests.recyclerView import kotlinx.android.synthetic.main.fragment_contests.swipeToRefresh +import org.rekotlin.StoreSubscriber import retrofit2.Call import retrofit2.Callback import retrofit2.Response -class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { +class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, + StoreSubscriber { private lateinit var contestAdapter: ContestAdapter + override fun onStart() { + super.onStart() + store.subscribe(this) { state -> state.select { it.contests } } + } + + override fun onStop() { + super.onStop() + store.unsubscribe(this) + } + + override fun newState(state: ContestsState) { + contestAdapter.setItems(state.contests.sortedBy(Contest::time)) + } + override fun onRefresh() { updateContestList() Analytics.logContestsListRefresh() @@ -51,10 +67,10 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { recyclerView.adapter = contestAdapter recyclerView.layoutManager = LinearLayoutManager(requireContext()) - val liveData = DatabaseClient.contestDao.getUpcomingContests() + /*val liveData = DatabaseClient.contestDao.getUpcomingContests() liveData.observe(this, Observer> { contestList -> contestList?.let { contestsList -> contestAdapter.setItems(contestsList.sortedBy(Contest::time)) } - }) + })*/ } private fun updateContestList(shouldDisplayError: Boolean = true) { @@ -67,8 +83,9 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener { if (response.body() != null) { val contestList = response.body()?.result if (contestList != null) { - DatabaseClient.contestDao.deleteAll(contestList) - DatabaseClient.contestDao.insert(contestList) + store.dispatch(ContestsActions.ContestsLoaded(contestList)) + // DatabaseClient.contestDao.deleteAll(contestList) + // DatabaseClient.contestDao.insert(contestList) } } if (activity != null) swipeToRefresh.isRefreshing = false diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt new file mode 100644 index 000000000..ca2d62c05 --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt @@ -0,0 +1,11 @@ +package com.bogdan.codeforceswatcher.feature.contests.redux + +import com.bogdan.codeforceswatcher.model.Contest +import org.rekotlin.Action + +class ContestsActions { + + data class ContestsLoaded( + val contests: List + ) : Action +} diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt new file mode 100644 index 000000000..a15a966a1 --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt @@ -0,0 +1,18 @@ +package com.bogdan.codeforceswatcher.feature.contests.redux + +import com.bogdan.codeforceswatcher.redux.AppState +import org.rekotlin.Action + +fun contestsReducer(action: Action, state: AppState): ContestsState { + var newState = state.contests + + when (action) { + is ContestsActions.ContestsLoaded -> { + newState = newState.copy( + contests = action.contests + ) + } + } + + return newState +} diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt new file mode 100644 index 000000000..709adb12c --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt @@ -0,0 +1,8 @@ +package com.bogdan.codeforceswatcher.feature.contests.redux + +import com.bogdan.codeforceswatcher.model.Contest +import org.rekotlin.StateType + +data class ContestsState( + val contests: List = listOf() +) : StateType diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt b/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt index 5d1c4a725..f82022c2d 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt @@ -1,6 +1,6 @@ package com.bogdan.codeforceswatcher.network -import com.bogdan.codeforceswatcher.network.model.ContestResponse +import com.bogdan.codeforceswatcher.feature.contests.ContestResponse import com.bogdan.codeforceswatcher.network.model.RatingChangeResponse import com.bogdan.codeforceswatcher.network.model.UserResponse import retrofit2.Call diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppReducer.kt new file mode 100644 index 000000000..9209ec872 --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppReducer.kt @@ -0,0 +1,11 @@ +package com.bogdan.codeforceswatcher.redux + +import com.bogdan.codeforceswatcher.feature.contests.redux.contestsReducer +import org.rekotlin.Action + +fun appReducer(action: Action, state: AppState?): AppState { + requireNotNull(state) + return AppState( + contests = contestsReducer(action, state) + ) +} diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppState.kt b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppState.kt new file mode 100644 index 000000000..00002cf4f --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppState.kt @@ -0,0 +1,8 @@ +package com.bogdan.codeforceswatcher.redux + +import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState +import org.rekotlin.StateType + +data class AppState( + val contests: ContestsState = ContestsState() +) : StateType diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt b/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt index fde3ea2e7..e61efd50d 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt @@ -3,6 +3,7 @@ package com.bogdan.codeforceswatcher.room import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters +import com.bogdan.codeforceswatcher.feature.contests.ContestDao import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.model.User From 8fe4ebd6296d098258df11be371b3e07b2eaf061 Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Mon, 16 Sep 2019 21:03:26 +0300 Subject: [PATCH 02/10] Add Request action. --- .../com/bogdan/codeforceswatcher/CwApplication.kt | 4 +++- .../bogdan/codeforceswatcher/redux/AppMiddleware.kt | 13 +++++++++++++ .../com/bogdan/codeforceswatcher/redux/Request.kt | 8 ++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/redux/AppMiddleware.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/redux/Request.kt diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt index d841dfe8c..6f32b3938 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt @@ -2,13 +2,15 @@ package com.bogdan.codeforceswatcher import android.app.Application import com.bogdan.codeforceswatcher.redux.AppState +import com.bogdan.codeforceswatcher.redux.appMiddleware import com.bogdan.codeforceswatcher.redux.appReducer import com.google.firebase.analytics.FirebaseAnalytics import org.rekotlin.Store val store = Store( reducer = ::appReducer, - state = AppState() + state = AppState(), + middleware = listOf(appMiddleware) ) class CwApp : Application() { diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppMiddleware.kt b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppMiddleware.kt new file mode 100644 index 000000000..f55ce18fa --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/redux/AppMiddleware.kt @@ -0,0 +1,13 @@ +package com.bogdan.codeforceswatcher.redux + +import org.rekotlin.Middleware +import org.rekotlin.StateType + +val appMiddleware: Middleware = { _, _ -> + { next -> + { action -> + (action as? Request)?.execute() + next(action) + } + } +} diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/redux/Request.kt b/app/src/main/java/com/bogdan/codeforceswatcher/redux/Request.kt new file mode 100644 index 000000000..6e9a2862d --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/redux/Request.kt @@ -0,0 +1,8 @@ +package com.bogdan.codeforceswatcher.redux + +import org.rekotlin.Action + +abstract class Request : Action { + + abstract fun execute() +} From e4842dbca5f487e09a28ea213c689e0f85c999a5 Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Mon, 16 Sep 2019 21:13:36 +0300 Subject: [PATCH 03/10] Implement FetchContests request. --- .../feature/contests/ContestsFragment.kt | 42 ++---------------- .../feature/contests/redux/ContestsActions.kt | 11 ----- .../feature/contests/redux/ContestsReducer.kt | 5 ++- .../contests/redux/ContestsRequests.kt | 44 +++++++++++++++++++ 4 files changed, 51 insertions(+), 51 deletions(-) delete mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index 8c30b0093..b4d1d46a4 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -4,25 +4,19 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.fragment.app.Fragment import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import com.bogdan.codeforceswatcher.CwApp import com.bogdan.codeforceswatcher.R import com.bogdan.codeforceswatcher.adapter.ContestAdapter -import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsActions +import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsRequests import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState import com.bogdan.codeforceswatcher.model.Contest -import com.bogdan.codeforceswatcher.network.RestClient import com.bogdan.codeforceswatcher.store import com.bogdan.codeforceswatcher.util.Analytics import kotlinx.android.synthetic.main.fragment_contests.recyclerView import kotlinx.android.synthetic.main.fragment_contests.swipeToRefresh import org.rekotlin.StoreSubscriber -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, StoreSubscriber { @@ -44,7 +38,7 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, } override fun onRefresh() { - updateContestList() + store.dispatch(ContestsRequests.FetchContests()) Analytics.logContestsListRefresh() } @@ -61,7 +55,7 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, private fun initViews() { swipeToRefresh.setOnRefreshListener(this) - updateContestList(false) + store.dispatch(ContestsRequests.FetchContests()) contestAdapter = ContestAdapter(listOf(), requireContext()) recyclerView.adapter = contestAdapter @@ -72,34 +66,4 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, contestList?.let { contestsList -> contestAdapter.setItems(contestsList.sortedBy(Contest::time)) } })*/ } - - private fun updateContestList(shouldDisplayError: Boolean = true) { - RestClient.getContests().enqueue(object : Callback { - - override fun onResponse( - call: Call, - response: Response - ) { - if (response.body() != null) { - val contestList = response.body()?.result - if (contestList != null) { - store.dispatch(ContestsActions.ContestsLoaded(contestList)) - // DatabaseClient.contestDao.deleteAll(contestList) - // DatabaseClient.contestDao.insert(contestList) - } - } - if (activity != null) swipeToRefresh.isRefreshing = false - } - - override fun onFailure(call: Call, t: Throwable) { - if (activity != null) swipeToRefresh.isRefreshing = false - if (shouldDisplayError) - Toast.makeText( - CwApp.app, - getString(R.string.no_internet_connection), - Toast.LENGTH_SHORT - ).show() - } - }) - } } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt deleted file mode 100644 index ca2d62c05..000000000 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsActions.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.bogdan.codeforceswatcher.feature.contests.redux - -import com.bogdan.codeforceswatcher.model.Contest -import org.rekotlin.Action - -class ContestsActions { - - data class ContestsLoaded( - val contests: List - ) : Action -} diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt index a15a966a1..279186b07 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt @@ -7,11 +7,14 @@ fun contestsReducer(action: Action, state: AppState): ContestsState { var newState = state.contests when (action) { - is ContestsActions.ContestsLoaded -> { + is ContestsRequests.FetchContests.Success -> { newState = newState.copy( contests = action.contests ) } + is ContestsRequests.FetchContests.Failure -> { + // TODO: Handle failure + } } return newState diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt new file mode 100644 index 000000000..65e21b3f8 --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt @@ -0,0 +1,44 @@ +package com.bogdan.codeforceswatcher.feature.contests.redux + +import com.bogdan.codeforceswatcher.feature.contests.ContestResponse +import com.bogdan.codeforceswatcher.model.Contest +import com.bogdan.codeforceswatcher.network.RestClient +import com.bogdan.codeforceswatcher.redux.Request +import com.bogdan.codeforceswatcher.store +import org.rekotlin.Action +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class ContestsRequests { + + class FetchContests : Request() { + + override fun execute() { + RestClient.getContests().enqueue(object : Callback { + + override fun onResponse( + call: Call, + response: Response + ) { + if (response.body() != null) { + val contestList = response.body()?.result + if (contestList != null) { + store.dispatch(Success(contestList)) + // DatabaseClient.contestDao.deleteAll(contestList) + // DatabaseClient.contestDao.insert(contestList) + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + + } + }) + } + + data class Success(val contests: List) : Action + + data class Failure(val t: Throwable) : Action + } +} From b407ecf5f12b805b6cf81e6da31fbdc68aba47ed Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 12:59:10 +0300 Subject: [PATCH 04/10] Handle loading status for Contests. --- .../feature/contests/ContestsFragment.kt | 5 ++++- .../feature/contests/redux/ContestsReducer.kt | 10 +++++++++- .../feature/contests/redux/ContestsState.kt | 6 +++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index b4d1d46a4..0968e7cb6 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -34,6 +34,7 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, } override fun newState(state: ContestsState) { + swipeToRefresh.isRefreshing = (state.status == ContestsState.Status.PENDING) contestAdapter.setItems(state.contests.sortedBy(Contest::time)) } @@ -50,12 +51,14 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + initViews() + + store.dispatch(ContestsRequests.FetchContests()) } private fun initViews() { swipeToRefresh.setOnRefreshListener(this) - store.dispatch(ContestsRequests.FetchContests()) contestAdapter = ContestAdapter(listOf(), requireContext()) recyclerView.adapter = contestAdapter diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt index 279186b07..dd02422ff 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt @@ -7,13 +7,21 @@ fun contestsReducer(action: Action, state: AppState): ContestsState { var newState = state.contests when (action) { + is ContestsRequests.FetchContests -> { + newState = newState.copy( + status = ContestsState.Status.PENDING + ) + } is ContestsRequests.FetchContests.Success -> { newState = newState.copy( + status = ContestsState.Status.IDLE, contests = action.contests ) } is ContestsRequests.FetchContests.Failure -> { - // TODO: Handle failure + newState = newState.copy( + status = ContestsState.Status.IDLE + ) } } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt index 709adb12c..eedb46b44 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsState.kt @@ -4,5 +4,9 @@ import com.bogdan.codeforceswatcher.model.Contest import org.rekotlin.StateType data class ContestsState( + val status: Status = Status.IDLE, val contests: List = listOf() -) : StateType +) : StateType { + + enum class Status { IDLE, PENDING } +} From 8c9ddb6c54516fd53ef586f4435ce515c7207384 Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 13:06:23 +0300 Subject: [PATCH 05/10] Handle Failure for FetchContests request. --- .../feature/contests/ContestsFragment.kt | 5 ----- .../feature/contests/redux/ContestsRequests.kt | 15 +++++---------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index 0968e7cb6..f3d4f4f6c 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -63,10 +63,5 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, contestAdapter = ContestAdapter(listOf(), requireContext()) recyclerView.adapter = contestAdapter recyclerView.layoutManager = LinearLayoutManager(requireContext()) - - /*val liveData = DatabaseClient.contestDao.getUpcomingContests() - liveData.observe(this, Observer> { contestList -> - contestList?.let { contestsList -> contestAdapter.setItems(contestsList.sortedBy(Contest::time)) } - })*/ } } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt index 65e21b3f8..b96fdd93e 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt @@ -21,24 +21,19 @@ class ContestsRequests { call: Call, response: Response ) { - if (response.body() != null) { - val contestList = response.body()?.result - if (contestList != null) { - store.dispatch(Success(contestList)) - // DatabaseClient.contestDao.deleteAll(contestList) - // DatabaseClient.contestDao.insert(contestList) - } - } + response.body()?.result?.let { contests -> + store.dispatch(Success(contests)) + } ?: store.dispatch(Failure()) } override fun onFailure(call: Call, t: Throwable) { - + store.dispatch(Failure(t)) } }) } data class Success(val contests: List) : Action - data class Failure(val t: Throwable) : Action + data class Failure(val t: Throwable? = null) : Action } } From db1ab070b37d7fa050c146aabd6c78e98acd679d Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 14:50:40 +0300 Subject: [PATCH 06/10] Filter and sort contests. --- .../codeforceswatcher/feature/contests/ContestsFragment.kt | 2 +- .../feature/contests/redux/ContestsReducer.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index f3d4f4f6c..bc1622bd6 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -35,7 +35,7 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, override fun newState(state: ContestsState) { swipeToRefresh.isRefreshing = (state.status == ContestsState.Status.PENDING) - contestAdapter.setItems(state.contests.sortedBy(Contest::time)) + contestAdapter.setItems(state.contests) } override fun onRefresh() { diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt index dd02422ff..d60145f14 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt @@ -1,5 +1,6 @@ package com.bogdan.codeforceswatcher.feature.contests.redux +import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.redux.AppState import org.rekotlin.Action @@ -15,7 +16,7 @@ fun contestsReducer(action: Action, state: AppState): ContestsState { is ContestsRequests.FetchContests.Success -> { newState = newState.copy( status = ContestsState.Status.IDLE, - contests = action.contests + contests = action.contests.filter { it.phase == "BEFORE" }.sortedBy(Contest::time) ) } is ContestsRequests.FetchContests.Failure -> { From a3fbce433ae1a1aeee8399e918b9bcca7ea91faf Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 15:02:03 +0300 Subject: [PATCH 07/10] Ongoing refactoring. --- .../feature/contests/ContestsFragment.kt | 3 +-- .../feature/contests/redux/ContestsReducer.kt | 1 + .../{ => redux/request}/ContestResponse.kt | 2 +- .../redux/{ => request}/ContestsRequests.kt | 15 +++++++++++---- .../feature/contests/{ => room}/ContestDao.kt | 7 +++---- .../codeforceswatcher/network/CodeforcesApi.kt | 2 +- .../com/bogdan/codeforceswatcher/room/Database.kt | 2 +- 7 files changed, 19 insertions(+), 13 deletions(-) rename app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/{ => redux/request}/ContestResponse.kt (66%) rename app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/{ => request}/ContestsRequests.kt (72%) rename app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/{ => room}/ContestDao.kt (65%) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index bc1622bd6..2495770cd 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -9,9 +9,8 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.bogdan.codeforceswatcher.R import com.bogdan.codeforceswatcher.adapter.ContestAdapter -import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsRequests +import com.bogdan.codeforceswatcher.feature.contests.redux.request.ContestsRequests import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState -import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.store import com.bogdan.codeforceswatcher.util.Analytics import kotlinx.android.synthetic.main.fragment_contests.recyclerView diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt index d60145f14..8c45ef5b3 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsReducer.kt @@ -1,5 +1,6 @@ package com.bogdan.codeforceswatcher.feature.contests.redux +import com.bogdan.codeforceswatcher.feature.contests.redux.request.ContestsRequests import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.redux.AppState import org.rekotlin.Action diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestResponse.kt similarity index 66% rename from app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestResponse.kt index 10c2be4ec..2c9a55a9a 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestResponse.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestResponse.kt @@ -1,4 +1,4 @@ -package com.bogdan.codeforceswatcher.feature.contests +package com.bogdan.codeforceswatcher.feature.contests.redux.request import com.bogdan.codeforceswatcher.model.Contest diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt similarity index 72% rename from app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt index b96fdd93e..292c54112 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/ContestsRequests.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt @@ -1,6 +1,5 @@ -package com.bogdan.codeforceswatcher.feature.contests.redux +package com.bogdan.codeforceswatcher.feature.contests.redux.request -import com.bogdan.codeforceswatcher.feature.contests.ContestResponse import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.network.RestClient import com.bogdan.codeforceswatcher.redux.Request @@ -22,12 +21,20 @@ class ContestsRequests { response: Response ) { response.body()?.result?.let { contests -> - store.dispatch(Success(contests)) + store.dispatch( + Success( + contests + ) + ) } ?: store.dispatch(Failure()) } override fun onFailure(call: Call, t: Throwable) { - store.dispatch(Failure(t)) + store.dispatch( + Failure( + t + ) + ) } }) } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt similarity index 65% rename from app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt rename to app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt index 6b3a5f38f..ca2b70a95 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestDao.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt @@ -1,6 +1,5 @@ -package com.bogdan.codeforceswatcher.feature.contests +package com.bogdan.codeforceswatcher.feature.contests.room -import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert @@ -11,8 +10,8 @@ import com.bogdan.codeforceswatcher.model.Contest @Dao interface ContestDao { - @Query("SELECT * FROM contest WHERE phase = 'BEFORE'") - fun getUpcomingContests(): LiveData> + @Query("SELECT * FROM contest") + fun getUpcomingContests(): List @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(contests: List) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt b/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt index f82022c2d..aa7531313 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/network/CodeforcesApi.kt @@ -1,6 +1,6 @@ package com.bogdan.codeforceswatcher.network -import com.bogdan.codeforceswatcher.feature.contests.ContestResponse +import com.bogdan.codeforceswatcher.feature.contests.redux.request.ContestResponse import com.bogdan.codeforceswatcher.network.model.RatingChangeResponse import com.bogdan.codeforceswatcher.network.model.UserResponse import retrofit2.Call diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt b/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt index e61efd50d..c0cd7329e 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/room/Database.kt @@ -3,7 +3,7 @@ package com.bogdan.codeforceswatcher.room import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters -import com.bogdan.codeforceswatcher.feature.contests.ContestDao +import com.bogdan.codeforceswatcher.feature.contests.room.ContestDao import com.bogdan.codeforceswatcher.model.Contest import com.bogdan.codeforceswatcher.model.User From c6233600555d6516d4ff3f17e37404309372abd9 Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 15:15:43 +0300 Subject: [PATCH 08/10] Add RoomController. --- .../bogdan/codeforceswatcher/CwApplication.kt | 4 ++- .../feature/contests/room/ContestDao.kt | 5 ++-- .../codeforceswatcher/room/RoomController.kt | 26 +++++++++++++++++++ 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/bogdan/codeforceswatcher/room/RoomController.kt diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt index 6f32b3938..39a8999d2 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/CwApplication.kt @@ -4,12 +4,13 @@ import android.app.Application import com.bogdan.codeforceswatcher.redux.AppState import com.bogdan.codeforceswatcher.redux.appMiddleware import com.bogdan.codeforceswatcher.redux.appReducer +import com.bogdan.codeforceswatcher.room.RoomController import com.google.firebase.analytics.FirebaseAnalytics import org.rekotlin.Store val store = Store( reducer = ::appReducer, - state = AppState(), + state = RoomController.fetchAppState(), middleware = listOf(appMiddleware) ) @@ -20,6 +21,7 @@ class CwApp : Application() { app = this + RoomController.onAppCreated() FirebaseAnalytics.getInstance(this) } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt index ca2b70a95..b9552a1bb 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/room/ContestDao.kt @@ -1,7 +1,6 @@ package com.bogdan.codeforceswatcher.feature.contests.room import androidx.room.Dao -import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query @@ -16,6 +15,6 @@ interface ContestDao { @Insert(onConflict = OnConflictStrategy.REPLACE) fun insert(contests: List) - @Delete - fun deleteAll(contests: List) + @Query("DELETE FROM contest") + fun deleteAll() } diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/room/RoomController.kt b/app/src/main/java/com/bogdan/codeforceswatcher/room/RoomController.kt new file mode 100644 index 000000000..f7ef07bd2 --- /dev/null +++ b/app/src/main/java/com/bogdan/codeforceswatcher/room/RoomController.kt @@ -0,0 +1,26 @@ +package com.bogdan.codeforceswatcher.room + +import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState +import com.bogdan.codeforceswatcher.redux.AppState +import com.bogdan.codeforceswatcher.store +import org.rekotlin.StoreSubscriber + +object RoomController : StoreSubscriber { + + fun onAppCreated() { + store.subscribe(this) { + it.skipRepeats { oldState, newState -> + oldState.contests == newState.contests + } + } + } + + fun fetchAppState() = AppState( + contests = ContestsState(contests = DatabaseClient.contestDao.getUpcomingContests()) + ) + + override fun newState(state: AppState) { + DatabaseClient.contestDao.deleteAll() + DatabaseClient.contestDao.insert(state.contests.contests) + } +} From e71cfe5f369492e2644ed0bff1eb43895f49ca47 Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 15:19:21 +0300 Subject: [PATCH 09/10] Self-review. --- .../codeforceswatcher/activity/MainActivity.kt | 6 ++---- .../contests/redux/request/ContestsRequests.kt | 12 ++---------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt b/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt index 83ca7a59c..765ec1600 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/activity/MainActivity.kt @@ -14,10 +14,10 @@ import androidx.viewpager.widget.ViewPager import com.bogdan.codeforceswatcher.R import com.bogdan.codeforceswatcher.feature.contests.ContestsFragment import com.bogdan.codeforceswatcher.fragment.UsersFragment +import com.bogdan.codeforceswatcher.network.UserLoader import com.bogdan.codeforceswatcher.receiver.StartAlarm import com.bogdan.codeforceswatcher.ui.AppRateDialog import com.bogdan.codeforceswatcher.util.Prefs -import com.bogdan.codeforceswatcher.network.UserLoader import kotlinx.android.synthetic.main.activity_main.bottomNavigation import kotlinx.android.synthetic.main.activity_main.fab import kotlinx.android.synthetic.main.activity_main.llToolbar @@ -122,9 +122,7 @@ class MainActivity : AppCompatActivity() { } class ViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) { - private val mFragmentList = listOf(UsersFragment(), - ContestsFragment() - ) + private val mFragmentList = listOf(UsersFragment(), ContestsFragment()) private val mFragmentTitleList = listOf("Users", "Contests") override fun getItem(position: Int): Fragment { diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt index 292c54112..6b48bed6d 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/redux/request/ContestsRequests.kt @@ -21,20 +21,12 @@ class ContestsRequests { response: Response ) { response.body()?.result?.let { contests -> - store.dispatch( - Success( - contests - ) - ) + store.dispatch(Success(contests)) } ?: store.dispatch(Failure()) } override fun onFailure(call: Call, t: Throwable) { - store.dispatch( - Failure( - t - ) - ) + store.dispatch(Failure(t)) } }) } From 17d3b21dbabdec75301173f4a3af2a8bb4562cfd Mon Sep 17 00:00:00 2001 From: Yevhenii Kanivets Date: Tue, 17 Sep 2019 15:30:42 +0300 Subject: [PATCH 10/10] Integrate Alla's feedback. --- .../codeforceswatcher/feature/contests/ContestsFragment.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt index 2495770cd..6cf136c74 100644 --- a/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt +++ b/app/src/main/java/com/bogdan/codeforceswatcher/feature/contests/ContestsFragment.kt @@ -9,8 +9,8 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.bogdan.codeforceswatcher.R import com.bogdan.codeforceswatcher.adapter.ContestAdapter -import com.bogdan.codeforceswatcher.feature.contests.redux.request.ContestsRequests import com.bogdan.codeforceswatcher.feature.contests.redux.ContestsState +import com.bogdan.codeforceswatcher.feature.contests.redux.request.ContestsRequests import com.bogdan.codeforceswatcher.store import com.bogdan.codeforceswatcher.util.Analytics import kotlinx.android.synthetic.main.fragment_contests.recyclerView @@ -20,7 +20,7 @@ import org.rekotlin.StoreSubscriber class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, StoreSubscriber { - private lateinit var contestAdapter: ContestAdapter + private val contestAdapter by lazy { ContestAdapter(listOf(), requireContext()) } override fun onStart() { super.onStart() @@ -59,7 +59,6 @@ class ContestsFragment : Fragment(), SwipeRefreshLayout.OnRefreshListener, private fun initViews() { swipeToRefresh.setOnRefreshListener(this) - contestAdapter = ContestAdapter(listOf(), requireContext()) recyclerView.adapter = contestAdapter recyclerView.layoutManager = LinearLayoutManager(requireContext()) }