Commit 0c141bec authored by Vladislav Bogdashkin's avatar Vladislav Bogdashkin 🎣

fix estate offline behaviour

parent 65a0a1b2
...@@ -102,6 +102,7 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon ...@@ -102,6 +102,7 @@ abstract class BigantoBaseController<VS : BigantoBaseViewState,V: BigantoBaseCon
} }
override fun handleBack(): Boolean { override fun handleBack(): Boolean {
detachDisposable.clear()
router.popController(this) router.popController(this)
return true return true
// return super.handleBack() // return super.handleBack()
......
...@@ -47,17 +47,16 @@ class EstateRepository @Inject constructor( ...@@ -47,17 +47,16 @@ class EstateRepository @Inject constructor(
.toList().toObservable() .toList().toObservable()
.doOnError(Timber::e) .doOnError(Timber::e)
){apiList,dbList -> ){apiList,dbList ->
if (dbList.isEmpty()) apiList.forEach { estate ->
return@zip apiList estate.setFavorite(true)
estate.user = user
}
dbList dbList
.filterNotNull() .filterNotNull()
.filter { dbFav ->!apiList.map{it.id}.contains(dbFav.id) } .filter { dbFav ->!apiList.map{it.id}.contains(dbFav.id) }
.let{ db.deleteEstate(it) } .let{ db.deleteEstate(it) }
apiList.forEach { estate ->
estate.setFavorite(true)
estate.user = user
}
return@zip apiList return@zip apiList
} }
.flatMap(db::upsertEstates) .flatMap(db::upsertEstates)
...@@ -72,54 +71,6 @@ class EstateRepository @Inject constructor( ...@@ -72,54 +71,6 @@ class EstateRepository @Inject constructor(
.map { it.map {deal -> deal.estate as EstateEntity } } .map { it.map {deal -> deal.estate as EstateEntity } }
.doOnNext { db.refreshUser(user) } .doOnNext { db.refreshUser(user) }
private val getFavoritesApi: Observable<List<EstateEntity>> =
local.recentUser()
.flatMap {
when (it) {
is UserState.Authenticated -> db.fetchUser(it.uuid.toInt())
else -> throw CustomApiException.NotAuthorizedException()
}
}
.flatMap { user ->
api.getFavorites(user.authToken)
.doOnError(Timber::e)
.map { fromRawList(it, ::fromRaw) }
.doOnNext {
it.forEach { estate ->
estate.setFavorite(true)
estate.user = user
}
}
.doOnNext(db::blockingUpsert)
.doOnNext{ db.refreshUser(user) }
}
private val getFavoritesDb: Observable<MutableList<EstateEntity?>>? =
local.recentUser()
.flatMap {
when (it) {
is UserState.Authenticated -> db.fetchUser(it.uuid.toInt()).take(1)
else -> throw CustomApiException.NotAuthorizedException()
}
}
.flatMap {
db.getUserFavorites(it.uuid)
.doOnError(Timber::e)
.toList().toObservable()
}
override fun getFavorites(user:UserEntity): Observable<List<EstateModel>> {
return Observable.mergeDelayError(
arrayListOf(
fetchFavorites(user), getFavoritesDb
)
)
.map { it.filterNotNull() }
.map { fromEntity(it, ::fromEntity) }
.doOnError(Timber::e)
}
private fun fetchEstateDb(id: Int) = db.getEstate(id) private fun fetchEstateDb(id: Int) = db.getEstate(id)
......
...@@ -21,5 +21,4 @@ interface DealContract{ ...@@ -21,5 +21,4 @@ interface DealContract{
fun setDealRead(dealId: String): Completable fun setDealRead(dealId: String): Completable
fun fetchDeals(user: UserEntity): Observable<List<EstateEntity>> fun fetchDeals(user: UserEntity): Observable<List<EstateEntity>>
fun fetchFavorites(user: UserEntity): Observable<List<EstateEntity>> fun fetchFavorites(user: UserEntity): Observable<List<EstateEntity>>
fun getFavorites(user: UserEntity): Observable<List<EstateModel>>
} }
\ No newline at end of file
...@@ -15,6 +15,9 @@ class FavoritesInteractor @Inject constructor( ...@@ -15,6 +15,9 @@ class FavoritesInteractor @Inject constructor(
private val estateUseCase: EstateUseCase private val estateUseCase: EstateUseCase
) { ) {
fun cachedFavorites() =
estateUseCase.prefetchFavorites()
fun getFavoritesForCurrentUser() = fun getFavoritesForCurrentUser() =
estateUseCase.fetchFavorites() estateUseCase.fetchFavorites()
// Single.just(parkingEstateSample ) // Single.just(parkingEstateSample )
...@@ -52,6 +55,7 @@ class FavoritesInteractor @Inject constructor( ...@@ -52,6 +55,7 @@ class FavoritesInteractor @Inject constructor(
albumId = 10, albumId = 10,
multitourId = null, multitourId = null,
url = null url = null
,availableStatus = true
), ),
EstateModel( EstateModel(
id = 1905, id = 1905,
...@@ -81,7 +85,7 @@ class FavoritesInteractor @Inject constructor( ...@@ -81,7 +85,7 @@ class FavoritesInteractor @Inject constructor(
albumId = 10, albumId = 10,
multitourId = null, multitourId = null,
url = null url = null
), ,availableStatus = true),
EstateModel( EstateModel(
id = 1774, id = 1774,
type = FlatType.valueOf("flat".toUpperCase()), type = FlatType.valueOf("flat".toUpperCase()),
...@@ -118,6 +122,7 @@ class FavoritesInteractor @Inject constructor( ...@@ -118,6 +122,7 @@ class FavoritesInteractor @Inject constructor(
albumId = 10, albumId = 10,
url = null, url = null,
multitourId = 5790 multitourId = 5790
,availableStatus = true
// ,explications = arrayListOf<ExplicationListModel>( // ,explications = arrayListOf<ExplicationListModel>(
// ExplicationListModel( // ExplicationListModel(
// planId = 0, // planId = 0,
......
...@@ -51,6 +51,7 @@ data class EstateModel( ...@@ -51,6 +51,7 @@ data class EstateModel(
val id:Int, val id:Int,
val type:FlatType, val type:FlatType,
val number:String, val number:String,
val availableStatus:Boolean,
val sectionBegin:Int?=null, val sectionBegin:Int?=null,
val sectionEnd:Int?=null, val sectionEnd:Int?=null,
val planPNG:PlanModel?, val planPNG:PlanModel?,
...@@ -90,6 +91,7 @@ fun fromEntity(entity:EstateEntity): EstateModel { ...@@ -90,6 +91,7 @@ fun fromEntity(entity:EstateEntity): EstateModel {
id = entity.id, id = entity.id,
type = FlatType.valueOf(entity.type.toUpperCase()), type = FlatType.valueOf(entity.type.toUpperCase()),
number = entity.number, number = entity.number,
availableStatus = entity.available,
sectionBegin = entity.sectionBegin, sectionBegin = entity.sectionBegin,
sectionEnd = entity.sectionEnd, sectionEnd = entity.sectionEnd,
planPNG = null, planPNG = null,
......
package com.biganto.visual.roompark.domain.use_case package com.biganto.visual.roompark.domain.use_case
import com.biganto.visual.roompark.data.repository.db.requrey.model.EstateEntity
import com.biganto.visual.roompark.domain.contract.AuthContract import com.biganto.visual.roompark.domain.contract.AuthContract
import com.biganto.visual.roompark.domain.contract.DealContract import com.biganto.visual.roompark.domain.contract.DealContract
import com.biganto.visual.roompark.domain.contract.FlatPlanContract import com.biganto.visual.roompark.domain.contract.FlatPlanContract
import com.biganto.visual.roompark.domain.model.EstateModel import com.biganto.visual.roompark.domain.model.EstateModel
import com.biganto.visual.roompark.domain.model.fromEntity
import io.reactivex.Observable import io.reactivex.Observable
import javax.inject.Inject import javax.inject.Inject
...@@ -17,9 +19,19 @@ class EstateUseCase @Inject constructor( ...@@ -17,9 +19,19 @@ class EstateUseCase @Inject constructor(
private val authContract: AuthContract private val authContract: AuthContract
) { ) {
fun prefetchFavorites() =
authContract.currentUser()
.map {user -> user.estates?.asSequence()
?.map { it as EstateEntity }
?.filter{ it.favorite }?.filterNotNull()?.toList()
}
.map { fromEntity(it, ::fromEntity) }
fun fetchFavorites(): Observable<List<EstateModel>> = fun fetchFavorites(): Observable<List<EstateModel>> =
authContract.currentUser() authContract.currentUser()
.flatMap (contract::getFavorites) .flatMap (contract::fetchFavorites)
.map { fromEntity(it, ::fromEntity) }
fun getEstate(estateId: Int) = contract.getEstate(estateId) fun getEstate(estateId: Int) = contract.getEstate(estateId)
......
...@@ -215,7 +215,8 @@ class EstateScreenController : ...@@ -215,7 +215,8 @@ class EstateScreenController :
if (it.scrollY > flatTitle.measuredHeight) { if (it.scrollY > flatTitle.measuredHeight) {
val status = estateModel?.to( val status = estateModel?.to(
StatusToolbarModel( StatusToolbarModel(
StatusState.AVAILABLE if (estateModel?.availableStatus == true) StatusState.AVAILABLE
else StatusState.SOLD_OUT
, null , null
, resources?.getString( , resources?.getString(
estateModel?.type?.typeShortString() ?: -1 estateModel?.type?.typeShortString() ?: -1
...@@ -229,7 +230,8 @@ class EstateScreenController : ...@@ -229,7 +230,8 @@ class EstateScreenController :
} else toolBar.setToolbar( } else toolBar.setToolbar(
null, null,
StatusToolbarModel( StatusToolbarModel(
StatusState.AVAILABLE, null, null if (estateModel?.availableStatus == true) StatusState.AVAILABLE
else StatusState.SOLD_OUT, null, null
) )
) )
} }
...@@ -237,7 +239,8 @@ class EstateScreenController : ...@@ -237,7 +239,8 @@ class EstateScreenController :
} }
private fun bindRecycler() { private fun bindRecycler() {
flatInfoRecyclerView.isNestedScrollingEnabled = true flatScroll.isNestedScrollingEnabled = false
flatInfoRecyclerView.isNestedScrollingEnabled = false
flatInfoRecyclerView.layoutManager = flatInfoRecyclerView.layoutManager =
LinearLayoutManager(activity, RecyclerView.VERTICAL, false) LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
flatInfoRecyclerView.adapter = FlatInfoAdapter() flatInfoRecyclerView.adapter = FlatInfoAdapter()
...@@ -378,8 +381,15 @@ class EstateScreenController : ...@@ -378,8 +381,15 @@ class EstateScreenController :
} }
private fun setEstateInfo(estateModel: EstateModel?){ private fun setEstateInfo(estateModel: EstateModel?){
this.estateModel = estateModel
toolBar.setToolbar( toolBar.setToolbar(
null, StatusToolbarModel(StatusState.AVAILABLE,null, null) null,
StatusToolbarModel(
if (estateModel?.availableStatus == true) StatusState.AVAILABLE
else StatusState.SOLD_OUT
, null
, null
)
) )
estateModel?.let {estate -> estateModel?.let {estate ->
flatTitle.text = resources?.getString(estate.type.typeShortString() flatTitle.text = resources?.getString(estate.type.typeShortString()
...@@ -402,6 +412,7 @@ class EstateScreenController : ...@@ -402,6 +412,7 @@ class EstateScreenController :
.into(tourScreen) .into(tourScreen)
} }
when(estateModel?.type){ when(estateModel?.type){
FlatType.FLAT -> { FlatType.FLAT -> {
flatTypeView.setGone(false) flatTypeView.setGone(false)
......
...@@ -66,6 +66,7 @@ class FavoritesScreenController : ...@@ -66,6 +66,7 @@ class FavoritesScreenController :
} }
private fun setToolbar(){ private fun setToolbar(){
R.string.area_living
favoritesRecyclerView.isNestedScrollingEnabled = false favoritesRecyclerView.isNestedScrollingEnabled = false
toolBar.setToolbar( toolBar.setToolbar(
...@@ -76,7 +77,7 @@ class FavoritesScreenController : ...@@ -76,7 +77,7 @@ class FavoritesScreenController :
} }
private fun bindRecycler() { private fun bindRecycler() {
favoritesRecyclerView.isNestedScrollingEnabled = true favoritesRecyclerView.isNestedScrollingEnabled = false
favoritesRecyclerView.layoutManager = favoritesRecyclerView.layoutManager =
LinearLayoutManager(activity, RecyclerView.VERTICAL, false) LinearLayoutManager(activity, RecyclerView.VERTICAL, false)
favoritesRecyclerView.adapter = FavoritesListAdapter() favoritesRecyclerView.adapter = FavoritesListAdapter()
...@@ -104,6 +105,7 @@ class FavoritesScreenController : ...@@ -104,6 +105,7 @@ class FavoritesScreenController :
is FavoritesScreenViewState.FavoriteEstatesLoaded -> render(viewState) is FavoritesScreenViewState.FavoriteEstatesLoaded -> render(viewState)
is FavoritesScreenViewState.SomeError -> render(viewState) is FavoritesScreenViewState.SomeError -> render(viewState)
is FavoritesScreenViewState.ToursLoaded -> render(viewState) is FavoritesScreenViewState.ToursLoaded -> render(viewState)
is FavoritesScreenViewState.RestoreView -> render(viewState)
} }
} }
......
...@@ -34,14 +34,21 @@ class FavoritesScreenPresenter @Inject constructor( ...@@ -34,14 +34,21 @@ class FavoritesScreenPresenter @Inject constructor(
override fun bindIntents() { override fun bindIntents() {
val prefetchCards = interactor.getFavoritesForCurrentUser() val prefetchCards = interactor.cachedFavorites()
.doOnNext { restoreModel.list = it.toMutableList() } .doOnNext { restoreModel.list = it.toMutableList() }
.map { FavoritesScreenViewState.FavoriteEstatesLoaded(it) } .map<FavoritesScreenViewState> { FavoritesScreenViewState.FavoriteEstatesLoaded(it) }
.onErrorReturn (::parseError)
val invalidateData = interactor.getFavoritesForCurrentUser()
.doOnNext { restoreModel.list = it.toMutableList() }
.map<FavoritesScreenViewState> { FavoritesScreenViewState.FavoriteEstatesLoaded(it) }
.onErrorReturn (::parseError)
val onStartTours = intent(FavoritesScreen::tourCardClicked) val onStartTours = intent(FavoritesScreen::tourCardClicked)
.flatMap {estate -> toursInteractor.getEstateTourList(estate) .flatMap {estate -> toursInteractor.getEstateTourList(estate)
.map { FavoritesScreenViewState.ToursLoaded(it) } .map<FavoritesScreenViewState> { FavoritesScreenViewState.ToursLoaded(it) }
.onErrorReturn (::parseError)
} }
...@@ -49,6 +56,7 @@ class FavoritesScreenPresenter @Inject constructor( ...@@ -49,6 +56,7 @@ class FavoritesScreenPresenter @Inject constructor(
arrayListOf( arrayListOf(
restoreStateObservable, restoreStateObservable,
prefetchCards, prefetchCards,
invalidateData,
onStartTours onStartTours
) )
) )
......
...@@ -14,6 +14,7 @@ import com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyc ...@@ -14,6 +14,7 @@ import com.biganto.visual.roompark.presentation.screen.settings.util.CommonRecyc
import com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder import com.biganto.visual.roompark.presentation.screen.settings.util.CommonViewHolder
import com.biganto.visual.roompark.util.extensions.setGone import com.biganto.visual.roompark.util.extensions.setGone
import com.biganto.visual.roompark.util.extensions.startUrl import com.biganto.visual.roompark.util.extensions.startUrl
import com.google.android.material.textview.MaterialTextView
import com.jakewharton.rxbinding3.view.clicks import com.jakewharton.rxbinding3.view.clicks
import io.reactivex.Observable import io.reactivex.Observable
import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.PublishSubject
...@@ -39,6 +40,9 @@ class FavoritesListAdapter : CommonRecyclerAdapter<FavoriteViewHolder,EstateMode ...@@ -39,6 +40,9 @@ class FavoritesListAdapter : CommonRecyclerAdapter<FavoriteViewHolder,EstateMode
class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemView) { class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemView) {
@BindView(R.id.avaliable_text) lateinit var availableText: MaterialTextView
@BindView(R.id.avaliable_status) lateinit var availableStatus:View
@BindView(R.id.object_card_title) lateinit var estateTitle: TextView @BindView(R.id.object_card_title) lateinit var estateTitle: TextView
@BindView(R.id.common_info_block) lateinit var commonInfo:View @BindView(R.id.common_info_block) lateinit var commonInfo:View
@BindView(R.id.start_tour_button) lateinit var startTour:View @BindView(R.id.start_tour_button) lateinit var startTour:View
...@@ -62,7 +66,8 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie ...@@ -62,7 +66,8 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie
ButterKnife.bind(this, itemView) ButterKnife.bind(this, itemView)
} }
val onStartTourObs: Observable<EstateModel> get() = startTour.clicks().map { bindedModel } val onStartTourObs: Observable<EstateModel> get() =
startTour.clicks().filter { bindedModel.availableStatus }.map { bindedModel }
override fun onViewBound(model: EstateModel) { override fun onViewBound(model: EstateModel) {
estateTitle.text = estateTitle.text =
...@@ -74,6 +79,13 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie ...@@ -74,6 +79,13 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie
startTour.setGone(model.multitourId == null) startTour.setGone(model.multitourId == null)
availableStatus.isEnabled = model.availableStatus
availableText.text = itemView.resources.getString(
if (model.availableStatus) R.string.estate_avalibale
else R.string.estate_sold_out
)
siteLink.setGone(model.url == null) siteLink.setGone(model.url == null)
siteLinkDivider.setGone(model.url == null) siteLinkDivider.setGone(model.url == null)
model.url?.let {url -> model.url?.let {url ->
...@@ -97,11 +109,11 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie ...@@ -97,11 +109,11 @@ class FavoriteViewHolder(itemView: View) : CommonViewHolder<EstateModel>(itemVie
if (info.area == null) info1.visibility = View.GONE if (info.area == null) info1.visibility = View.GONE
else { info4.title().text = "Общая, м²"; info4.text().text = info.area.toString()} else { info4.title().text = "Общая, м²"; info4.text().text = info.area.toString()}
if (info.price_meter == null) info1.visibility = View.GONE if (info.price_meter == null && !bindedModel.availableStatus) info1.visibility = View.GONE
else { info5.title().text = "Цена за м²"; info5.text().text = info.price_meter.toRubles()} else { info5.title().text = "Цена за м²"; info5.text().text = info.price_meter?.toRubles()}
if (info.price == null) info1.visibility = View.GONE if (info.price == null && !bindedModel.availableStatus) info1.visibility = View.GONE
else { info6.title().text = "Стоимость"; info6.text().text = info.price.toRubles()} else { info6.title().text = "Стоимость"; info6.text().text = info.price?.toRubles()}
if (true) info7.visibility = View.GONE if (true) info7.visibility = View.GONE
else { info7.title().text = "вщщ"; info7.text().text = info.building.toString()} else { info7.title().text = "вщщ"; info7.text().text = info.building.toString()}
......
...@@ -18,17 +18,16 @@ ...@@ -18,17 +18,16 @@
android:padding="16dp"> android:padding="16dp">
<FrameLayout <FrameLayout
android:id="@+id/feed_read" android:id="@+id/avaliable_status"
android:layout_width="12dp" android:layout_width="12dp"
android:layout_height="12dp" android:layout_height="12dp"
android:background="@drawable/new_feed_icon" android:background="@drawable/available_status"
android:backgroundTint="@color/colorAccent"
android:visibility="visible" android:visibility="visible"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<TextView <com.google.android.material.textview.MaterialTextView
android:id="@+id/feed_date_text_view3" android:id="@+id/avaliable_text"
style="@style/LiteText.Accent" style="@style/LiteText.Accent"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
...@@ -38,7 +37,7 @@ ...@@ -38,7 +37,7 @@
android:visibility="visible" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="@+id/feed_read" app:layout_constraintBottom_toBottomOf="@+id/feed_read"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/feed_read" app:layout_constraintStart_toEndOf="@+id/avaliable_status"
app:layout_constraintTop_toTopOf="@+id/feed_read" /> app:layout_constraintTop_toTopOf="@+id/feed_read" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
...@@ -50,7 +49,7 @@ ...@@ -50,7 +49,7 @@
android:text="\n" android:text="\n"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/feed_date_text_view3" /> app:layout_constraintTop_toBottomOf="@+id/avaliable_text" />
<include <include
android:id="@+id/header_divider" android:id="@+id/header_divider"
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:background="@drawable/available_status" android:background="@drawable/available_status"
android:fitsSystemWindows="true"
android:visibility="visible" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
...@@ -27,9 +26,8 @@ ...@@ -27,9 +26,8 @@
style="@style/Accent_Minor_TextView" style="@style/Accent_Minor_TextView"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="4dp"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:fitsSystemWindows="true"
android:text="СВОБОДНА"
app:layout_constraintBottom_toBottomOf="@+id/status_icon" app:layout_constraintBottom_toBottomOf="@+id/status_icon"
app:layout_constraintStart_toEndOf="@+id/status_icon" app:layout_constraintStart_toEndOf="@+id/status_icon"
app:layout_constraintTop_toTopOf="@+id/status_icon" /> app:layout_constraintTop_toTopOf="@+id/status_icon" />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment