Commit f85ff40b authored by Vladislav Bogdashkin's avatar Vladislav Bogdashkin 🎣

Merge branch 'feature/minor_ui_fixes' into develop

parents 56ddc3d9 463ed781
package com.biganto.visual.roompark.conductor.dialogs.tour_chooser
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import androidx.annotation.LayoutRes
import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.base.BaseRoomParkActivity
import com.biganto.visual.roompark.base.RoomParkApplication
import com.biganto.visual.roompark.base.RoomParkMainActivity
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.di.dagger.ActivityModule
import com.biganto.visual.roompark.di.dagger.AppComponent
import com.biganto.visual.roompark.di.dagger.PerScreen
import com.biganto.visual.roompark.domain.interactor.SettingsInteractor
import com.biganto.visual.roompark.domain.model.bytesToSize
import com.biganto.visual.roompark.util.view_utils.snackbar.ISnackBarProvider
import com.bluelinelabs.conductor.Controller
import com.google.android.material.textview.MaterialTextView
import com.jakewharton.rxbinding3.view.clicks
import dagger.Binds
import dagger.BindsInstance
import dagger.Component
import dagger.Module
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.util.concurrent.TimeUnit
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 09.04.2019.
*/
private const val TOTAL_SIZE_DOWNLOAD_KEY = "TOURS_TO_DOWNLOAD_OVERALL_SIZE"
class StartToursDownloadingDialogController : Controller {
constructor(args: Bundle) : super(args)
constructor(size:Long) : super( Bundle().apply { putLong(TOTAL_SIZE_DOWNLOAD_KEY,size) } )
private val detachDisposable = CompositeDisposable()
override fun onDetach(view: View) {
detachDisposable.clear()
super.onDetach(view)
}
@Inject
lateinit var downloader: SettingsInteractor
@Inject
lateinit var file: FileModule
lateinit var snackbar: ISnackBarProvider
@Inject
lateinit var rpActivity: RoomParkMainActivity
override fun onContextAvailable(context: Context) {
super.onContextAvailable(context)
DaggerStartToursDownloadingDialogScreenComponent.factory()
.create(RoomParkApplication.component,activity as RoomParkMainActivity)
.inject(this)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(getLayoutId(), container, false)
snackbar = ActivityModule.provideSnackBar(rpActivity)
args.getLong(TOTAL_SIZE_DOWNLOAD_KEY).let {
view.findViewById<MaterialTextView>(R.id.all_tours_size_textView)
.text = resources?.getString(R.string.download_all_tours_size_title,it.bytesToSize())
}
file.freeSpace.bytesToSize().let {
view.findViewById<MaterialTextView>(R.id.disk_size_textView)
.text = resources?.getString(R.string.download_all_tours_disk_size_title,it)
}
view.findViewById<Button>(R.id.alert_dismiss_button)
.setOnClickListener { handleBack() }
view.findViewById<ImageView>(R.id.close_current_button)
.setOnClickListener { handleBack() }
detachDisposable.add(
view.findViewById<Button>(R.id.alert_ok_button)
.clicks()
.debounce(200, TimeUnit.MILLISECONDS)
.observeOn(
Schedulers.io())
.flatMap{ downloader.startToursDownloading()
// .subscribeOn(Schedulers.computation())
.doOnComplete { Timber.d(" C ") }
}
.doOnComplete { Timber.d(" X ") }
// .subscribeOn(AndroidSchedulers.mainThread())
.doOnComplete { Timber.d(" Xss ") }
.observeOn(AndroidSchedulers.mainThread())
.subscribe ({
Timber.d(" SUBSCRIBER ")
snackbar.showSnackBar(R.string.download_all_tours_start_snackbar_message)
handleBack()
},{
Timber.e(it)
snackbar.showSnackBar(R.string.download_all_tours_errors_snackbar_message)
handleBack()
}
)
)
view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
// view.setOnClickListener { handleBack() }
return view
}
@LayoutRes
fun getLayoutId() = R.layout.tours_download_dialog_screen
override fun handleBack(): Boolean {
return router.popCurrentController()
}
}
@PerScreen
@Component(
modules = [StartToursDownloadingDialogScreenModule::class],
dependencies = [AppComponent::class])
interface StartToursDownloadingDialogScreenComponent {
@Component.Factory
interface Factory{
fun create(
appComponent: AppComponent
,@BindsInstance activity: RoomParkMainActivity
): StartToursDownloadingDialogScreenComponent
}
fun inject(controller: StartToursDownloadingDialogController)
}
@Module
abstract class StartToursDownloadingDialogScreenModule{
@PerScreen
@Binds
abstract fun provideActivity(activity: RoomParkMainActivity): BaseRoomParkActivity
}
......@@ -80,7 +80,7 @@ class ChooseTourDialogController : Controller {
.subscribe(::onTourClicked)
)
view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
// view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
view.setOnClickListener { handleBack() }
return view
......
......@@ -6,6 +6,7 @@ import com.biganto.visual.roompark.data.repository.api.room_park.IRoomParkApi
import com.biganto.visual.roompark.data.repository.db.IDb
import com.biganto.visual.roompark.data.repository.db.requrey.model.DealEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.UserEntity
import com.biganto.visual.roompark.data.repository.mapper.fromRaw
import com.biganto.visual.roompark.data.repository.mapper.fromRawList
import com.biganto.visual.roompark.domain.contract.DealContract
......@@ -38,6 +39,27 @@ class EstateRepository @Inject constructor(
Timber.d("Estate Repository Created $this")
}
override fun fetchFavorites(user:UserEntity): Observable<Iterable<EstateEntity>> =
api.getFavorites(user.authToken)
.doOnError(Timber::e)
.map { fromRawList(it, ::fromRaw) }
.doOnNext {
it.forEach { estate ->
estate.setFavorite(true)
estate.user = user
}
}
.flatMap(db::upsertEstates)
.doOnNext{ db.refreshUser(user) }
override fun fetchDeals(user:UserEntity): Observable<List<EstateEntity>> =
api.getDeals(TEST_DEAL_TOKEN)//api.getDeals(user.authToken)
.doOnError(Timber::e)
.map { List(it.size){index -> fromRaw(it[index],user)} }
.flatMap(db::upsertDeals)
.map { it.map {deal -> deal.estate as EstateEntity } }
.doOnNext { db.refreshUser(user) }
private val getFavoritesApi: Observable<List<EstateEntity>> =
local.recentUser()
.flatMap {
......
......@@ -12,6 +12,7 @@ import com.biganto.visual.roompark.domain.contract.FlatPlanContract
import com.biganto.visual.roompark.domain.model.FeatureModel
import com.biganto.visual.roompark.domain.model.PlanPresetModel
import com.biganto.visual.roompark.domain.model.fromEntity
import com.biganto.visual.roompark.domain.use_case.DownloadUseCase
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
......@@ -47,6 +48,55 @@ class PlanRepository @Inject constructor(
.subscribeOn(Schedulers.io())
override fun getPlansObservable(list:List<PlanFeaturesVariant>
,cancellationToken: DownloadUseCase.CancellationToken)
: Observable<String> {
return Observable.create { emitter ->
list
.asSequence()
.chunked(12)
.also { System.gc() }
.flatten()
.filter { !cancellationToken.isCancelled }
.forEach { variant->
val file = FileModule.getDirectory(
file.context
, FileModule.FileDirectory.PlanTypeDir(
estateId = variant.estateId,
planId = variant.planId,
furniture = variant.furniture,
walls = variant.walls,
sizes = variant.sizes,
electric = variant.electric
))
if (file.exists())
emitter.onNext(file.absolutePath)
else{
try {
Timber.w("Cancellation is: ${cancellationToken.isCancelled}")
if (cancellationToken.isCancelled){
emitter.onComplete()
}
file.parentFile.mkdirs()
file.writeText(
api.getDirectPlan(variant.estateId, variant.planId,
variant.furniture?:false
,variant.sizes?:false
,variant.walls?:false
,variant.electric?:false).blockingFirst()
)
emitter.onNext(file.absolutePath)
}
catch (e:Throwable){emitter.onError(e)}
}
}
emitter.onComplete()
}
}
override fun getPlanTypes(estateId: Int): Observable<List<PlanPresetModel>> =
Observable.mergeDelayError(
arrayListOf(getPlanTypesApi(estateId))
......@@ -64,16 +114,17 @@ class PlanRepository @Inject constructor(
,sizes?:false
,walls?:false
,electric?:false)
.map{
.map {
val sFile = getPlanFile(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric)
file.saveFileToDisk(sFile,it)
sFile.path
electric = electric
)
file.saveFileToDisk(sFile, it)
sFile.absolutePath
}
.subscribeOn(Schedulers.io())
......@@ -88,7 +139,7 @@ class PlanRepository @Inject constructor(
electric = featuresVariant.electric
)
fun getPlanFile(estateId: Int
private fun getPlanFile(estateId: Int
, planId:Int
, furniture:Boolean? = null
, sizes:Boolean? = null
......@@ -133,7 +184,7 @@ class PlanRepository @Inject constructor(
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric) }.switchMap {
electric = electric) }.flatMap {
if (it.exists()) Observable.just(it.path)
else getPlanApi(estateId
,planId
......
......@@ -75,4 +75,6 @@ interface IDb {
fun refreshUser(userEntity: UserEntity): Observable<UserEntity>
fun refreshEntities(entities: List<Persistable>): Observable<Iterable<Persistable>>
fun refreshEstatesWithTours(): Completable
fun upsertEstates(entity: List<EstateEntity>): Observable<Iterable<EstateEntity>>?
fun upsertDeals(entity: List<DealEntity>): Observable<Iterable<DealEntity>>
}
\ No newline at end of file
......@@ -90,6 +90,12 @@ class RequeryRepository @Inject constructor(
override fun <T : List<Persistable>> blockingUpsert(entity: T) =
store.upsert(entity).toObservable().blockingSubscribe()
override fun upsertDeals(entity:List<DealEntity>): Observable<Iterable<DealEntity>> =
store.upsert(entity).toObservable()
override fun upsertEstates(entity:List<EstateEntity>): Observable<Iterable<EstateEntity>> =
store.upsert(entity).toObservable()
override fun upsertEstate(entity:EstateEntity) =
store.upsert(entity).toObservable().blockingSubscribe()
......
......@@ -8,6 +8,7 @@ import com.google.gson.JsonElement
import dagger.Module
import io.reactivex.Observable
import kotlinx.io.IOException
import okio.Okio
import timber.log.Timber
import java.io.File
import javax.inject.Inject
......@@ -58,6 +59,31 @@ class FileModule @Inject constructor(val context: Application) {
file.writeText("[$jsonElement]") //to json array because core unity method parse data like TourData[] Estate[] etc..
}
fun saveFileToDiskObservable(file:File,content: String):Observable<Long> {
file.parentFile.mkdirs()
return Observable.create { emitter ->
val fileStorage = file
val sink = Okio.buffer(Okio.sink(fileStorage))
val buffer = sink.buffer()
var read = 0L
val step = 8192
val source =
content.byteInputStream()
var bytesRead = 0L
Timber.w("start read ")
file.writeText(content)
Timber.w("butes read ")
// sink.flush()
System.gc()
emitter.onNext(bytesRead)
// emitter.onComplete()
}
}
fun saveFileToDisk(file:File,content: String){
Timber.d("write to : $file")
// file.createNewFile()
......@@ -90,11 +116,12 @@ class FileModule @Inject constructor(val context: Application) {
}
val getCoreCacheDirectory:String
get(){
return rootFolder.absolutePath
}
val freeSpace = rootFolder.freeSpace
companion object {
fun getDirectory(context: Context, dirType: FileDirectory): File =
File(context.filesDir.absolutePath.plus(dirType.dir))
......
package com.biganto.visual.roompark.domain.contract
import com.biganto.visual.roompark.data.repository.db.requrey.model.DealEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.UserEntity
import com.biganto.visual.roompark.domain.model.DealModel
import com.biganto.visual.roompark.domain.model.EstateModel
import io.reactivex.Completable
......@@ -17,4 +20,6 @@ interface DealContract{
fun getDeals(): Observable<List<DealModel>>
fun fetchEstate(building: Int, number: Int): Observable<EstateModel>
fun setDealRead(dealId: String): Completable
fun fetchDeals(user: UserEntity): Observable<List<EstateEntity>>
fun fetchFavorites(user: UserEntity): Observable<Iterable<EstateEntity>>
}
\ No newline at end of file
......@@ -2,6 +2,7 @@ package com.biganto.visual.roompark.domain.contract
import com.biganto.visual.roompark.data.data_provider.PlanFeaturesVariant
import com.biganto.visual.roompark.domain.model.PlanPresetModel
import com.biganto.visual.roompark.domain.use_case.DownloadUseCase
import io.reactivex.Observable
import java.io.File
......@@ -22,4 +23,8 @@ interface FlatPlanContract{
fun getPlanFile(featuresVariant: PlanFeaturesVariant): File
fun getPlan(featuresVariant: PlanFeaturesVariant): Observable<String>
fun getPlansObservable(
list: List<PlanFeaturesVariant>,
cancellationToken: DownloadUseCase.CancellationToken
): Observable<String>
}
\ No newline at end of file
......@@ -67,14 +67,19 @@ class SettingsInteractor @Inject constructor(
}
}
fun startToursDownloading(): Completable =
fun startToursDownloading() =
toursUc.downloadAllDeelsAndEstates()
.doOnNext { Timber.d(" gonna startService") }
.doOnNext { this.startDownloadService() }
.delay(100,TimeUnit.MILLISECONDS)
.doOnNext { Timber.d(" gonna startServic222e") }
.doOnNext { tours ->
startDownloadService(tours.map { tour -> tour.id })
}.ignoreElements()
}
.doOnNext { Timber.d(" gonna startServsdfsfdsice") }
// .doOnComplete { Timber.w(" azzaza complete") }
fun getSubscriptions() =
......
package com.biganto.visual.roompark.domain.use_case
import com.biganto.visual.roompark.data.data_provider.PlanFeaturesVariant
import com.biganto.visual.roompark.data.data_provider.featuresVariants
import com.biganto.visual.roompark.data.repository.db.requrey.model.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.UserEntity
import com.biganto.visual.roompark.domain.contract.AuthContract
import com.biganto.visual.roompark.domain.contract.DealContract
import com.biganto.visual.roompark.domain.contract.FlatPlanContract
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import io.reactivex.rxkotlin.Observables
import javax.inject.Inject
/**
......@@ -15,20 +16,30 @@ import javax.inject.Inject
class PlanTypesUseCase @Inject constructor(
private val planContract: FlatPlanContract,
private val auth:AuthContract
private val auth:AuthContract,
private val dealContract: DealContract
) {
private fun fetchUserEstates(user:UserEntity): Observable<List<EstateEntity>> =
Observables.zip(dealContract.fetchDeals(user),dealContract.fetchFavorites(user))
{t1,t2 -> t1+t2}
private val fetchAllPlanTypes =
auth.currentUser()
.map { user ->
val list =
user.deals?.map { it.estate as EstateEntity }?.toMutableList()
?: mutableListOf()
list.addAll(user.estates?.map { it as EstateEntity } ?: arrayListOf())
list
.flatMap {user ->
fetchUserEstates(user)
.onErrorReturn { arrayListOf() }
.map { apiList ->
val list =
user.deals?.map { it.estate as EstateEntity }?.toMutableList()
?: mutableListOf()
list.addAll(user.estates?.map { it as EstateEntity } ?: arrayListOf())
(list+apiList).distinctBy { it.id }
}
}
fun fetchNotDownloadedPlansSizes(): Observable<Int> =
fetchAllPlanTypes
.flatMapIterable { it }
......@@ -39,8 +50,9 @@ class PlanTypesUseCase @Inject constructor(
.map { list -> list.sumBy { if (planContract.getPlanFile(it).exists()) 0 else 1 } }
.scan { t1: Int, t2: Int -> t1 + t2 }
fun downloadAllPlanTypes(cancellationToken: DownloadUseCase.CancellationToken) =
fetchAllPlanTypes
fun downloadAllPlanTypes(cancellationToken: DownloadUseCase.CancellationToken): Observable<DownloadProgress> {
var listSize = 0
return fetchAllPlanTypes
.flatMapSingle {
Observable.fromIterable(it)
.flatMap { estateEntity ->
......@@ -51,29 +63,38 @@ class PlanTypesUseCase @Inject constructor(
}
.map { it.flatten() }
.filter { !cancellationToken.isCancelled }
.flatMap { downloadPlan(it, cancellationToken) }
private fun downloadPlan(
list: List<PlanFeaturesVariant>
, cancellationToken: DownloadUseCase.CancellationToken
)
: Observable<DownloadProgress> {
var completedThreads = 0
return Observable.fromIterable(list)
.filter { !cancellationToken.isCancelled }
.flatMap {
planContract.getPlan(it)
.subscribeOn(Schedulers.io())
.map {
completedThreads++
DownloadProgress(completedThreads, list.size)
.flatMap { list ->
planContract.getPlansObservable(list,cancellationToken)
.map { 1 }
.scan(0,
{ t1, t2 -> t1 + t2 })
.map { completed ->
DownloadProgress(completed, list.size)
}
}
}
}
// private fun downloadPlan(
// list: PlanFeaturesVariant
// , cancellationToken: DownloadUseCase.CancellationToken
// )
// : Observable<DownloadProgress> {
//
// val avaliablethread = true
//
// return Observable.fromIterable(list)
//
//
// .delay(100,TimeUnit.MILLISECONDS)
// .doOnNext { Timber.w("emmited") }
// .delay { variant ->
// planContract.getPlan(variant)}
// .filter { !cancellationToken.isCancelled }
//
// }
......
package com.biganto.visual.roompark.presentation.screen.estate
import android.annotation.SuppressLint
import android.net.Uri
import android.os.Bundle
import android.view.View
......@@ -262,6 +263,7 @@ class EstateScreenController :
is EstateScreenViewState.SomeError -> render(viewState)
is EstateScreenViewState.ShowEstateInfo -> render(viewState)
is EstateScreenViewState.ToursLoaded -> render(viewState)
is EstateScreenViewState.RestoreView -> render(viewState)
}
}
......@@ -277,40 +279,12 @@ class EstateScreenController :
private var estateModel : EstateModel? = null
private fun render(viewState: EstateScreenViewState.LoadEstate) {
estateModel = viewState.estate
toolBar.setToolbar(
null, StatusToolbarModel(StatusState.AVAILABLE,null, null)
)
flatTitle.text = resources?.getString(viewState.estate.type.typeShortString()
,viewState.estate.number)
setEstateInfo(viewState.estate)
}
siteLink.setGone(viewState.estate.url == null)
viewState.estate.url?.let {url ->
siteLink.setOnClickListener{
activity?.startUrl(url)
}
}
startTour.setGone(viewState.estate.multitourId == null)
startTourDivider.setGone(viewState.estate.multitourId == null)
viewState.estate.multitourPreview?.let {
Glide.with(tourScreen)
.load(it)
.into(tourScreen)
}
when(viewState.estate.type){
FlatType.FLAT -> {
flatTypeView.setGone(false)
infoTabDivicder.setGone(false)
explicationTab.setGone(false)
}
else -> {
flatTypeView.setGone(true)
infoTabDivicder.setGone(true)
explicationTab.setGone(true)
}
}
private fun render(viewState: EstateScreenViewState.RestoreView) {
setEstateInfo(viewState.restore.estate)
}
......@@ -395,6 +369,7 @@ class EstateScreenController :
}
@SuppressLint("SetJavaScriptEnabled")
private fun render(viewState: EstateScreenViewState.LoadPlan) {
planWebView.settings.javaScriptEnabled = true
planWebView.clearCache(true)
......@@ -402,11 +377,51 @@ class EstateScreenController :
planWebView.loadUrl(uri)
}
private fun setEstateInfo(estateModel: EstateModel?){
toolBar.setToolbar(
null, StatusToolbarModel(StatusState.AVAILABLE,null, null)
)
estateModel?.let {estate ->
flatTitle.text = resources?.getString(estate.type.typeShortString()
,estate.number)
}
siteLink.setGone(estateModel?.url == null)
estateModel?.url?.let {url ->
siteLink.setOnClickListener{
activity?.startUrl(url)
}
}
startTour.setGone(estateModel?.multitourId == null)
startTourDivider.setGone(estateModel?.multitourId == null)
estateModel?.multitourPreview?.let {
Glide.with(tourScreen)
.load(it)
.into(tourScreen)
}
when(estateModel?.type){
FlatType.FLAT -> {
flatTypeView.setGone(false)
infoTabDivicder.setGone(false)
explicationTab.setGone(false)
}
else -> {
flatTypeView.setGone(true)
infoTabDivicder.setGone(true)
explicationTab.setGone(true)
}
}
}
private fun getComponent() = DaggerEstateScreenComponent.factory()
.create(RoomParkApplication.component,activity as RoomParkMainActivity
,args.getInt(SELECTED_ESTATE_ID_KEY))
.inject(this)
override fun getLayoutId(): Int = R.layout.flat_full_card_screen
......
......@@ -30,11 +30,6 @@ class EstateScreenPresenter @Inject constructor(
)
: BigantoBasePresenter<EstateScreen, EstateScreenViewState>() {
private var planList: List<PlanPresetModel>? = null
private var estate: EstateModel? = null
private var showType: InfoShowType = InfoShowType.COMMON_INFO
override fun defaultErrorViewStateHandler() =
{ e: ExceptionString -> EstateScreenViewState.SomeError(e) }
......@@ -43,18 +38,26 @@ class EstateScreenPresenter @Inject constructor(
interactor.getPlan(plan)
.map<EstateScreenViewState> { EstateScreenViewState.LoadPlan(it) }
private var restoreModel = RestoreModel(null,null)
override fun detachView() {
super.detachView()
restoreStateObservable.accept(EstateScreenViewState.RestoreView(restoreModel))
}
override fun bindIntents() {
val prefetchCards = interactor.getEstate(estateId)
.doOnNext { estate = it.copy() }
.doOnNext { restoreModel.estate = it.copy() }
.map { EstateScreenViewState.LoadEstate(it) }
val fetchPlans = interactor.getPlanTypes(estateId)
.doOnNext { planList = it.toList() }
.doOnNext {restoreModel.planList = it.toList() }
.map { EstateScreenViewState.LoadPlanTypes(it) }
val fetchPlan = intent(EstateScreen::planTypesTabSelected)
.map { planList?.get(it) }
.map { restoreModel.planList?.get(it) }
.flatMap { planPreset ->
interactor.getPlan(planPreset)
.map<EstateScreenViewState> { plan -> EstateScreenViewState.LoadPlan(plan) }
......@@ -67,9 +70,9 @@ class EstateScreenPresenter @Inject constructor(
Observable.just<EstateScreenViewState>(
EstateScreenViewState.ShowEstateInfo(
showType
, if (showType == InfoShowType.COMMON_INFO)
mapCommonInfo(estate?.commonInfo)
restoreModel.showType
, if (restoreModel.showType == InfoShowType.COMMON_INFO)
mapCommonInfo(restoreModel.estate?.commonInfo)
else mapCommonInfo(planPreset.explication)
)
)
......@@ -78,48 +81,48 @@ class EstateScreenPresenter @Inject constructor(
val switchSizes = intent(EstateScreen::switchSizes)
.map { pair ->
val plan = planList?.first { it.planId == pair.first }
val plan = restoreModel.planList?.first { it.planId == pair.first }
plan?.switchFeature<FeatureModel.Sizes>(pair.second)
plan
}.flatMap(::getPlan)
val switchFurn = intent(EstateScreen::switchFurniture)
.map { pair ->
val plan = planList?.first { it.planId == pair.first }
val plan = restoreModel.planList?.first { it.planId == pair.first }
plan?.switchFeature<FeatureModel.Furniture>(pair.second)
plan
}.flatMap(::getPlan)
val switchWalls = intent(EstateScreen::switchWalls)
.map { pair ->
val plan = planList?.first { it.planId == pair.first }
val plan = restoreModel.planList?.first { it.planId == pair.first }
plan?.switchFeature<FeatureModel.Walls>(pair.second)
plan
}.flatMap(::getPlan)
val switchElectric = intent(EstateScreen::switchElectric)
.map { pair ->
val plan = planList?.first { it.planId == pair.first }
val plan = restoreModel.planList?.first { it.planId == pair.first }
plan?.switchFeature<FeatureModel.Electric>(pair.second)
plan
}.flatMap(::getPlan)
val showInfo = intent(EstateScreen::showCommonInfo)
.doOnNext { showType = InfoShowType.COMMON_INFO }
.map { estate?.commonInfo }
.doOnNext { restoreModel.showType = InfoShowType.COMMON_INFO }
.map { restoreModel.estate?.commonInfo }
.map(::mapCommonInfo)
.map { EstateScreenViewState.ShowEstateInfo(showType, it) }
.map { EstateScreenViewState.ShowEstateInfo(restoreModel.showType, it) }
val showExplication = intent(EstateScreen::showExplication)
.doOnNext { showType = InfoShowType.EXPLICATIONS }
.map { planList?.get(it)?.explication }
.doOnNext { restoreModel.showType = InfoShowType.EXPLICATIONS }
.map { restoreModel.planList?.get(it)?.explication }
.map(::mapCommonInfo)
.map { EstateScreenViewState.ShowEstateInfo(showType, it) }
.map { EstateScreenViewState.ShowEstateInfo(restoreModel.showType, it) }
val onStartTours = intent(EstateScreen::tourCardClicked)
.map { estate }
.map { restoreModel.estate }
.flatMap {estate -> toursInteractor.getEstateTourList(estate)
.map { EstateScreenViewState.ToursLoaded(it) }
}
......@@ -202,3 +205,8 @@ enum class InfoShowType{
COMMON_INFO,
EXPLICATIONS
}
data class RestoreModel(var planList: List<PlanPresetModel>? = null,
var estate: EstateModel? = null,
var showType: InfoShowType = InfoShowType.COMMON_INFO)
\ No newline at end of file
......@@ -21,4 +21,5 @@ sealed class EstateScreenViewState : BigantoBaseViewState() {
class SomeError(val exception: ExceptionString) : EstateScreenViewState()
class ShowEstateInfo(val showType: InfoShowType, val info:List<DisplayInfoModel>) : EstateScreenViewState()
class ToursLoaded(val tours:List<TourModel>) : EstateScreenViewState()
class RestoreView(val restore:RestoreModel) : EstateScreenViewState()
}
\ No newline at end of file
......@@ -9,7 +9,7 @@ import io.reactivex.Observable
*/
interface SettingsScreen : BigantoBaseContract<SettingsScreenViewState> {
fun downloadAllTours(): Observable<Int>
// fun downloadAllTours(): Observable<Int>
fun signOut(): Observable<Int>
fun clearCache(): Observable<Int>
fun refreshCacheInfo(): Observable<Int>
......
......@@ -15,6 +15,7 @@ import com.biganto.visual.roompark.base.RoomParkMainActivity
import com.biganto.visual.roompark.conductor.BigantoBaseController
import com.biganto.visual.roompark.conductor.dialogs.DownloadPlansDialogController
import com.biganto.visual.roompark.conductor.dialogs.change_handler.DialogChangeHandler
import com.biganto.visual.roompark.conductor.dialogs.tour_chooser.StartToursDownloadingDialogController
import com.biganto.visual.roompark.domain.model.SubscriptionModel
import com.biganto.visual.roompark.presentation.screen.settings.util.CahcedListAdapter
import com.biganto.visual.roompark.presentation.screen.settings.util.PushListAdapter
......@@ -54,8 +55,9 @@ class SettingsScreenController :
.map { Timber.d("Clicked clear cache button"); 1 }
.observeOn(AndroidSchedulers.mainThread())
override fun downloadAllTours(): Observable<Int> =
toursDownloaderButton.clicks().map { 1 }.observeOn(AndroidSchedulers.mainThread())
// override fun downloadAllTours(): Observable<Int> =
// toursDownloaderButton.clicks().filter { false }
// .map { 1 }.observeOn(AndroidSchedulers.mainThread())
private val refreshEmitter = BehaviorRelay.create<Int>()
......@@ -128,6 +130,16 @@ class SettingsScreenController :
)
}
@OnClick(R.id.downloadToursIcon)
fun startDownloadingDialog(){
router.pushController(RouterTransaction.with(StartToursDownloadingDialogController(tempToursSize))
.pushChangeHandler(DialogChangeHandler())
.popChangeHandler(DialogChangeHandler())
)
}
private var tempToursSize = 0L
private fun bindRecycler(){
pushRecycler.isNestedScrollingEnabled = true
pushRecycler.layoutManager =
......@@ -184,6 +196,7 @@ class SettingsScreenController :
}
private fun render(viewState: SettingsScreenViewState.OnSizePrefetch) {
tempToursSize = viewState.size
toursDownloaderTitle.text =
resources?.getString(
R.string.download_all_tours_settings_with_size
......
......@@ -7,6 +7,7 @@ import com.biganto.visual.roompark.domain.model.CachedDataModel
import com.biganto.visual.roompark.domain.model.SubscriptionModel
import com.biganto.visual.roompark.domain.model.TitledSubscriptionModel
import com.biganto.visual.roompark.util.monades.ExceptionString
import com.jakewharton.rxrelay2.PublishRelay
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
......@@ -18,6 +19,7 @@ import javax.inject.Inject
* Created by Vladislav Bogdashkin on 30.09.2019.
*/
private const val TYPICAL_PLAN_SIZE = (1.2f*1024L*1024L).toLong()
class SettingsScreenPresenter @Inject constructor(
private val interactor: SettingsInteractor,
......@@ -36,19 +38,31 @@ class SettingsScreenPresenter @Inject constructor(
override fun defaultErrorViewStateHandler() =
{ e: ExceptionString -> SettingsScreenViewState.SomeError(e) }
override fun bindIntents() {
private val cacheSizeRefresher = PublishRelay.create<Int>()
val fetchToursSize = interactor.fetchToursSizes()
.map { SettingsScreenViewState.OnSizePrefetch(it) }
private val cahcObs =
cacheSizeRefresher.flatMap {
Observable.merge(
arrayListOf(
fetchToursSize, fetchPlansSize
)
)
}
val fetchPlansSize = interactor.fetchPlanTypesSizes()
.map { it*1024L*1024L }
.map { SettingsScreenViewState.OnPlanTypesPrefetch(it) }
private val fetchToursSize: Observable<SettingsScreenViewState> = interactor.fetchToursSizes()
.map { SettingsScreenViewState.OnSizePrefetch(it) }
val onDownloadTours = intent(SettingsScreen::downloadAllTours)
.flatMap { interactor.startToursDownloading()
.andThen(Observable.just(SettingsScreenViewState.Idle()))
}
private val fetchPlansSize: Observable<SettingsScreenViewState> = interactor.fetchPlanTypesSizes()
.map { it* TYPICAL_PLAN_SIZE }
.map { SettingsScreenViewState.OnPlanTypesPrefetch(it) }
override fun bindIntents() {
// val onDownloadTours = intent(SettingsScreen::downloadAllTours)
// .flatMap { interactor.startToursDownloading()
// .andThen(Observable.just(SettingsScreenViewState.Idle()))
// }
val onSubChecked = intent(SettingsScreen::onSubscription)
.flatMap { sub ->
......@@ -87,6 +101,7 @@ class SettingsScreenPresenter @Inject constructor(
.doOnNext { cached -> cached.sortBy { it.id } }
.doOnNext { restoreModel.cacheInfo = it }
.map { SettingsScreenViewState.LoadCachInfo(it) }
.doOnNext {cacheSizeRefresher.accept(1) }
val fetchSubscriptions = interactor.getSubscriptions()
.doOnNext { restoreModel.subs = it.toMutableList() }
......@@ -108,28 +123,35 @@ class SettingsScreenPresenter @Inject constructor(
interactor.deleteCacheFiles()
.map<SettingsScreenViewState> {
Timber.d(" got progress: ${it.first} / ${it.second.toFloat()}")
if (it.first == it.second)
cacheSizeRefresher.accept(1)
SettingsScreenViewState.OnCacheDeleting(
it.first / it.second.toFloat()
)
}
.delay(600,TimeUnit.MILLISECONDS)
.startWith(SettingsScreenViewState.OnCacheDeleting(0f))
.doOnError { Timber.e(it) }
.subscribeOn(Schedulers.io())
}
val state = Observable.mergeDelayError(
arrayListOf(
restoreStateObservable,
fetchPlansSize,
cahcObs,
// fetchPlansSize,
fetchSettings,
onSignOut,
onClearCache,
refreshInfo,
fetchSubscriptions,
fetchCache,
onSubChecked,
onDownloadTours,
fetchToursSize
onSubChecked
// onDownloadTours,
// fetchToursSize
)
)
.doOnError { Timber.e(it) }
......
......@@ -126,6 +126,7 @@ class FindFlatScreenController :
is FindFlatScreenViewState.SomeError -> render(viewState)
is FindFlatScreenViewState.FlatFounded -> render(viewState)
is FindFlatScreenViewState.FlatNotFound -> render(viewState)
is FindFlatScreenViewState.FlatSold -> render(viewState)
is FindFlatScreenViewState.StartFlat -> render(viewState)
is FindFlatScreenViewState.RestoreView -> render(viewState)
}
......@@ -156,8 +157,14 @@ class FindFlatScreenController :
{findFlatButton.text = resources?.getString(it)},
{findFlatButton.text = it}
)
}
private fun render(viewState: FindFlatScreenViewState.FlatSold){
findFlatButton.isEnabled = false
viewState.exceptionString.selectHandler(
{findFlatButton.text = resources?.getString(it)},
{findFlatButton.text = it}
)
}
private fun render(viewState: FindFlatScreenViewState.StartFlat){
......
......@@ -37,6 +37,7 @@ class FindFlatScreenPresenter @Inject constructor(
override fun vsByCode(code: Int): (ExceptionString) -> FindFlatScreenViewState =
when (code) {
304 -> {message:ExceptionString ->FindFlatScreenViewState.FlatNotFound(message)}
307 -> {message:ExceptionString ->FindFlatScreenViewState.FlatSold(message)}
else -> super.vsByCode(code)
}
......
......@@ -13,6 +13,7 @@ sealed class FindFlatScreenViewState : BigantoBaseViewState() {
class RequstFlatProgress : FindFlatScreenViewState()
class FlatFounded : FindFlatScreenViewState()
class FlatNotFound(val exceptionString:ExceptionString) : FindFlatScreenViewState()
class FlatSold(val exceptionString:ExceptionString) : FindFlatScreenViewState()
class StartFlat(val esateId:Int) : FindFlatScreenViewState()
class SomeError(val exception: ExceptionString) : FindFlatScreenViewState()
class RestoreView(val restore:RestoreModel) : FindFlatScreenViewState()
......
......@@ -59,10 +59,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/cancelDownloadButton"
android:background="?attr/selectableItemBackgroundBorderless"
android:clickable="true"
android:focusable="true"
app:layout_constraintTop_toBottomOf="@+id/downloadProgress" android:layout_marginTop="16dp"
app:layout_constraintStart_toStartOf="parent" android:layout_marginStart="32dp"
app:layout_constraintEnd_toEndOf="parent" android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintVertical_bias="0.24000001" style="@style/CancelTextDownloader" android:padding="4dp"
app:layout_constraintVertical_bias="0.24000001" style="@style/CancelTextDownloader"
android:padding="8dp"
android:paddingStart="8dp" android:paddingEnd="8dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -5,8 +5,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/playTourCardOpacityLight"
android:backgroundTintMode="src_atop"
android:clickable="true"
android:focusableInTouchMode="true">
android:focusable="true">
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
......@@ -42,10 +43,9 @@
android:layout_alignParentEnd="true"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:clickable="true"
android:clickable="false"
android:contentDescription="@string/content_description_close"
android:focusable="true"
android:focusableInTouchMode="true"
android:focusable="false"
android:scaleType="fitXY"
android:src="@drawable/ic_close_circled"
app:layout_constraintEnd_toEndOf="parent"
......
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/playTourCardOpacityLight"
android:backgroundTintMode="src_atop"
android:clickable="true"
android:focusable="true">
<com.google.android.material.card.MaterialCardView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
app:cardElevation="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.32999998">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="8dp"
android:orientation="vertical">
<com.google.android.material.textview.MaterialTextView
style="@style/Default_TextView.Header_Text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="@string/download_all_tours_notice_text"
android:textAlignment="center" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/all_tours_size_textView"
style="@style/Default_TextView.Notice_Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:text="@string/download_all_tours_size_title" />
<com.google.android.material.textview.MaterialTextView
android:id="@+id/disk_size_textView"
style="@style/Default_TextView.Notice_Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="2dp"
android:text="@string/download_all_tours_disk_size_title" />
<LinearLayout
android:id="@+id/buttons_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="@+id/alert_ok_button"
style="@style/DefaultButton.DismissButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/download_all_tours_yes_action" />
<Button
android:id="@+id/alert_dismiss_button"
style="@style/DefaultButton.DismissButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/download_all_tours_cancel_action"
android:visibility="visible" />
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<ImageView
android:id="@+id/close_current_button"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
android:layout_marginTop="16dp"
android:layout_marginEnd="8dp"
android:clickable="false"
android:contentDescription="@string/content_description_close"
android:focusable="false"
android:scaleType="fitXY"
android:src="@drawable/ic_close_circled"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
......@@ -132,5 +132,12 @@
<string name="download_all_plan_types_settings_with_sizes">Скачать карточки моих квартир из избранного и сделок (%s)</string>
<string name="plan_types_download_completed">Загрузка планов завершена.</string>
<string name="download_plan_types_screen_title">Cкачиваются планировки</string>
<string name="download_all_tours_notice_text">Загрузить все туры?</string>
<string name="download_all_tours_size_title">Размер всех туров: %s</string>
<string name="download_all_tours_disk_size_title">Размер свободного места на диске: %s</string>
<string name="download_all_tours_yes_action">Скачать</string>
<string name="download_all_tours_cancel_action">Отмена</string>
<string name="download_all_tours_errors_snackbar_message">Ошибка при попытке загрузить туры!</string>
<string name="download_all_tours_start_snackbar_message">Загрузка туров началась!</string>
</resources>
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