From 1fa3f8c43d2e53b40578c679d2e642aba94a85ec Mon Sep 17 00:00:00 2001 From: Carlos Martinez Date: Thu, 6 Feb 2020 10:35:54 -0300 Subject: [PATCH 1/2] implement favorite button --- app/src/main/AndroidManifest.xml | 3 +- .../hako/base/domain/database/dao/UserDao.kt | 8 +++- .../base/domain/database/entities/User.kt | 3 +- .../hako/base/domain/network/RequestStatus.kt | 1 + .../hako/base/extensions/DataExtensions.kt | 2 + .../com/hako/base/navigation/ShowFabButton.kt | 3 ++ .../com/hako/base/widgets/EmptyOverlay.kt | 23 ++++++++++ .../java/com/hako/base/widgets/LikeButton.kt | 16 +++++-- base/src/main/res/layout/empty_overlay.xml | 33 ++++++++++++++ .../main/res/layout/network_error_overlay.xml | 10 ++--- base/src/main/res/raw/empty_animation.json | 1 + .../com/hako/userlist/di/UserlistModules.kt | 4 ++ .../domain/usecase/GetFavoriteUsers.kt | 29 +++++++++++++ .../hako/userlist/domain/usecase/GetUsers.kt | 11 +++-- .../domain/usecase/SetFavoriteStatus.kt | 26 +++++++++++ .../hako/userlist/feature/UserlistFragment.kt | 21 +++++++-- .../com/hako/userlist/model/UserModels.kt | 4 +- .../userlist/viewmodel/UserlistViewmodel.kt | 43 ++++++++++++++++--- .../hako/userlist/widget/UserlistAdapter.kt | 14 ++++-- .../src/main/res/layout/fragment_userlist.xml | 10 +++++ 20 files changed, 236 insertions(+), 29 deletions(-) create mode 100644 base/src/main/java/com/hako/base/navigation/ShowFabButton.kt create mode 100644 base/src/main/java/com/hako/base/widgets/EmptyOverlay.kt create mode 100644 base/src/main/res/layout/empty_overlay.xml create mode 100644 base/src/main/res/raw/empty_animation.json create mode 100644 userlist/src/main/java/com/hako/userlist/domain/usecase/GetFavoriteUsers.kt create mode 100644 userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ba6cfa1..8eebcdc 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,7 +11,8 @@ android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="false" - android:theme="@style/AppTheme"> + android:theme="@style/AppTheme" + android:hardwareAccelerated="true"> ) + @Query("UPDATE ${UserEntity.TABLE_NAME} SET isFavorite = :favorite WHERE id = :id") + fun saveFavorite(id: Int, favorite: Boolean): Int + @get:Query("SELECT * FROM ${UserEntity.TABLE_NAME}") val all: List - @Query("SELECT * FROM ${UserEntity.TABLE_NAME}") + @Query("SELECT * FROM ${UserEntity.TABLE_NAME} ORDER BY id ASC") fun getAllUsers(): List + @Query("SELECT * FROM ${UserEntity.TABLE_NAME} WHERE isFavorite = 1 ORDER BY id ASC") + fun getFavoriteUsers(): List + @Query("SELECT COUNT(*) FROM ${UserEntity.TABLE_NAME}") fun count(): Int diff --git a/base/src/main/java/com/hako/base/domain/database/entities/User.kt b/base/src/main/java/com/hako/base/domain/database/entities/User.kt index c359911..14e5be0 100644 --- a/base/src/main/java/com/hako/base/domain/database/entities/User.kt +++ b/base/src/main/java/com/hako/base/domain/database/entities/User.kt @@ -12,7 +12,8 @@ data class UserEntity( val userName: String, val email: String, val phone: String, - val website: String + val website: String, + val isFavorite: Boolean = true ) { companion object { const val TABLE_NAME = "users" diff --git a/base/src/main/java/com/hako/base/domain/network/RequestStatus.kt b/base/src/main/java/com/hako/base/domain/network/RequestStatus.kt index d34b084..f599907 100644 --- a/base/src/main/java/com/hako/base/domain/network/RequestStatus.kt +++ b/base/src/main/java/com/hako/base/domain/network/RequestStatus.kt @@ -4,4 +4,5 @@ sealed class RequestStatus { object Ready : RequestStatus() object Loading : RequestStatus() object Errored : RequestStatus() + object Empty : RequestStatus() } diff --git a/base/src/main/java/com/hako/base/extensions/DataExtensions.kt b/base/src/main/java/com/hako/base/extensions/DataExtensions.kt index f4ad2c3..f469a26 100644 --- a/base/src/main/java/com/hako/base/extensions/DataExtensions.kt +++ b/base/src/main/java/com/hako/base/extensions/DataExtensions.kt @@ -11,3 +11,5 @@ fun LiveData.observeNonNull(owner: LifecycleOwner, func: (T) -> Unit) { } }) } + +fun Int.wasUpdated() = this > 0 \ No newline at end of file diff --git a/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt b/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt new file mode 100644 index 0000000..20475f8 --- /dev/null +++ b/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt @@ -0,0 +1,3 @@ +package com.hako.base.navigation + +interface ShowFabButton \ No newline at end of file diff --git a/base/src/main/java/com/hako/base/widgets/EmptyOverlay.kt b/base/src/main/java/com/hako/base/widgets/EmptyOverlay.kt new file mode 100644 index 0000000..cf4ace9 --- /dev/null +++ b/base/src/main/java/com/hako/base/widgets/EmptyOverlay.kt @@ -0,0 +1,23 @@ +package com.hako.base.widgets + +import android.content.Context +import android.util.AttributeSet +import android.widget.FrameLayout +import com.hako.base.R +import com.hako.base.extensions.inflate +import kotlinx.android.synthetic.main.empty_overlay.view.* + +class EmptyOverlay @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr) { + + init { + inflate(R.layout.empty_overlay, true) + } + + fun setLabel(message: String) { + empty_overlay_label.text = message + } +} \ No newline at end of file diff --git a/base/src/main/java/com/hako/base/widgets/LikeButton.kt b/base/src/main/java/com/hako/base/widgets/LikeButton.kt index 357dbe1..3757df0 100644 --- a/base/src/main/java/com/hako/base/widgets/LikeButton.kt +++ b/base/src/main/java/com/hako/base/widgets/LikeButton.kt @@ -10,7 +10,7 @@ import kotlinx.android.synthetic.main.like_button.view.* private const val LIKE_MIN_FRAME = 0 private const val LIKE_MAX_FRAME = 28 private const val LIKE_ANIM_SPEED = 1f -private const val DISLIKE_MIN_FRAME = 28 +private const val DISLIKE_MIN_FRAME = 29 private const val DISLIKE_MAX_FRAME = 70 private const val DISLIKE_ANIM_SPEED = 2f @@ -29,16 +29,24 @@ class LikeButton @JvmOverloads constructor( } fun dislike() { - like_button_animation_view.frame = LIKE_MIN_FRAME + like_button_animation_view.frame = DISLIKE_MAX_FRAME } - fun playLike() { + fun play() { + if (like_button_animation_view.frame <= LIKE_MAX_FRAME){ + playDislike() + } else { + playLike() + } + } + + private fun playLike() { like_button_animation_view.setMinAndMaxFrame(LIKE_MIN_FRAME, LIKE_MAX_FRAME) like_button_animation_view.speed = LIKE_ANIM_SPEED like_button_animation_view.playAnimation() } - fun playDislike() { + private fun playDislike() { like_button_animation_view.setMinAndMaxFrame(DISLIKE_MIN_FRAME, DISLIKE_MAX_FRAME) like_button_animation_view.speed = DISLIKE_ANIM_SPEED like_button_animation_view.playAnimation() diff --git a/base/src/main/res/layout/empty_overlay.xml b/base/src/main/res/layout/empty_overlay.xml new file mode 100644 index 0000000..5f7eb83 --- /dev/null +++ b/base/src/main/res/layout/empty_overlay.xml @@ -0,0 +1,33 @@ + + + + + + + + \ No newline at end of file diff --git a/base/src/main/res/layout/network_error_overlay.xml b/base/src/main/res/layout/network_error_overlay.xml index 72ee319..0aee1cc 100644 --- a/base/src/main/res/layout/network_error_overlay.xml +++ b/base/src/main/res/layout/network_error_overlay.xml @@ -6,7 +6,7 @@ android:background="@color/soft_background"> + app:layout_constraintEnd_toEndOf="@+id/network_error_overlay_animation_view" + app:layout_constraintStart_toStartOf="@+id/network_error_overlay_animation_view" + app:layout_constraintTop_toBottomOf="@+id/network_error_overlay_animation_view" /> \ No newline at end of file diff --git a/base/src/main/res/raw/empty_animation.json b/base/src/main/res/raw/empty_animation.json new file mode 100644 index 0000000..f79bf38 --- /dev/null +++ b/base/src/main/res/raw/empty_animation.json @@ -0,0 +1 @@ +{"v":"4.7.0","fr":25,"ip":0,"op":50,"w":120,"h":120,"nm":"Comp 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"ruoi","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.967]},"o":{"x":[0.167],"y":[0.033]},"n":["0p833_0p967_0p167_0p033"],"t":35,"s":[100],"e":[0]},{"t":49}]},"r":{"a":0,"k":0},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0,"y":0},"n":"0p833_0p833_0_0","t":0,"s":[57.361,61.016,0],"e":[57.699,41.796,0],"to":[-4.67500305175781,-4.12800598144531,0],"ti":[-13.9099960327148,5.27300262451172,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":10.219,"s":[57.699,41.796,0],"e":[79.084,33.982,0],"to":[12.8159942626953,-4.85800170898438,0],"ti":[-4.54498291015625,3.73400115966797,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":19.445,"s":[79.084,33.982,0],"e":[59.691,9.121,0],"to":[6.61601257324219,-5.43799591064453,0],"ti":[20.0290069580078,1.20700073242188,0]},{"t":35}]},"a":{"a":0,"k":[60.531,10.945,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-0.994,0],[0,-0.994],[0.995,0],[0,0.994]],"o":[[0.995,0],[0,0.994],[-0.994,0],[0,-0.994]],"v":[[-0.001,-1.801],[1.801,-0.001],[-0.001,1.801],[-1.801,-0.001]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.529,0.529,0.529,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[62.4,13.144],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.422,0],[0,-1.422],[1.421,0],[0,1.422]],"o":[[1.421,0],[0,1.422],[-1.422,0],[0,-1.422]],"v":[[0.001,-2.574],[2.574,0],[0.001,2.574],[-2.574,0]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.529,0.529,0.529,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0.7},"lc":1,"lj":1,"ml":10,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[64.145,9.606],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"ix":2,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-1.996,0],[0,-1.996],[1.996,0],[0,1.996]],"o":[[1.996,0],[0,1.996],[-1.996,0],[0,-1.996]],"v":[[0,-3.614],[3.614,0],[0,3.614],[-3.614,0]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.529,0.529,0.529,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":0.7},"lc":1,"lj":1,"ml":10,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"fl","c":{"a":0,"k":[1,1,1,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[57.957,10.552],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 3","np":3,"cix":2,"ix":3,"mn":"ADBE Vector Group"},{"ty":"tr","p":{"a":0,"k":[60.531,10.941],"ix":2},"a":{"a":0,"k":[60.531,10.941],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"ruoi","np":3,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":50,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 2","ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.967]},"o":{"x":[0.167],"y":[0.033]},"n":["0p833_0p967_0p167_0p033"],"t":35,"s":[100],"e":[0]},{"t":49}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[-0.75,-0.75,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[-13.91,5.273],[-4.545,3.734],[20.029,1.207]],"o":[[-4.675,-4.128],[12.816,-4.858],[6.616,-5.438],[0,0]],"v":[[-7.383,24.76],[-7.046,5.54],[14.34,-2.273],[-3.178,-24.76]],"c":false}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"st","c":{"a":0,"k":[0.627,0.627,0.627,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":1},"lc":2,"lj":2,"d":[{"n":"d","nm":"dash","v":{"a":0,"k":2.028}},{"n":"g","nm":"gap","v":{"a":0,"k":2.028}},{"n":"o","nm":"offset","v":{"a":0,"k":0}}],"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke"},{"ty":"tr","p":{"a":0,"k":[67.87,37.631],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 6","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.953]},"o":{"x":[0.167],"y":[0.033]},"n":["0p833_0p953_0p167_0p033"],"t":0,"s":[0],"e":[100]},{"t":35}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim"}],"ip":0,"op":50,"st":0,"bm":0,"sr":1},{"ddd":0,"ind":3,"ty":4,"nm":"im_emptyBox Outlines","ks":{"o":{"a":0,"k":100},"r":{"a":0,"k":0},"p":{"a":0,"k":[60,60,0]},"a":{"a":0,"k":[60,60,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-0.001,-16.607],[-32.143,-0.002],[-0.001,16.607],[32.144,-0.002]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.8,0.82,0.851,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[60,55.75],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 7","np":2,"cix":2,"ix":1,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[12.856,-23.249],[0,-16.605],[-12.857,-23.249],[-45,-6.641],[-32.144,0.001],[-45,6.645],[-12.857,23.249],[0,16.609],[12.856,23.249],[45,6.645],[32.143,0.001],[45,-6.641]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.957,0.957,0.957,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[60,55.748],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 8","np":2,"cix":2,"ix":2,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-16.072,24.171],[16.072,11.312],[16.072,-24.171],[-16.072,-24.171]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.902,0.914,0.929,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[76.072,83.33],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 9","np":2,"cix":2,"ix":3,"mn":"ADBE Vector Group"},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-32.143,-24.171],[-32.143,11.311],[-0.001,24.171],[32.144,11.311],[32.144,-24.171]],"c":true}},"nm":"Path 1","mn":"ADBE Vector Shape - Group"},{"ty":"fl","c":{"a":0,"k":[0.8,0.82,0.851,1]},"o":{"a":0,"k":100},"r":1,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill"},{"ty":"tr","p":{"a":0,"k":[60,83.33],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 10","np":2,"cix":2,"ix":4,"mn":"ADBE Vector Group"},{"ty":"tr","p":{"a":0,"k":[60,60.186],"ix":2},"a":{"a":0,"k":[60,60.186],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"box","np":4,"cix":2,"ix":1,"mn":"ADBE Vector Group"}],"ip":0,"op":50,"st":0,"bm":0,"sr":1}]} \ No newline at end of file diff --git a/userlist/src/main/java/com/hako/userlist/di/UserlistModules.kt b/userlist/src/main/java/com/hako/userlist/di/UserlistModules.kt index d9a58bb..f31580e 100644 --- a/userlist/src/main/java/com/hako/userlist/di/UserlistModules.kt +++ b/userlist/src/main/java/com/hako/userlist/di/UserlistModules.kt @@ -2,7 +2,9 @@ package com.hako.userlist.di import com.hako.base.domain.network.RemoteClient import com.hako.userlist.domain.datasource.UserlistRemoteApi +import com.hako.userlist.domain.usecase.GetFavoriteUsers import com.hako.userlist.domain.usecase.GetUsers +import com.hako.userlist.domain.usecase.SetFavoriteStatus import com.hako.userlist.viewmodel.UserlistViewmodel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module @@ -10,6 +12,8 @@ import org.koin.dsl.module val userlistModules = module { factory { get().getClient(UserlistRemoteApi::class.java) } factory { GetUsers(get()) } + factory { GetFavoriteUsers(get()) } + factory { SetFavoriteStatus(get()) } viewModel { UserlistViewmodel() } } \ No newline at end of file diff --git a/userlist/src/main/java/com/hako/userlist/domain/usecase/GetFavoriteUsers.kt b/userlist/src/main/java/com/hako/userlist/domain/usecase/GetFavoriteUsers.kt new file mode 100644 index 0000000..c656e6e --- /dev/null +++ b/userlist/src/main/java/com/hako/userlist/domain/usecase/GetFavoriteUsers.kt @@ -0,0 +1,29 @@ +package com.hako.userlist.domain.usecase + +import com.hako.base.domain.database.dao.UserDao +import com.hako.userlist.model.UserViewable +import com.hako.userlist.model.toUserViewable +import io.reactivex.Single +import io.reactivex.schedulers.Schedulers + +class GetFavoriteUsers(private val dao: UserDao) { + + fun execute( + onSuccess: (List) -> Unit, + onEmpty: () -> Unit, + onError: (Throwable) -> Unit + ) { + Single.fromCallable { dao.getFavoriteUsers() } + .subscribeOn(Schedulers.io()) + .doOnSuccess { dbUsers -> + if (dbUsers.isEmpty()) { + onEmpty() + } else { + onSuccess(dbUsers.map { it.toUserViewable() }) + } + } + .doOnError { onError(it) } + .onErrorReturn { emptyList() } + .subscribe() + } +} diff --git a/userlist/src/main/java/com/hako/userlist/domain/usecase/GetUsers.kt b/userlist/src/main/java/com/hako/userlist/domain/usecase/GetUsers.kt index 864a693..28ec6e3 100644 --- a/userlist/src/main/java/com/hako/userlist/domain/usecase/GetUsers.kt +++ b/userlist/src/main/java/com/hako/userlist/domain/usecase/GetUsers.kt @@ -17,7 +17,8 @@ class GetUsers(private val dao: UserDao) : KoinComponent { fun execute( onSuccess: (List) -> Unit, onError: (Throwable) -> Unit, - onLoading: () -> Unit + onLoading: () -> Unit, + onEmpty: () -> Unit ) { Single.fromCallable { dao.getAllUsers() } .subscribeOn(Schedulers.io()) @@ -26,8 +27,12 @@ class GetUsers(private val dao: UserDao) : KoinComponent { if (dbUsers.isEmpty()) { api.getUsers() .doOnSuccess { - dao.saveAll(it.map { user -> user.toUserEntity() }) - onSuccess(dao.getAllUsers().map { user -> user.toUserViewable() }) + if (it.isEmpty()) { + onEmpty() + } else { + dao.saveAll(it.map { user -> user.toUserEntity() }) + onSuccess(dao.getAllUsers().map { user -> user.toUserViewable() }) + } } .doOnSubscribe { onLoading() } .subscribeOn(Schedulers.io()) diff --git a/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt b/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt new file mode 100644 index 0000000..f067ead --- /dev/null +++ b/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt @@ -0,0 +1,26 @@ +package com.hako.userlist.domain.usecase + +import com.hako.base.domain.database.dao.UserDao +import com.hako.base.extensions.wasUpdated +import com.hako.userlist.domain.datasource.UserlistRemoteApi +import com.hako.userlist.model.UserViewable +import com.hako.userlist.model.toUserEntity +import com.hako.userlist.model.toUserViewable +import io.reactivex.Single +import io.reactivex.schedulers.Schedulers +import org.koin.core.KoinComponent +import org.koin.core.get + +class SetFavoriteStatus(private val dao: UserDao) { + + fun execute( + userId: Int, + favoriteStatus: Boolean, + onError: (userId: Int) -> Unit + ) { + Single.fromCallable { dao.saveFavorite(userId, favoriteStatus) } + .subscribeOn(Schedulers.io()) + .doOnError { onError(userId) } + .subscribe() + } +} diff --git a/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt b/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt index 64cda99..b837a41 100644 --- a/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt +++ b/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt @@ -12,6 +12,7 @@ import com.hako.base.extensions.observeNonNull import com.hako.base.extensions.toast import com.hako.base.extensions.visible import com.hako.base.navigation.NavigationRouter +import com.hako.base.navigation.ShowFabButton import com.hako.userlist.model.UserViewable import com.hako.userlist.viewmodel.UserlistViewmodel import com.hako.userlist.widget.UserlistAdapter @@ -22,7 +23,9 @@ import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel import timber.log.Timber -class UserlistFragment : Fragment() { +const val ALBUMLIST_FRAGMENT_BUNDLE_FAVORITES = "ALBUMLIST_FRAGMENT_BUNDLE_FAVORITES" + +class UserlistFragment : Fragment(), ShowFabButton { private val viewModel: UserlistViewmodel by viewModel() private val listAdapter by lazy { UserlistAdapter() } @@ -40,7 +43,7 @@ class UserlistFragment : Fragment() { } private fun setObservers() { - viewModel.data.observeNonNull(this) { + viewModel.userList.observeNonNull(this) { it.either(::handleFetchError, ::handleFetchSuccess) } @@ -49,17 +52,29 @@ class UserlistFragment : Fragment() { RequestStatus.Ready -> { fragment_userlist_error_overlay.gone() fragment_userlist_loading_overlay.gone() + fragment_userlist_empty_overlay.gone() } RequestStatus.Loading -> { fragment_userlist_error_overlay.gone() fragment_userlist_loading_overlay.visible() + fragment_userlist_empty_overlay.gone() } RequestStatus.Errored -> { fragment_userlist_error_overlay.visible() fragment_userlist_loading_overlay.gone() + fragment_userlist_empty_overlay.gone() + } + RequestStatus.Empty -> { + fragment_userlist_error_overlay.gone() + fragment_userlist_loading_overlay.gone() + fragment_userlist_empty_overlay.visible() } } } + + viewModel.emptyMessage.observeNonNull(this) { + fragment_userlist_empty_overlay.setLabel(it) + } } private fun handleFetchError(throwable: Throwable) { @@ -79,7 +94,7 @@ class UserlistFragment : Fragment() { } onFavoriteClick = { - context.toast(it.userName) + viewModel.updateUserFavoriteStatus(it.id, !it.isFavorite) } } } diff --git a/userlist/src/main/java/com/hako/userlist/model/UserModels.kt b/userlist/src/main/java/com/hako/userlist/model/UserModels.kt index b89a2aa..0fe1412 100644 --- a/userlist/src/main/java/com/hako/userlist/model/UserModels.kt +++ b/userlist/src/main/java/com/hako/userlist/model/UserModels.kt @@ -19,10 +19,10 @@ data class UserViewable( val id: Int, val realName: String, val userName: String, - var isFavorite: Boolean = false + var isFavorite: Boolean ) fun User.toUserEntity() = UserEntity(this.id, this.realName, this.userName, this.email, this.phone, this.website) -fun UserEntity.toUserViewable() = UserViewable(this.id, this.realName, this.userName) +fun UserEntity.toUserViewable() = UserViewable(this.id, this.realName, this.userName, this.isFavorite) diff --git a/userlist/src/main/java/com/hako/userlist/viewmodel/UserlistViewmodel.kt b/userlist/src/main/java/com/hako/userlist/viewmodel/UserlistViewmodel.kt index abe56e5..600cca4 100644 --- a/userlist/src/main/java/com/hako/userlist/viewmodel/UserlistViewmodel.kt +++ b/userlist/src/main/java/com/hako/userlist/viewmodel/UserlistViewmodel.kt @@ -3,34 +3,65 @@ package com.hako.userlist.viewmodel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.hako.base.domain.network.RequestStatus -import com.hako.base.domain.network.RequestStatus.Ready -import com.hako.base.domain.network.RequestStatus.Loading -import com.hako.base.domain.network.RequestStatus.Errored import com.hako.base.domain.Either +import com.hako.base.domain.network.RequestStatus.* +import com.hako.userlist.domain.usecase.GetFavoriteUsers import com.hako.userlist.domain.usecase.GetUsers +import com.hako.userlist.domain.usecase.SetFavoriteStatus import com.hako.userlist.model.UserViewable import org.koin.core.KoinComponent import org.koin.core.get class UserlistViewmodel : ViewModel(), KoinComponent { - val data = MutableLiveData>>() + val userList = MutableLiveData>>() + val favoriteError = MutableLiveData() + val emptyMessage = MutableLiveData() val requestStatus = MutableLiveData() private val getUsers: GetUsers = get() + private val getFavoriteUsers: GetFavoriteUsers = get() + private val setFavoriteStatus: SetFavoriteStatus = get() fun fetchUsers() { getUsers.execute( onSuccess = { requestStatus.postValue(Ready) - data.postValue(Either.Right(it)) + userList.postValue(Either.Right(it)) }, onLoading = { requestStatus.postValue(Loading) }, onError = { requestStatus.postValue(Errored) - data.postValue(Either.Left(it)) + userList.postValue(Either.Left(it)) + }, + onEmpty = { + requestStatus.postValue(Empty) + emptyMessage.postValue("No se encontró ningún usuario") + }) + } + + fun fetchFavoriteUsers() { + getFavoriteUsers.execute( + onSuccess = { + requestStatus.postValue(Ready) + userList.postValue(Either.Right(it)) + }, + onError = { + requestStatus.postValue(Errored) + userList.postValue(Either.Left(it)) + }, + onEmpty = { + requestStatus.postValue(Empty) + emptyMessage.postValue("No tienes favoritos!") + }) + } + + fun updateUserFavoriteStatus(userId: Int, status: Boolean) { + setFavoriteStatus.execute(userId, status, + onError = { + favoriteError.postValue(it) }) } } diff --git a/userlist/src/main/java/com/hako/userlist/widget/UserlistAdapter.kt b/userlist/src/main/java/com/hako/userlist/widget/UserlistAdapter.kt index fe5f979..25dd99f 100644 --- a/userlist/src/main/java/com/hako/userlist/widget/UserlistAdapter.kt +++ b/userlist/src/main/java/com/hako/userlist/widget/UserlistAdapter.kt @@ -44,18 +44,26 @@ class UserlistAdapter : RecyclerView.Adapter() { } } -class UserViewHolder(private val view: View, - private val onItemClick: (UserViewable) -> Unit, - private val onFavoriteClick: (UserViewable) -> Unit) : +class UserViewHolder( + private val view: View, + private val onItemClick: (UserViewable) -> Unit, + private val onFavoriteClick: (UserViewable) -> Unit +) : RecyclerView.ViewHolder(view) { fun bind(user: UserViewable) = with(view) { item_user_card_real_name.text = user.realName item_user_card_user_name.text = user.userName + if (user.isFavorite) { + item_user_card_like_button.like() + } else { + item_user_card_like_button.dislike() + } item_user_card_container.setOnClickListener { onItemClick(user) } item_user_card_like_button.setOnClickListener { + item_user_card_like_button.play() onFavoriteClick(user) } } diff --git a/userlist/src/main/res/layout/fragment_userlist.xml b/userlist/src/main/res/layout/fragment_userlist.xml index ef7295d..9f9d635 100644 --- a/userlist/src/main/res/layout/fragment_userlist.xml +++ b/userlist/src/main/res/layout/fragment_userlist.xml @@ -35,4 +35,14 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + \ No newline at end of file From f2c9082598f82f9e1d77ead59cdee53b9f0839b6 Mon Sep 17 00:00:00 2001 From: Carlos Martinez Date: Thu, 6 Feb 2020 11:32:39 -0300 Subject: [PATCH 2/2] implement favorite view --- .../com/hako/friendlists/view/MainActivity.kt | 27 +++++++++++++++++- .../viewmodel/NavigationViewmodel.kt | 3 ++ app/src/main/res/layout/activity_main.xml | 10 +++++++ app/src/main/res/values/colors.xml | 2 +- .../base/extensions/NavigationExtensions.kt | 26 +++++++++++++++++ .../com/hako/base/navigation/ShowFabButton.kt | 6 +++- base/src/main/res/drawable-hdpi/ic_heart.png | Bin 0 -> 778 bytes base/src/main/res/drawable-mdpi/ic_heart.png | Bin 0 -> 457 bytes base/src/main/res/drawable-xhdpi/ic_heart.png | Bin 0 -> 890 bytes .../src/main/res/drawable-xxhdpi/ic_heart.png | Bin 0 -> 1023 bytes .../main/res/drawable-xxxhdpi/ic_heart.png | Bin 0 -> 1119 bytes .../domain/usecase/SetFavoriteStatus.kt | 7 ----- .../feature/FavoriteUserlistFragment.kt | 9 ++++++ .../hako/userlist/feature/UserlistFragment.kt | 17 +++++++---- .../userlist/navigation/UserlistNavigation.kt | 1 + .../res/navigation/userlist_navigation.xml | 16 ++++++++++- 16 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 base/src/main/res/drawable-hdpi/ic_heart.png create mode 100644 base/src/main/res/drawable-mdpi/ic_heart.png create mode 100644 base/src/main/res/drawable-xhdpi/ic_heart.png create mode 100644 base/src/main/res/drawable-xxhdpi/ic_heart.png create mode 100644 base/src/main/res/drawable-xxxhdpi/ic_heart.png create mode 100644 userlist/src/main/java/com/hako/userlist/feature/FavoriteUserlistFragment.kt diff --git a/app/src/main/java/com/hako/friendlists/view/MainActivity.kt b/app/src/main/java/com/hako/friendlists/view/MainActivity.kt index 43a6891..14723a0 100644 --- a/app/src/main/java/com/hako/friendlists/view/MainActivity.kt +++ b/app/src/main/java/com/hako/friendlists/view/MainActivity.kt @@ -4,18 +4,21 @@ import android.os.Bundle import androidx.appcompat.app.AppCompatActivity import androidx.navigation.findNavController import androidx.navigation.ui.NavigationUI.setupActionBarWithNavController -import com.hako.base.extensions.observeNonNull +import com.hako.base.extensions.* import com.hako.base.navigation.NavigationRouter +import com.hako.base.navigation.ShowFabButton import com.hako.friendlists.BuildConfig import com.hako.friendlists.R import com.hako.friendlists.viewmodel.NavigationViewmodel import com.squareup.picasso.Picasso +import kotlinx.android.synthetic.main.activity_main.* import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel class MainActivity : AppCompatActivity() { private val navController by lazy { findNavController(R.id.main_fragment_container) } + private val navHostFragment by lazy { findNavHostFragment(R.id.main_fragment_container) } private val navRouter: NavigationRouter by inject() private val picasso: Picasso by inject() private val viewModel: NavigationViewmodel by viewModel() @@ -39,6 +42,28 @@ class MainActivity : AppCompatActivity() { } setupActionBarWithNavController(this, navController) + + navHostFragment.registerOnFragmentViewCreated { currentFragment -> + initializeViews() + when (currentFragment) { + is ShowFabButton -> fabButtonBehaviour(currentFragment) + } + } + } + + private fun initializeViews() { + main_fragment_fab.hide() + } + + private fun fabButtonBehaviour(currentFragment: ShowFabButton) { + main_fragment_fab.setOnClickListener { + currentFragment.fabButtonPressed().invoke() + } + if (currentFragment.shouldShowFabButton()) { + main_fragment_fab.show() + } else { + main_fragment_fab.hide() + } } private fun setupPicasso() { diff --git a/app/src/main/java/com/hako/friendlists/viewmodel/NavigationViewmodel.kt b/app/src/main/java/com/hako/friendlists/viewmodel/NavigationViewmodel.kt index 4c8bb76..aa1db70 100644 --- a/app/src/main/java/com/hako/friendlists/viewmodel/NavigationViewmodel.kt +++ b/app/src/main/java/com/hako/friendlists/viewmodel/NavigationViewmodel.kt @@ -35,6 +35,9 @@ class NavigationViewmodel : ViewModel() { putString(FRAGMENT_TITLE, event.userName) }) ) + is UserlistNavigation.ClickedOnFab -> navigate.postValue( + buildNavigation(R.id.action_userlistFragment_to_favoriteUserlistFragment) + ) } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 626a29b..78e06e2 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -15,4 +15,14 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index ecb305d..68bac2d 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -2,7 +2,7 @@ #37474F #324047 - #CBCFD1 + #D32F2F #D32F2F #333333 diff --git a/base/src/main/java/com/hako/base/extensions/NavigationExtensions.kt b/base/src/main/java/com/hako/base/extensions/NavigationExtensions.kt index 24eff13..7e0e618 100644 --- a/base/src/main/java/com/hako/base/extensions/NavigationExtensions.kt +++ b/base/src/main/java/com/hako/base/extensions/NavigationExtensions.kt @@ -1,6 +1,32 @@ package com.hako.base.extensions import android.os.Bundle +import android.view.View import androidx.annotation.IdRes +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import androidx.navigation.fragment.NavHostFragment + +fun AppCompatActivity.findNavHostFragment(@IdRes id: Int) = + supportFragmentManager.findFragmentById(id) as NavHostFragment + +fun NavHostFragment.registerOnFragmentViewCreated( + recursive: Boolean = true, + listener: (currentFragment: Fragment) -> Unit +) { + childFragmentManager + .registerFragmentLifecycleCallbacks(object : FragmentManager.FragmentLifecycleCallbacks() { + override fun onFragmentViewCreated( + fm: FragmentManager, + f: Fragment, + v: View, + savedInstanceState: Bundle? + ) { + super.onFragmentViewCreated(fm, f, v, savedInstanceState) + listener(f) + } + }, recursive) +} fun buildNavigation(@IdRes id: Int, bundle: Bundle = Bundle()) = Pair(id, bundle) diff --git a/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt b/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt index 20475f8..9685690 100644 --- a/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt +++ b/base/src/main/java/com/hako/base/navigation/ShowFabButton.kt @@ -1,3 +1,7 @@ package com.hako.base.navigation -interface ShowFabButton \ No newline at end of file +interface ShowFabButton { + fun shouldShowFabButton(): Boolean + + fun fabButtonPressed(): () -> Unit = {} +} \ No newline at end of file diff --git a/base/src/main/res/drawable-hdpi/ic_heart.png b/base/src/main/res/drawable-hdpi/ic_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..4fd52b2dec7076553a8d85261e8776b262d827dd GIT binary patch literal 778 zcmV+l1NHogP)y5w4%4vU?+vzCRwo@q@|HsZ2L+lS<Zz-6QEy4o5X6c1Dw=vrnSbBjf8B{_Br`#mG3I2pn9+cTm(Nr3j8X7t>2vi2f#sa zR-f4()~Dp_0@zFqPBBz@2|RH88!v*$J#Zb|(0jXx_4IXLzSqq^K5h9{skJ;9a+7gU z?0QSSdqE2Y9R=qVboK%amP+o?Go}U&Mf~jmgt(!GQ3`quVj&Pj4N*h6ArS&W)bPPj zP|bxv5H(m7^c~EGKoC#bH$#~-9s)t{!CMM?1g1hD=s9?3s0dDkK+s(lZ3@~AP6aF` zqk=p@L7iZKz+%Wg&_O{pU_F=wF9Q(t0*tG`*W@aG3%CrPsJ3J(v@`Vem?ZIy0mO?mg^~HaEu7fPeW=`tRj0H2JmssYxDN}m}omy^B7Yz z9#TT?Xfvn10eg9R{T{O!R~_Iq_)=h}_}y0xkzEUl7Y~9=jmiVyns#f}73{XM{3~!1 z?9r@mmh(cQL1|%BUEZAQSkEZWwDF`?;)cXjO6b*)Ii(i(lPdQyunjCO>(1m6#@e?W z+>(%}y1wR$?94x|aH>H&*eKf7Uqynv?~|3|v_?f?J)07*qo IM6N<$g6GU;=Kufz literal 0 HcmV?d00001 diff --git a/base/src/main/res/drawable-mdpi/ic_heart.png b/base/src/main/res/drawable-mdpi/ic_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..ba121c8622af206e2647524cfe90f1e8ce7a4c28 GIT binary patch literal 457 zcmV;)0XF`LP)M*6vn45goe!xt_k@7gw6lYzz2{UC4a6dNiLMyB>4a+E>^^<4Gmd4X7)Rc=g~8@ zP0P;izGLfmGkf0WnfJWsJ!dTIzkWdwq`@3G1bOfU3g8qhf!>PPKCrC+3X08ZEj7|n z@jq%<^ zbkSg1uD^*#jrEMY->flM#Xxeicp23C|Z3JY(=fUiJ}kITM@j}%S#Kf`eOT{ z&{R=dyvAsnG;GrRPw{+m28NK7q+K^V!N3o!OJ?V6c4xntv8-zQRzsjby8&1O+u<%n*hWliSDj~o=kC$^++Z={lw1a(IS|~sh?1j^Loz0d(uAmJ= zaFROdC6A@cY*P<)3ie1}^^VUc`Du^yCreUh7AH&dm%Bh0X@tjS(`JHt*vF9Sx24@* z_n0zS<_U_K&f`RzN%m2mpH-qN0-U2^?Lo?VlG)Ia#2rUdu}W5UvE^LGXX7*lhQst9nDh79PqDhyx15g`G#&@+PqNExw7 zNPuSQ;}kFM@rO6cTfQlOW+v0V#}M{#fI)ZwCkoApjSnERvW?K8y`9q@se5A7!FxYg zD1e`9H?pkqm23|LuvOUryJSfPYKtvs)xtV>NYM&TGu3&e509t?7Qw=q7P$OeVi9jy zIN24t@>A?Xi2S82EgB!72Ii40fF}1H&iQP;os@C#7F-SjnTi8XaN;&qEC3~2+O|v6I*Z=?k literal 0 HcmV?d00001 diff --git a/base/src/main/res/drawable-xxhdpi/ic_heart.png b/base/src/main/res/drawable-xxhdpi/ic_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..f3c77c1fb0dee0fe09d261d84362d1bb6b39969d GIT binary patch literal 1023 zcmV^cZGEJya_6P$X#h5Og7k3W-Vs!-A-w z+Z5%kX`GyK{-sO$(e~W_gM#iPiOS({mq=qz8%NWO}CV7(P*@WtYeL20E`hI z2m!yf?+zJcm&pcD5##ukq#l^R9b$K_WB9Ey;Jz`d?2S;b8VyJTN>f1e;c~JTbdhtc zmyCi>WCnym(Aqb_g)|gb~&N{CnNeoHM zlJ85HwLY7y<71snSnog=-<(_yT+NMcNYCv6Zkct=r8g^INTj6CN&^8m=8h& z(tx}NGz?y9K<U-QUIU5~khu=^10PHr z$fvH55Y)@Z*Iv;OE1>113XH%+g2_Dl)kv4dQ&J7eG$0KqbpaKTQqV!pv+Lv!2Ge1H(c2UN%o4V{~+q_Hz)_~#!w3X)+8>jf(6~P<| zC}@@aB-Cq5vX&)OkbU5RHDr{H!#Cm~IRq+Gv2H^H(tx}LRBElU=;rkj0;kq4WT?vm z%YbD&OE!YibS#zHNsa^j#=;qT*1<9y13NOYmP`ZEfV>4%Y(1i%0OnEtHwdRF5PbL> z;O85GWh>5x<(n;_FAX#H?Fr!5$U%{f>svLT1eztHlUEjsDQHR0C#ffJ+8SUuZLT#U z+gD3h;m`?BikM_G9!DUgJv9yuPNO=PmXm8h8j!buO1SMNTH*HFgL44+79FdbVhUW~ zz8vESSqVyV`3(+cvEC+j7-zD_8NCfy6W!b3Mo^zmuei{F;sj(C46kR+yyQrHwYp7^ z4_+iN#;cO0MP8S$FHA8_l-1xWFU=NjLBI7@gc2v;Hw{Pw@*GeR&cET+#qFR2G+FbP tiVE>1PGw}(63U!H-!vc%NVkIC{sOt$Cupv!!z=&*002ovPDHLkV1mu4$vpr7 literal 0 HcmV?d00001 diff --git a/base/src/main/res/drawable-xxxhdpi/ic_heart.png b/base/src/main/res/drawable-xxxhdpi/ic_heart.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2fc6f677cb2a2891b12c2f81a4af8f75f340bc GIT binary patch literal 1119 zcmV-l1fctgP)D<^Te_sqNto;%0ZdLLu2S%+_X9vd4QTfAEk1WBO=*ehHB z`h)>s1Q=3&=CN=IXciU&i9Gt65S9R2h0DMbr5{5|fAMGflyUD-@<~zv1yBG56q*3} zV3{x-s1-H>r-fTUzc2{+Kt}io^a@?T5n(f61~z*f771H`qss5^Rr--p`itY~SH^ux z$){Gyu`C|}DPcWuPWT243qKv=hyR96o3I;b1x_lT^BwnfSjp$CuntI300mG01;j}} z7`Tmjc$^3Bg%2nje+mR3-NIGi8qoch&${j_=5trcacMZC9K%zlPfd!=jN<|1%V?g& zp|2Sw$3|hH4FymD1yDf50uBIYl&|A{Oa@g*XtOx;jd{O~r>tvqFg$0NY};)pfC4Ch z0wNah5=b*BXQadZgfTp2!(os?Ipc%y#)bkYfC4CB>M+^9wegf?)GUK?Mi%p?01BW0 z3W!+1SKvE?a)w!w{$k^W2aRk77?d;2)bq6s1yBG5P(Z{29soTI${A0E`!=3(Y`cp= zIinMg;ZpzwPyhu)ET9EA#-N-XBr`X4w%Hf~D}h}M&eKn}f$|hRG$=F*1bcE(@O5r-IuZ-Jdu^OnJ%#vjkKmim$0TBu?wQc4D zt;!YGL8Z(=F$9i9{IJ5KnI+BxDqUC8HOtm(fj;H9d!Y-!dJpC*ZxgUAigLyjKmim$ z0TBwQ6smxI!U>>|Y7hBJe{no!jI)5G7l$StX$XGTX|}&Q@*hId9G;U?B<1V9oQb^zVI#Km0}AIE!6?- z0hD;mvzpg%IIFTT`?kx0DvylV`Ce){Q_}@q(a&k!u9|F002ovPDHLkV1m`!+ynps literal 0 HcmV?d00001 diff --git a/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt b/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt index f067ead..6afdcac 100644 --- a/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt +++ b/userlist/src/main/java/com/hako/userlist/domain/usecase/SetFavoriteStatus.kt @@ -1,15 +1,8 @@ package com.hako.userlist.domain.usecase import com.hako.base.domain.database.dao.UserDao -import com.hako.base.extensions.wasUpdated -import com.hako.userlist.domain.datasource.UserlistRemoteApi -import com.hako.userlist.model.UserViewable -import com.hako.userlist.model.toUserEntity -import com.hako.userlist.model.toUserViewable import io.reactivex.Single import io.reactivex.schedulers.Schedulers -import org.koin.core.KoinComponent -import org.koin.core.get class SetFavoriteStatus(private val dao: UserDao) { diff --git a/userlist/src/main/java/com/hako/userlist/feature/FavoriteUserlistFragment.kt b/userlist/src/main/java/com/hako/userlist/feature/FavoriteUserlistFragment.kt new file mode 100644 index 0000000..b32dfc8 --- /dev/null +++ b/userlist/src/main/java/com/hako/userlist/feature/FavoriteUserlistFragment.kt @@ -0,0 +1,9 @@ +package com.hako.userlist.feature + +class FavoriteUserlistFragment : UserlistFragment() { + override fun doRequest() { + viewModel.fetchFavoriteUsers() + } + + override fun shouldShowFabButton() = false +} \ No newline at end of file diff --git a/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt b/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt index b837a41..db86a70 100644 --- a/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt +++ b/userlist/src/main/java/com/hako/userlist/feature/UserlistFragment.kt @@ -9,7 +9,6 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.hako.base.domain.network.RequestStatus import com.hako.base.extensions.gone import com.hako.base.extensions.observeNonNull -import com.hako.base.extensions.toast import com.hako.base.extensions.visible import com.hako.base.navigation.NavigationRouter import com.hako.base.navigation.ShowFabButton @@ -23,11 +22,9 @@ import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel import timber.log.Timber -const val ALBUMLIST_FRAGMENT_BUNDLE_FAVORITES = "ALBUMLIST_FRAGMENT_BUNDLE_FAVORITES" +open class UserlistFragment : Fragment(), ShowFabButton { -class UserlistFragment : Fragment(), ShowFabButton { - - private val viewModel: UserlistViewmodel by viewModel() + val viewModel: UserlistViewmodel by viewModel() private val listAdapter by lazy { UserlistAdapter() } private val navigation: NavigationRouter by inject() @@ -39,9 +36,19 @@ class UserlistFragment : Fragment(), ShowFabButton { super.onViewCreated(view, savedInstanceState) setRecycler() setObservers() + doRequest() + } + + open fun doRequest() { viewModel.fetchUsers() } + override fun shouldShowFabButton() = true + + override fun fabButtonPressed(): () -> Unit = { + navigation.sendNavigation(UserlistNavigation.ClickedOnFab) + } + private fun setObservers() { viewModel.userList.observeNonNull(this) { it.either(::handleFetchError, ::handleFetchSuccess) diff --git a/userlist/src/main/java/com/hako/userlist/navigation/UserlistNavigation.kt b/userlist/src/main/java/com/hako/userlist/navigation/UserlistNavigation.kt index 3fb87d5..3edb0c3 100644 --- a/userlist/src/main/java/com/hako/userlist/navigation/UserlistNavigation.kt +++ b/userlist/src/main/java/com/hako/userlist/navigation/UserlistNavigation.kt @@ -4,4 +4,5 @@ import com.hako.base.navigation.NavigationEvent sealed class UserlistNavigation : NavigationEvent { data class ClickedOnUser(val userId: Int, val userName: String) : UserlistNavigation() + object ClickedOnFab : UserlistNavigation() } diff --git a/userlist/src/main/res/navigation/userlist_navigation.xml b/userlist/src/main/res/navigation/userlist_navigation.xml index c680ef2..4424c70 100644 --- a/userlist/src/main/res/navigation/userlist_navigation.xml +++ b/userlist/src/main/res/navigation/userlist_navigation.xml @@ -9,6 +9,20 @@ android:id="@+id/userlistFragment" android:name="com.hako.userlist.feature.UserlistFragment" tools:layout="@layout/fragment_userlist" - android:label="Friendlist" /> + android:label="Friendlist" > + + + + \ No newline at end of file