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

Merge branch 'feature/plan_types_download' into develop

parents 5ee2709b b338b557
package com.biganto.visual.roompark.conductor.dialogs
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.ProgressBar
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.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.use_case.DownloadUseCase
import com.biganto.visual.roompark.util.view_utils.snackbar.ISnackBarProvider
import com.bluelinelabs.conductor.Controller
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.FitCenter
import com.google.android.material.textview.MaterialTextView
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 jp.wasabeef.glide.transformations.BlurTransformation
import jp.wasabeef.glide.transformations.ColorFilterTransformation
import timber.log.Timber
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 09.04.2019.
*/
class DownloadPlansDialogController : Controller {
constructor():super()
constructor(args: Bundle) : super(args)
lateinit var progressBarDownload: ProgressBar
lateinit var downloaderBg: ImageView
lateinit var downloadTourTitleText: MaterialTextView
lateinit var cancelDownloadText: MaterialTextView
lateinit var downloadingContentText: MaterialTextView
override fun onContextAvailable(context: Context) {
super.onContextAvailable(context)
DaggerPlansDownloaderScreenComponent.factory()
.create(RoomParkApplication.component,activity as RoomParkMainActivity)
.inject(this)
}
private var downloadToken = DownloadUseCase.CancellationToken(false)
@Inject
lateinit var downloader: SettingsInteractor
@Inject
lateinit var rpActivity: RoomParkMainActivity
lateinit var snackbar: ISnackBarProvider
private val disposables = CompositeDisposable()
override fun onDetach(view: View) {
disposables.clear()
super.onDetach(view)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View {
val view = inflater.inflate(getLayoutId(), container, false)
snackbar = ActivityModule.provideSnackBar(rpActivity)
progressBarDownload = view.findViewById(R.id.downloadProgress)
downloaderBg = view.findViewById(R.id.backgroundDownloader)
cancelDownloadText = view.findViewById(R.id.cancelDownloadButton)
downloadTourTitleText = view.findViewById(R.id.tourToDownloadTitle)
downloadingContentText = view.findViewById(R.id.downloadingTitle)
downloadingContentText.text = resources?.getString(R.string.download_plan_types_screen_title)
// progress.visibility = View.VISIBLE
downloadToken = DownloadUseCase.CancellationToken(false)
downloadTourTitleText.text = ""
Glide.with(view)
.load(R.drawable.flat_placeholder)
.transform(BlurTransformation(13, 4)
,ColorFilterTransformation(0x99000000.toInt())
,FitCenter())
.into(downloaderBg)
disposables.add(
downloader.downloadTourPlans(downloadToken)
// .onErrorReturn { parseError(it);TourPreviewEntity() }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe (
{ model ->
downloadTourTitleText.text = "${model.currentProgress}/${model.totalProgress}"
updateProgressBar(model.currentProgress, model.totalProgress)
if (model.currentProgress == model.totalProgress){
snackbar.showSnackBar(R.string.plan_types_download_completed)
handleBack()
}
}
,{error ->
Timber.e(error)
snackbar.showSnackBar(error.localizedMessage)
handleBack()
}
))
cancelDownloadText.setOnClickListener {handleBack() }
// downloadTour(it.tour.tour_id, downloadToken)
// view.findViewById<View>(R.id.close_current_button).setOnClickListener { handleBack() }
return view
}
private fun updateProgressBar(curr:Int, max:Int){
activity?.runOnUiThread {
progressBarDownload.max = max
progressBarDownload.progress = curr
}
}
@LayoutRes
fun getLayoutId() = R.layout.download_tour_layout
override fun handleBack(): Boolean {
downloadToken.isCancelled = true
return router.popController(this)
}
}
@PerScreen
@Component(
modules = [PlansDownloaderScreenModule::class],
dependencies = [AppComponent::class])
interface PlansDownloaderScreenComponent {
@Component.Factory
interface Factory{
fun create(
appComponent: AppComponent
,@BindsInstance activity: RoomParkMainActivity
): PlansDownloaderScreenComponent
}
//
// val presenter: ArticlesScreenPresenter
fun inject(controller: DownloadPlansDialogController)
}
@Module
abstract class PlansDownloaderScreenModule{
@PerScreen
@Binds
abstract fun provideActivity(activity: RoomParkMainActivity): BaseRoomParkActivity
}
...@@ -6,15 +6,12 @@ import com.biganto.visual.roompark.data.repository.api.room_park.IRoomParkApi ...@@ -6,15 +6,12 @@ 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.IDb
import com.biganto.visual.roompark.data.repository.db.requrey.model.DealEntity 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.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.PlanPresetEntity
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.repository.mapper.fromRaw import com.biganto.visual.roompark.data.repository.mapper.fromRaw
import com.biganto.visual.roompark.data.repository.mapper.fromRawList import com.biganto.visual.roompark.data.repository.mapper.fromRawList
import com.biganto.visual.roompark.domain.contract.DealContract import com.biganto.visual.roompark.domain.contract.DealContract
import com.biganto.visual.roompark.domain.custom_exception.CustomApiException import com.biganto.visual.roompark.domain.custom_exception.CustomApiException
import com.biganto.visual.roompark.domain.model.DealModel import com.biganto.visual.roompark.domain.model.DealModel
import com.biganto.visual.roompark.domain.model.EstateModel import com.biganto.visual.roompark.domain.model.EstateModel
import com.biganto.visual.roompark.domain.model.PlanPresetModel
import com.biganto.visual.roompark.domain.model.fromEntity import com.biganto.visual.roompark.domain.model.fromEntity
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Observable import io.reactivex.Observable
...@@ -31,10 +28,9 @@ const val TEST_DEAL_TOKEN = ...@@ -31,10 +28,9 @@ const val TEST_DEAL_TOKEN =
"183|PQZi0LmaYswPmFHcLb0pHITkg_7aJNC4x2IIC90kbRKE1GBt2m48tdi-1jb9jo9MYoxCGyvJtDy3ret7_nAoAg==" "183|PQZi0LmaYswPmFHcLb0pHITkg_7aJNC4x2IIC90kbRKE1GBt2m48tdi-1jb9jo9MYoxCGyvJtDy3ret7_nAoAg=="
class EstateRepository @Inject constructor( class EstateRepository @Inject constructor(
private val local: ILocalStore, local: ILocalStore,
private val api: IRoomParkApi, private val api: IRoomParkApi,
private val db: IDb, private val db: IDb
private val file: FileModule
): DealContract { ): DealContract {
...@@ -96,106 +92,6 @@ class EstateRepository @Inject constructor( ...@@ -96,106 +92,6 @@ class EstateRepository @Inject constructor(
} }
private fun getPlanTypesApi(estateId: Int): Observable<List<PlanPresetEntity>> =
api.getEstatePlanTypes(estateId)
.doOnNext { Timber.d("raw0 $it") }
.map { fromRawList(it, ::fromRaw) }
.map {
it.onEach { plan ->
val e = EstateEntity()
e.setId(estateId)
plan.estateId = e
}.toList()
}
.doOnNext(db::blockingUpsert)
.subscribeOn(Schedulers.io())
override fun getPlanTypes(estateId: Int): Observable<List<PlanPresetModel>> =
Observable.mergeDelayError(
arrayListOf(getPlanTypesApi(estateId))
).map { l -> List(l.size) { fromEntity(l[it]) } }
private fun getPlanApi(estateId: Int
, planId:Int
, furniture:Boolean? = null
, sizes:Boolean? = null
, walls:Boolean? = null
, electric:Boolean? = null) =
api.getDirectPlan(estateId, planId,
furniture?:false
,sizes?:false
,walls?:false
,electric?:false)
.map{
val sFile = getPlanFile(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric)
file.saveFileToDisk(sFile,it)
sFile.path
}
.subscribeOn(Schedulers.io())
private fun getPlanFile(estateId: Int
, planId:Int
, furniture:Boolean? = null
, sizes:Boolean? = null
, walls:Boolean? = null
, electric:Boolean? = null)
= FileModule.getDirectory(file.context
,FileModule.FileDirectory.PlanTypeDir(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric
))
override fun getEmptyPlan(estateId: Int
,planId:Int): Observable<String> =
Observable.mergeDelayError(
arrayListOf(getPlanApi(estateId,planId))
)
override fun getPlan(estateId: Int
,planId:Int
, furniture:Boolean?
, sizes:Boolean?
, walls:Boolean?
, electric:Boolean?): Observable<String> =
Observable.fromCallable { getPlanFile(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric) }.switchMap {
if (it.exists()) Observable.just(it.path)
else getPlanApi(estateId
,planId
, furniture
, sizes
, walls
, electric
)
}
// fun getPlanRequestString(estateId: Int
// , planId:Int
// , furniture:Boolean
// , sizes:Boolean
// , walls:Boolean
// , electric:Boolean
// ) = api.getDirectPlan(estateId,planId,furniture,sizes,electric).
private val getDealsApi: Observable<List<DealEntity>> = private val getDealsApi: Observable<List<DealEntity>> =
local.recentUser() local.recentUser()
......
package com.biganto.visual.roompark.data.data_provider
import com.biganto.visual.androidplayer.data.repository.local.ILocalStore
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.EstateEntity
import com.biganto.visual.roompark.data.repository.db.requrey.model.PlanPresetEntity
import com.biganto.visual.roompark.data.repository.file.FileModule
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.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 io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.util.*
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 20.04.2020.
*/
class PlanRepository @Inject constructor(
private val local: ILocalStore,
private val api: IRoomParkApi,
private val db: IDb,
private val file: FileModule
)
: FlatPlanContract {
private fun getPlanTypesApi(estateId: Int): Observable<List<PlanPresetEntity>> =
api.getEstatePlanTypes(estateId)
.doOnNext { Timber.d("raw0 $it") }
.map { fromRawList(it, ::fromRaw) }
.map {
it.onEach { plan ->
val e = EstateEntity()
e.setId(estateId)
plan.estateId = e
}.toList()
}
.doOnNext(db::blockingUpsert)
.subscribeOn(Schedulers.io())
override fun getPlanTypes(estateId: Int): Observable<List<PlanPresetModel>> =
Observable.mergeDelayError(
arrayListOf(getPlanTypesApi(estateId))
).map { l -> List(l.size) { fromEntity(l[it]) } }
private fun getPlanApi(estateId: Int
, planId:Int
, furniture:Boolean? = null
, sizes:Boolean? = null
, walls:Boolean? = null
, electric:Boolean? = null) =
api.getDirectPlan(estateId, planId,
furniture?:false
,sizes?:false
,walls?:false
,electric?:false)
.map{
val sFile = getPlanFile(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric)
file.saveFileToDisk(sFile,it)
sFile.path
}
.subscribeOn(Schedulers.io())
override fun getPlanFile(featuresVariant: PlanFeaturesVariant)
= getPlanFile(
estateId = featuresVariant.estateId,
planId = featuresVariant.planId,
furniture = featuresVariant.furniture,
sizes = featuresVariant.sizes,
walls = featuresVariant.walls,
electric = featuresVariant.electric
)
fun getPlanFile(estateId: Int
, planId:Int
, furniture:Boolean? = null
, sizes:Boolean? = null
, walls:Boolean? = null
, electric:Boolean? = null)
= FileModule.getDirectory(file.context
, FileModule.FileDirectory.PlanTypeDir(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric
))
// override fun getEmptyPlan(estateId: Int
// ,planId:Int): Observable<String> =
// Observable.mergeDelayError(
// arrayListOf(getPlanApi(estateId,planId))
// )
override fun getPlan(featuresVariant: PlanFeaturesVariant)
= getPlan(
estateId = featuresVariant.estateId,
planId = featuresVariant.planId,
furniture = featuresVariant.furniture,
sizes = featuresVariant.sizes,
walls = featuresVariant.walls,
electric = featuresVariant.electric
)
override fun getPlan(estateId: Int
,planId:Int
, furniture:Boolean?
, sizes:Boolean?
, walls:Boolean?
, electric:Boolean?): Observable<String> =
Observable.fromCallable { getPlanFile(
estateId = estateId,
planId = planId,
furniture = furniture,
walls = walls,
sizes = sizes,
electric = electric) }.switchMap {
if (it.exists()) Observable.just(it.path)
else getPlanApi(estateId
,planId
, furniture
, sizes
, walls
, electric
)
}
// fun getPlanRequestString(estateId: Int
// , planId:Int
// , furniture:Boolean
// , sizes:Boolean
// , walls:Boolean
// , electric:Boolean
// ) = api.getDirectPlan(estateId,planId,furniture,sizes,electric).
}
private fun BitSet.getOrNull(index:Int) =
if (index<0 || index>=this.size()) null
else get(index)
private fun Int.getBit(index: Int): Boolean? {
if (index<0) return null
return Integer.toBinaryString(shr(index)).last()=='1'
}
val PlanPresetModel.featuresVariants : List<PlanFeaturesVariant>
get() {
if (this.features.isNullOrEmpty()) return arrayListOf()
val maxInd = this.features.size
val f = features.indexOfFirst { it is FeatureModel.Furniture }
val s = features.indexOfFirst { it is FeatureModel.Sizes }
val e = features.indexOfFirst { it is FeatureModel.Electric }
val w = features.indexOfFirst { it is FeatureModel.Walls }
val resList = mutableListOf<PlanFeaturesVariant>()
var increment = 0
var allTrue: Boolean
do{
val v = PlanFeaturesVariant(
estateId,planId,
furniture = increment.getBit(f),
sizes = increment.getBit(s),
electric = increment.getBit(e),
walls = increment.getBit(w)
)
allTrue = v.furniture?:true && v.electric?:true && v.sizes?:true && v.walls?:true
resList.add(v)
increment++
}while (!allTrue)
return resList
}
data class PlanFeaturesVariant(
val estateId: Int,
val planId:Int,
val furniture:Boolean?,
val sizes:Boolean?,
val walls:Boolean?,
val electric:Boolean?
)
\ No newline at end of file
...@@ -36,7 +36,7 @@ private const val TIMEOUT_SECONDS=120L ...@@ -36,7 +36,7 @@ private const val TIMEOUT_SECONDS=120L
private const val WRITE_SECONDS=120L private const val WRITE_SECONDS=120L
private const val READ_SECONDS=120L private const val READ_SECONDS=120L
val INTERCEPT_LOG_LEVEL = HttpLoggingInterceptor.Level.HEADERS val INTERCEPT_LOG_LEVEL = HttpLoggingInterceptor.Level.NONE
@Module @Module
class RetrofitModule{ class RetrofitModule{
......
...@@ -60,7 +60,6 @@ class FileModule @Inject constructor(val context: Application) { ...@@ -60,7 +60,6 @@ class FileModule @Inject constructor(val context: Application) {
fun saveFileToDisk(file:File,content: String){ fun saveFileToDisk(file:File,content: String){
Timber.d("write to : $file") Timber.d("write to : $file")
Timber.d("write to : ${file.name}")
// file.createNewFile() // file.createNewFile()
file.parentFile.mkdirs() file.parentFile.mkdirs()
file.writeText(content) //to json array because core unity method parse data like TourData[] Estate[] etc.. file.writeText(content) //to json array because core unity method parse data like TourData[] Estate[] etc..
......
...@@ -175,7 +175,7 @@ class DownloadManagerService @Inject constructor( ...@@ -175,7 +175,7 @@ class DownloadManagerService @Inject constructor(
val sink = Okio.buffer(Okio.appendingSink(fileStorage)) val sink = Okio.buffer(Okio.appendingSink(fileStorage))
val buffer = sink.buffer() val buffer = sink.buffer()
var read = 0L var read = 0L
val step = 4096 val step = 8192
val source = response.source() val source = response.source()
var timer = System.currentTimeMillis() var timer = System.currentTimeMillis()
var stop: Boolean = false var stop: Boolean = false
...@@ -194,7 +194,6 @@ class DownloadManagerService @Inject constructor( ...@@ -194,7 +194,6 @@ class DownloadManagerService @Inject constructor(
} }
} }
model.isDownloaded = (source.exhausted() model.isDownloaded = (source.exhausted()
&& (model.fileDownloadedSize == model.tempOverallFileSize && (model.fileDownloadedSize == model.tempOverallFileSize
|| model.tempOverallFileSize == 0L)) || model.tempOverallFileSize == 0L))
...@@ -268,9 +267,10 @@ class DownloadManagerService @Inject constructor( ...@@ -268,9 +267,10 @@ class DownloadManagerService @Inject constructor(
mergeFiles(fileEntities) mergeFiles(fileEntities)
val jlist = db.getTourFilesJunction(tour.id).toList() val jlist = db.getTourFilesJunction(tour.id).toList()
Timber.d("jlist:: ${jlist?.size} start ${jlist?.firstOrNull()?.id}")
val junctionList = fileEntities val junctionList = fileEntities
.map {file -> .map {file ->
val entity = jlist.firstOrNull{it.tour == tour.id && it.file == file.uri} val entity = jlist.firstOrNull{it.tour == tour.id && it.file.uri() == file.uri.uri()}
?: TourFileJunctionEntity().apply { ?: TourFileJunctionEntity().apply {
setTour(tour.id) setTour(tour.id)
setFile(file.uri) setFile(file.uri)
...@@ -279,8 +279,8 @@ class DownloadManagerService @Inject constructor( ...@@ -279,8 +279,8 @@ class DownloadManagerService @Inject constructor(
totalSize += file.totalSize totalSize += file.totalSize
entity entity
} }
Timber.w("fffff $downloadedSize $totalSize")
Timber.d("junctionList:: ${junctionList.size} start ${junctionList.first().id}")
setDownloadInfo( setDownloadInfo(
raw.id.toString() raw.id.toString()
, tempLoadedFiles = 0 , tempLoadedFiles = 0
...@@ -337,7 +337,6 @@ class DownloadManagerService @Inject constructor( ...@@ -337,7 +337,6 @@ class DownloadManagerService @Inject constructor(
.observeOn(Schedulers.computation()) .observeOn(Schedulers.computation())
// .doOnNext{Timber.d("7 ${it}")} // .doOnNext{Timber.d("7 ${it}")}
.flatMap { model -> .flatMap { model ->
Timber.d(" model __ ${model}")
setDownloadInfo( setDownloadInfo(
model.tourId model.tourId
, totalSizedDiffSize = model.tempTourTotalDiff , totalSizedDiffSize = model.tempTourTotalDiff
...@@ -377,10 +376,13 @@ class DownloadManagerService @Inject constructor( ...@@ -377,10 +376,13 @@ class DownloadManagerService @Inject constructor(
private fun downloadTourFromQueue(): Observable<String> = private fun downloadTourFromQueue(): Observable<String> =
Observable.fromCallable { activeDownloading.set(true);downloadQueue.poll() } Observable.fromCallable { activeDownloading.set(true);downloadQueue.poll() }
.doOnNext { Timber.d("to load tour: ${it}") }
.flatMap { db.getTourPreview(it).observable() } .flatMap { db.getTourPreview(it).observable() }
.filter { .filter {
Timber.d("to load tour: ${it.isDownloaded} ${it.id}")
val forward = it.isDownloaded != DownloadState.Downloaded val forward = it.isDownloaded != DownloadState.Downloaded
activeDownloading.set(forward) activeDownloading.set(forward)
Timber.d("to load tour: $forward")
if (!forward) if (!forward)
notifyDownloadProgress() notifyDownloadProgress()
forward forward
...@@ -519,6 +521,7 @@ class DownloadManagerService @Inject constructor( ...@@ -519,6 +521,7 @@ class DownloadManagerService @Inject constructor(
disposable.add( disposable.add(
toursToDownloadObserver toursToDownloadObserver
.flatMap { db.getTourPreview(it).observable() } .flatMap { db.getTourPreview(it).observable() }
.filter { it.isDownloaded != DownloadState.Downloaded }
.doOnNext { .doOnNext {
it.isDownloaded = DownloadState.Downloading it.isDownloaded = DownloadState.Downloading
it.downloadedFiles = 0 it.downloadedFiles = 0
...@@ -531,18 +534,20 @@ class DownloadManagerService @Inject constructor( ...@@ -531,18 +534,20 @@ class DownloadManagerService @Inject constructor(
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.doOnError(Timber::e) .doOnError(Timber::e)
.subscribe { downloadQueue.add(it) } .subscribe { downloadQueue.add(it) }
) )
} }
private fun getMeta(tour: TourPreviewEntity): Observable<String> = private fun getMeta(tour: TourPreviewEntity): Observable<String> =
api.getTourMetaAsString(tour.id) api.getTourMetaAsString(tour.id)
.doOnNext { meta -> .map { meta ->
tour.let { tour.apply {
val metaUri = RevisionString("$META_PREDICTION${tour.id}$META_FILE_TYPE") val metaUri = RevisionString("$META_PREDICTION${tour.id}$META_FILE_TYPE")
it.setMetaFileEntityId(metaUri) setMetaFileEntityId(metaUri)
fileModule.saveFileToDisk(fileModule.getFile(metaUri.uri()), meta) fileModule.saveFileToDisk(fileModule.getFile(metaUri.uri()), meta)
} }
} }
.flatMap { db.upsertTourPreview(it) }
.map { tour.id } .map { tour.id }
.onErrorReturn { .onErrorReturn {
setTourStatus(tour.id,DownloadState.Crushed) setTourStatus(tour.id,DownloadState.Crushed)
......
...@@ -66,6 +66,8 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{ ...@@ -66,6 +66,8 @@ interface AppComponent : AndroidInjector<RoomParkApplication>{
fun provideTour():TourContract fun provideTour():TourContract
fun providePlan():FlatPlanContract
fun provideLifeCycle(): ForegroundLifecycleObserver fun provideLifeCycle(): ForegroundLifecycleObserver
fun provideNotifivations(): INotificationCenter fun provideNotifivations(): INotificationCenter
......
...@@ -59,6 +59,10 @@ abstract class ContractRepositoryModule { ...@@ -59,6 +59,10 @@ abstract class ContractRepositoryModule {
@Binds @Binds
@Singleton @Singleton
abstract fun provideTourContract(impl: ToursRepository): TourContract abstract fun provideTourContract(impl: ToursRepository): TourContract
@Binds
@Singleton
abstract fun providePlanContract(impl: PlanRepository): FlatPlanContract
} }
......
...@@ -2,7 +2,6 @@ package com.biganto.visual.roompark.domain.contract ...@@ -2,7 +2,6 @@ package com.biganto.visual.roompark.domain.contract
import com.biganto.visual.roompark.domain.model.DealModel import com.biganto.visual.roompark.domain.model.DealModel
import com.biganto.visual.roompark.domain.model.EstateModel import com.biganto.visual.roompark.domain.model.EstateModel
import com.biganto.visual.roompark.domain.model.PlanPresetModel
import io.reactivex.Completable import io.reactivex.Completable
import io.reactivex.Observable import io.reactivex.Observable
...@@ -15,17 +14,6 @@ interface DealContract{ ...@@ -15,17 +14,6 @@ interface DealContract{
fun getFavorites() : Observable<List<EstateModel>> fun getFavorites() : Observable<List<EstateModel>>
fun getEstate(estateId: Int): Observable<EstateModel> fun getEstate(estateId: Int): Observable<EstateModel>
fun getPlanTypes(estateId: Int): Observable<List<PlanPresetModel>>
fun getEmptyPlan(estateId: Int, planId: Int): Observable<String>
fun getPlan(
estateId: Int
, planId: Int
, furniture:Boolean?
, sizes:Boolean?
, walls:Boolean?
, electric:Boolean?): Observable<String>
fun getDeals(): Observable<List<DealModel>> fun getDeals(): Observable<List<DealModel>>
fun fetchEstate(building: Int, number: Int): Observable<EstateModel> fun fetchEstate(building: Int, number: Int): Observable<EstateModel>
fun setDealRead(dealId: String): Completable fun setDealRead(dealId: String): Completable
......
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 io.reactivex.Observable
import java.io.File
/**
* Created by Vladislav Bogdashkin on 20.04.2020.
*/
interface FlatPlanContract{
fun getPlanTypes(estateId: Int): Observable<List<PlanPresetModel>>
fun getPlan(
estateId: Int
, planId: Int
, furniture:Boolean?
, sizes:Boolean?
, walls:Boolean?
, electric:Boolean?): Observable<String>
fun getPlanFile(featuresVariant: PlanFeaturesVariant): File
fun getPlan(featuresVariant: PlanFeaturesVariant): Observable<String>
}
\ No newline at end of file
...@@ -17,7 +17,6 @@ class EstateInteractor @Inject constructor( ...@@ -17,7 +17,6 @@ class EstateInteractor @Inject constructor(
fun getPlanTypes(estateId: Int) = fun getPlanTypes(estateId: Int) =
useCase.getEstatePlanPresets(estateId) useCase.getEstatePlanPresets(estateId)
fun getPlan(estateId: Int,planId:Int) = useCase.getPlan(estateId,planId)
fun getPlan(plan:PlanPresetModel) = fun getPlan(plan:PlanPresetModel) =
useCase.getPlan( useCase.getPlan(
......
...@@ -28,11 +28,17 @@ class SettingsInteractor @Inject constructor( ...@@ -28,11 +28,17 @@ class SettingsInteractor @Inject constructor(
private val settingsUseCase: SettingsUseCase, private val settingsUseCase: SettingsUseCase,
private val activity: BaseRoomParkActivity, private val activity: BaseRoomParkActivity,
private val subUc: SubscriptionUseCase, private val subUc: SubscriptionUseCase,
private val toursUc: TourPreviewsUseCase private val toursUc: TourPreviewsUseCase,
private val planTypes: PlanTypesUseCase
){ ){
fun downloadTourPlans(cancellationToken:DownloadUseCase.CancellationToken)
= planTypes.downloadAllPlanTypes(cancellationToken)
fun fetchToursSizes() = toursUc.fetchToursSizes() fun fetchToursSizes() = toursUc.fetchToursSizes()
fun fetchPlanTypesSizes() = planTypes.fetchNotDownloadedPlansSizes()
private fun startDownloadService() { private fun startDownloadService() {
val i = Intent(activity, DownloadManagerService::class.java) val i = Intent(activity, DownloadManagerService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
......
...@@ -63,7 +63,7 @@ class DownloadUseCase @Inject constructor( ...@@ -63,7 +63,7 @@ class DownloadUseCase @Inject constructor(
else Okio.buffer(Okio.sink(fileStorage)) else Okio.buffer(Okio.sink(fileStorage))
val buffer = sink.buffer() val buffer = sink.buffer()
var read = 0L var read = 0L
val step = 4096 val step = 8192
val source = response.source() val source = response.source()
var stop: Boolean = token.isCancelled var stop: Boolean = token.isCancelled
sink.use { sink.use {
...@@ -161,7 +161,7 @@ class DownloadUseCase @Inject constructor( ...@@ -161,7 +161,7 @@ class DownloadUseCase @Inject constructor(
val jlist = db.getTourFilesJunction(tour.id).toList() val jlist = db.getTourFilesJunction(tour.id).toList()
val junctionList = fileEntities val junctionList = fileEntities
.map {file -> .map {file ->
val entity = jlist.firstOrNull{it.tour == tour.id && it.file == file.uri} val entity = jlist.firstOrNull{it.tour == tour.id && it.file.uri() == file.uri.uri()}
?: TourFileJunctionEntity() ?: TourFileJunctionEntity()
entity.setTour(tour.id) entity.setTour(tour.id)
entity.setFile(file.uri) entity.setFile(file.uri)
......
package com.biganto.visual.roompark.domain.use_case package com.biganto.visual.roompark.domain.use_case
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 javax.inject.Inject import javax.inject.Inject
/** /**
...@@ -8,7 +9,8 @@ import javax.inject.Inject ...@@ -8,7 +9,8 @@ import javax.inject.Inject
*/ */
class EstateUseCase @Inject constructor( class EstateUseCase @Inject constructor(
private val contract: DealContract private val contract: DealContract,
private val planContract: FlatPlanContract
) { ) {
fun fetchFavorites() = contract.getFavorites() fun fetchFavorites() = contract.getFavorites()
...@@ -19,12 +21,9 @@ class EstateUseCase @Inject constructor( ...@@ -19,12 +21,9 @@ class EstateUseCase @Inject constructor(
contract.fetchEstate(building, number) contract.fetchEstate(building, number)
fun getEstatePlanPresets(estateId: Int) = fun getEstatePlanPresets(estateId: Int) =
contract.getPlanTypes(estateId) planContract.getPlanTypes(estateId)
fun getPlan(estateId: Int, planId: Int) =
contract.getEmptyPlan(estateId, planId)
fun getPlan( fun getPlan(
estateId: Int estateId: Int
, planId: Int , planId: Int
...@@ -32,7 +31,7 @@ class EstateUseCase @Inject constructor( ...@@ -32,7 +31,7 @@ class EstateUseCase @Inject constructor(
, sizes: Boolean? , sizes: Boolean?
, walls: Boolean? , walls: Boolean?
, electric: Boolean? , electric: Boolean?
) = contract.getPlan( ) = planContract.getPlan(
estateId estateId
, planId , planId
, furniture , furniture
......
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.domain.contract.AuthContract
import com.biganto.visual.roompark.domain.contract.FlatPlanContract
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
/**
* Created by Vladislav Bogdashkin on 20.04.2020.
*/
class PlanTypesUseCase @Inject constructor(
private val planContract: FlatPlanContract,
private val auth:AuthContract
) {
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
}
fun fetchNotDownloadedPlansSizes(): Observable<Int> =
fetchAllPlanTypes
.flatMapIterable { it }
.flatMap {
planContract.getPlanTypes(it.id)
.map { plantypes -> plantypes.flatMap { plan -> plan.featuresVariants } }
}
.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
.flatMapSingle {
Observable.fromIterable(it)
.flatMap { estateEntity ->
planContract.getPlanTypes(estateEntity.id)
.map { plantypes -> plantypes.flatMap { plan -> plan.featuresVariants } }
}
.toList()
}
.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)
}
}
}
}
data class DownloadProgress(
val currentProgress:Int,
val totalProgress:Int
)
\ No newline at end of file
...@@ -33,12 +33,16 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -33,12 +33,16 @@ class TourPreviewsUseCase @Inject constructor(
,private val tours:TourContract ,private val tours:TourContract
) { ) {
fun getTourById(tourId:String):Observable<DownloadTourByIdResult> { fun getTourById(tourId: String): Observable<DownloadTourByIdResult> {
val tour = retrieveTour(tourId) val tour = retrieveTour(tourId)
Timber.d("retrieveTour $tourId / $tour") Timber.d("retrieveTour $tourId / $tour")
if (tour != null) { if (tour != null) {
if (tour.downloadState == DownloadState.Downloaded) if (tour.downloadState == DownloadState.Downloaded)
return Observable.just<DownloadTourByIdResult>(DownloadTourByIdResult.ReadyToPlay(tour)) return Observable.just<DownloadTourByIdResult>(
DownloadTourByIdResult.ReadyToPlay(
tour
)
)
return setTourState(tour.tour_id, DownloadState.DownloadQueue) return setTourState(tour.tour_id, DownloadState.DownloadQueue)
.map<DownloadTourByIdResult> { DownloadTourByIdResult.DownloadStarted(tour) } .map<DownloadTourByIdResult> { DownloadTourByIdResult.DownloadStarted(tour) }
...@@ -50,21 +54,21 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -50,21 +54,21 @@ class TourPreviewsUseCase @Inject constructor(
} }
fun retrieveTour(tourId: String) = fun retrieveTour(tourId: String) =
db.getTourPreview(tourId) db.getTourPreview(tourId)
.asSequence() .asSequence()
.map ( ::fromEntity) .map(::fromEntity)
.firstOrNull() .firstOrNull()
private fun setTourState(tourId:String, state: DownloadState): Observable<Boolean> = private fun setTourState(tourId: String, state: DownloadState): Observable<Boolean> =
db.getTourPreview(tourId) db.getTourPreview(tourId)
.observable() .observable()
.doOnNext{ it.isDownloaded=state } .doOnNext { it.isDownloaded = state }
.flatMap { db.upsertTourPreview(it).map{true} } .flatMap { db.upsertTourPreview(it).map { true } }
private fun syncTour(tourId:String, parentId:Int):Observable<TourModel> = private fun syncTour(tourId: String, parentId: Int): Observable<TourModel> =
syncTour(tourId,parentId,calcTargetResolution()) syncTour(tourId, parentId, calcTargetResolution())
private fun syncTour(tourId:String, estateId: Int, targetResolution:Int) private fun syncTour(tourId: String, estateId: Int, targetResolution: Int)
: Observable<TourModel> { : Observable<TourModel> {
val request = ToursRemoteByIdRequestModel( val request = ToursRemoteByIdRequestModel(
arrayListOf(tourId) arrayListOf(tourId)
...@@ -76,15 +80,16 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -76,15 +80,16 @@ class TourPreviewsUseCase @Inject constructor(
.map { .map {
if (it.isNullOrEmpty()) if (it.isNullOrEmpty())
throw CustomApiException.TourByIdNotFoundException() throw CustomApiException.TourByIdNotFoundException()
it.first() } it.first()
}
.doOnNext { it.isDownloaded = DownloadState.DownloadQueue } .doOnNext { it.isDownloaded = DownloadState.DownloadQueue }
.flatMap {db.upsertTourPreview(it)} .flatMap { db.upsertTourPreview(it) }
.map(::fromEntity) .map(::fromEntity)
.doOnError(Timber::e) .doOnError(Timber::e)
} }
private fun calcTargetResolution():Int{ private fun calcTargetResolution(): Int {
val w = Resources.getSystem().displayMetrics.widthPixels val w = Resources.getSystem().displayMetrics.widthPixels
val h = Resources.getSystem().displayMetrics.heightPixels val h = Resources.getSystem().displayMetrics.heightPixels
return w.coerceAtLeast(h) return w.coerceAtLeast(h)
...@@ -93,10 +98,13 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -93,10 +98,13 @@ class TourPreviewsUseCase @Inject constructor(
private fun forceTourUpdate(requestModel: ToursRemoteByIdRequestModel): Observable<List<TourPreviewEntity>> = private fun forceTourUpdate(requestModel: ToursRemoteByIdRequestModel): Observable<List<TourPreviewEntity>> =
api.getToursPreviewById(requestModel.ids) api.getToursPreviewById(requestModel.ids)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.map { fromRaw(it .map {
, requestModel.estateId fromRaw(
, api.provideHttpUrl().toString() it
, requestModel.targetResolution) , requestModel.estateId
, api.provideHttpUrl().toString()
, requestModel.targetResolution
)
} }
...@@ -104,56 +112,60 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -104,56 +112,60 @@ class TourPreviewsUseCase @Inject constructor(
db.getEstateTourPreviews(estateId) db.getEstateTourPreviews(estateId)
.filter { !it.isNullOrEmpty() } .filter { !it.isNullOrEmpty() }
private fun fetchApiTourList(multitourId:Int,estateId: Int) = private fun fetchApiTourList(multitourId: Int, estateId: Int) =
auth.currentUser() auth.currentUser()
.doOnNext { Timber.d("user on next: $it") }
.map { it.targetResolution } .map { it.targetResolution }
.flatMap { res -> .flatMap { res ->
Timber.d("user: $res") api.getOfferTours(multitourId)
api.getOfferTours(multitourId) .doOnError { Timber.e(it) }
.doOnError { Timber.e(it) } .map {
.map { mergeRaw(
mergeRaw(it, TourRemoteRequestModel( it, TourRemoteRequestModel(
estateId, estateId,
api.provideHttpUrl().toString(), api.provideHttpUrl().toString(),
res res
)
) )
) }
} .map { it }
.map { it } .doOnNext { db.blockingUpsert(it) }
.doOnNext { db.blockingUpsert(it) } }
}
fun fetchTourOffer(multitourId:Int,parent:Int) = fun fetchTourOffer(multitourId: Int, parent: Int): Observable<List<TourModel>> =
Observable.mergeDelayError( Observable.mergeDelayError(
arrayListOf(fetchDbTourList(parent),fetchApiTourList(multitourId,parent)) arrayListOf(fetchDbTourList(parent), fetchApiTourList(multitourId, parent))
) )
.take(1) .take(1)
.doOnError { Timber.e(it) } .doOnError { Timber.e(it) }
.map (::fromEntity) .map(::fromEntity)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
private fun mergeRaw(raw: List<TourPreviewRaw>, requestRequestModel: TourRemoteRequestModel) = private fun mergeRaw(raw: List<TourPreviewRaw>, requestRequestModel: TourRemoteRequestModel) =
raw.map{ mergeRaw(it, requestRequestModel) } raw.map { mergeRaw(it, requestRequestModel) }
private fun mergeRaw(raw: TourPreviewRaw, requestRequestModel: TourRemoteRequestModel) private fun mergeRaw(raw: TourPreviewRaw, requestRequestModel: TourRemoteRequestModel)
: TourPreviewEntity { : TourPreviewEntity {
Timber.d("got raw: $raw") Timber.d("got raw: $raw")
val entity = db.getTourPreview(raw.id.toString()).firstOrNull() val entity = db.getTourPreview(raw.id.toString()).firstOrNull()
?: return fromRaw(raw ?: return fromRaw(
raw
, requestRequestModel.estateId , requestRequestModel.estateId
, api.provideHttpUrl().toString() , api.provideHttpUrl().toString()
, requestRequestModel.targetResolution) , requestRequestModel.targetResolution
)
val fromApi = fromRaw(raw val fromApi = fromRaw(
raw
, requestRequestModel.estateId , requestRequestModel.estateId
, api.provideHttpUrl().toString() , api.provideHttpUrl().toString()
, requestRequestModel.targetResolution) , requestRequestModel.targetResolution
)
if (fromApi.updated > entity.updated if (fromApi.updated > entity.updated
&& entity.isDownloaded == DownloadState.Downloaded) { && entity.isDownloaded == DownloadState.Downloaded
) {
entity.isDownloaded = entity.isDownloaded =
DownloadState.NotSynced//maxState(entity.isDownloaded, fromApi.isDownloaded) DownloadState.NotSynced//maxState(entity.isDownloaded, fromApi.isDownloaded)
return entity return entity
...@@ -163,19 +175,18 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -163,19 +175,18 @@ class TourPreviewsUseCase @Inject constructor(
// if (fromApi.estate.id!=requestRequestModel.estateId) // if (fromApi.estate.id!=requestRequestModel.estateId)
// entity.estate=fromApi.estate // entity.estate=fromApi.estate
fromApi.setMetaFileEntityId(entity.metaFileEntityId) fromApi.setMetaFileEntityId(entity.metaFileEntityId)
fromApi.targetResolution=entity.targetResolution fromApi.targetResolution = entity.targetResolution
fromApi.isDownloaded=entity.isDownloaded fromApi.isDownloaded = entity.isDownloaded
fromApi.overallSize=entity.overallSize fromApi.overallSize = entity.overallSize
fromApi.downloadedSize=entity.downloadedSize fromApi.downloadedSize = entity.downloadedSize
fromApi.tempSize=entity.tempSize fromApi.tempSize = entity.tempSize
fromApi.overallFiles=entity.overallFiles fromApi.overallFiles = entity.overallFiles
fromApi.downloadedFiles=entity.downloadedFiles fromApi.downloadedFiles = entity.downloadedFiles
return fromApi return fromApi
} }
private fun getUserEstates(user:UserEntity) private fun getUserEstates(user: UserEntity) = user.deals?.map { it.estate }?.plus(
= user.deals?.map { it.estate }?.plus(
user.estates user.estates
?.asSequence() ?.asSequence()
?.filter { it.favorite } ?.filter { it.favorite }
...@@ -185,18 +196,15 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -185,18 +196,15 @@ class TourPreviewsUseCase @Inject constructor(
fun fetchToursSizes(): Observable<Long> = fun fetchToursSizes(): Observable<Long> =
auth.currentUser() auth.currentUser()
.map (::getUserEstates) .map(::getUserEstates)
.map { it.filter { estates -> estates.multitourId!=null }.toList() } .map { it.filter { estates -> estates.multitourId != null }.toList() }
.map { estates -> .map { estates ->
val toursOffersToLoad = mutableListOf<Int>() val toursOffersToLoad = mutableListOf<Int>()
estates.forEach{ estates.forEach {
if (it.tours.isNullOrEmpty()) if (it.tours.isNullOrEmpty())
toursOffersToLoad.add(it.multitourId!!) toursOffersToLoad.add(it.multitourId!!)
} }
Timber.d(" targer estates : " + Pair(estates, toursOffersToLoad)
"${estates.map { it.tours?.size }} " )
Timber.d(" targer toursOffersToLoad : $toursOffersToLoad " )
Pair(estates,toursOffersToLoad)
} }
.flatMap { pair -> .flatMap { pair ->
if (pair.second.isNotEmpty()) { if (pair.second.isNotEmpty()) {
...@@ -206,51 +214,45 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -206,51 +214,45 @@ class TourPreviewsUseCase @Inject constructor(
fetchTourOffer( fetchTourOffer(
it, pair.first.first { estete -> estete.multitourId == it }.id it, pair.first.first { estete -> estete.multitourId == it }.id
).doOnError { Timber.e(it) } ).doOnError { Timber.e(it) }
.doOnNext { tours -> loadedIds.addAll(tours.map{ t -> t.tour_id }) } .doOnNext { tours -> loadedIds.addAll(tours.map { t -> t.tour_id }) }
} }
).takeLast(1) ).takeLast(1)
.doOnNext { db.refreshEntities(pair.first) } .doOnNext { db.refreshEntities(pair.first) }
.map { Pair(pair.first,loadedIds )} .map { Pair(pair.first, loadedIds) }
} } else return@flatMap Observable.just(Pair(pair.first, null))
else return@flatMap Observable.just(Pair(pair.first,null))
} }
.doOnNext { Timber.d(" HERER ") }
.flatMap { pair -> .flatMap { pair ->
val estates = pair.first val estates = pair.first
for (estate in estates) {
Timber.d(" targer estates : ${estate.user} " )
}
val r = (estates.first().user as UserEntity).targetResolution val r = (estates.first().user as UserEntity).targetResolution
Timber.d(" targer R : $r " )
var knownSize = var knownSize =
estates.flatMap { estates.flatMap {
it.tours?.map {t -> t as TourPreviewEntity} it.tours?.map { t -> t as TourPreviewEntity }
?.asIterable()?: arrayListOf() ?.asIterable() ?: arrayListOf()
}.filter{t -> t.overallSize > 0L } }
.onEach { Timber.d("it.overallSize - it.downloadedSize " + .filter { t -> t.overallSize > 0L }
"${it.overallSize}/${it.downloadedSize}") }
.sumByLong { it.overallSize - it.downloadedSize } .sumByLong { it.overallSize - it.downloadedSize }
Timber.d(" targer knownSize : $knownSize " )
val toursToLoadSize = val toursToLoadSize =
estates.flatMap { estates.flatMap {
it.tours?.map {t -> t as TourPreviewEntity} it.tours?.map { t -> t as TourPreviewEntity }
?.asIterable()?: arrayListOf() ?.asIterable() ?: arrayListOf()
}.filter{t -> t.overallSize < 1L } }
.filter { t -> t.overallSize < 1L }
Timber.d(" targer toursToLoadSize : $toursToLoadSize " ) .map { it.id }.toMutableList()
val listIds = toursToLoadSize.map { it.id }.toMutableList()
pair.second?.let { listIds.addAll(it)} pair.second?.let { toursToLoadSize.addAll(it) }
Timber.d(" targer estates : ${listIds} " )
if (listIds.isNullOrEmpty()) return@flatMap Observable.just(knownSize) if (toursToLoadSize.isNullOrEmpty()) return@flatMap Observable.just(knownSize)
else return@flatMap api.getTourFilesSizes( else return@flatMap api.getTourFilesSizes(
listIds,r.toString() toursToLoadSize, r.toString()
) )
.flatMapIterable { it } .flatMapIterable { it }
.flatMap { rawSize -> .flatMap { rawSize ->
db.getTourPreview(rawSize.id.toString()) db.getTourPreview(rawSize.id.toString())
.observable() .observable()
.map {entity -> .map { entity ->
knownSize += rawSize.total_size knownSize += rawSize.total_size
entity.apply { entity.apply {
overallSize = rawSize.total_size overallSize = rawSize.total_size
...@@ -258,7 +260,7 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -258,7 +260,7 @@ class TourPreviewsUseCase @Inject constructor(
} }
entity entity
} }
.doOnNext{ db.upsert(it).blockingGet() } .doOnNext { db.upsert(it).blockingGet() }
}.map { knownSize } }.map { knownSize }
} }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
...@@ -276,7 +278,6 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -276,7 +278,6 @@ class TourPreviewsUseCase @Inject constructor(
auth.currentUser() auth.currentUser()
.map { user -> .map { user ->
val estatesList = getUserEstates(user) val estatesList = getUserEstates(user)
estatesList estatesList
?.asSequence() ?.asSequence()
?.filter { it.multitourId != null } ?.filter { it.multitourId != null }
...@@ -291,26 +292,17 @@ class TourPreviewsUseCase @Inject constructor( ...@@ -291,26 +292,17 @@ class TourPreviewsUseCase @Inject constructor(
) )
} }
} }
.doOnNext { Timber.d("merged list:${it?.size}") }
.map { list -> .map { list ->
list.map { pair -> list.map { pair ->
api.getOfferTours(pair.first) api.getOfferTours(pair.first)
.doOnNext { Timber.d(" gonna merge") }
.map { .map {
mergeRaw( mergeRaw(it, pair.second)
it
, pair.second
)
} }
.map { it } .map { it }
.doOnNext { Timber.d("merged list:${it.size}") }
.blockingFirst() .blockingFirst()
} }
.flatten() .flatten()
} }
// .map { it.flatten() }
.doOnNext { Timber.d("merged flatten list:${it.size}") }
.flatMap { db.upsertTourPreview(it) } .flatMap { db.upsertTourPreview(it) }
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
} }
......
...@@ -7,11 +7,14 @@ import androidx.core.widget.NestedScrollView ...@@ -7,11 +7,14 @@ import androidx.core.widget.NestedScrollView
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView import butterknife.BindView
import butterknife.OnClick
import com.biganto.visual.roompark.R import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.base.HeaderToolbarModel import com.biganto.visual.roompark.base.HeaderToolbarModel
import com.biganto.visual.roompark.base.RoomParkApplication import com.biganto.visual.roompark.base.RoomParkApplication
import com.biganto.visual.roompark.base.RoomParkMainActivity import com.biganto.visual.roompark.base.RoomParkMainActivity
import com.biganto.visual.roompark.conductor.BigantoBaseController 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.domain.model.SubscriptionModel 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.CahcedListAdapter
import com.biganto.visual.roompark.presentation.screen.settings.util.PushListAdapter import com.biganto.visual.roompark.presentation.screen.settings.util.PushListAdapter
...@@ -105,6 +108,14 @@ class SettingsScreenController : ...@@ -105,6 +108,14 @@ class SettingsScreenController :
@BindView(R.id.progress_lock_background) @BindView(R.id.progress_lock_background)
lateinit var progressShame:View lateinit var progressShame:View
@OnClick(R.id.downloadFlatCardsIcon)
fun onStartTourPlans(){
router.pushController(RouterTransaction.with(DownloadPlansDialogController())
.pushChangeHandler(DialogChangeHandler())
.popChangeHandler(DialogChangeHandler())
)
}
private fun setToolbar(){ private fun setToolbar(){
toolBar.appBar.liftOnScrollTargetViewId = R.id.nestedScrollContainer toolBar.appBar.liftOnScrollTargetViewId = R.id.nestedScrollContainer
pushRecycler.isNestedScrollingEnabled = false pushRecycler.isNestedScrollingEnabled = false
...@@ -133,6 +144,15 @@ class SettingsScreenController : ...@@ -133,6 +144,15 @@ class SettingsScreenController :
override fun onViewBound(v: View) { override fun onViewBound(v: View) {
bottomNavigationController.show() bottomNavigationController.show()
toursDownloaderTitle.text =
resources
?.getString(R.string.download_all_tours_settings_with_size, "-")
flatDownloaderTitle.text =
resources
?.getString(R.string.download_all_plan_types_settings_with_sizes, "-")
setToolbar() setToolbar()
bindRecycler() bindRecycler()
} }
...@@ -146,6 +166,7 @@ class SettingsScreenController : ...@@ -146,6 +166,7 @@ class SettingsScreenController :
is SettingsScreenViewState.SomeError -> render(viewState) is SettingsScreenViewState.SomeError -> render(viewState)
is SettingsScreenViewState.SignOut -> render(viewState) is SettingsScreenViewState.SignOut -> render(viewState)
is SettingsScreenViewState.OnCacheDeleting -> render(viewState) is SettingsScreenViewState.OnCacheDeleting -> render(viewState)
is SettingsScreenViewState.OnPlanTypesPrefetch -> render(viewState)
is SettingsScreenViewState.LoadCachInfo -> render(viewState) is SettingsScreenViewState.LoadCachInfo -> render(viewState)
is SettingsScreenViewState.LoadSubscriptions -> render(viewState) is SettingsScreenViewState.LoadSubscriptions -> render(viewState)
is SettingsScreenViewState.SubscriptionStatus -> render(viewState) is SettingsScreenViewState.SubscriptionStatus -> render(viewState)
...@@ -170,6 +191,14 @@ class SettingsScreenController : ...@@ -170,6 +191,14 @@ class SettingsScreenController :
) )
} }
private fun render(viewState: SettingsScreenViewState.OnPlanTypesPrefetch) {
flatDownloaderTitle.text =
resources?.getString(
R.string.download_all_plan_types_settings_with_sizes
, viewState.size.bytesToSize()
)
}
private fun render(viewState: SettingsScreenViewState.LoadSubscriptions){ private fun render(viewState: SettingsScreenViewState.LoadSubscriptions){
(pushRecycler.adapter as PushListAdapter).setItems(viewState.list) (pushRecycler.adapter as PushListAdapter).setItems(viewState.list)
} }
...@@ -208,11 +237,6 @@ class SettingsScreenController : ...@@ -208,11 +237,6 @@ class SettingsScreenController :
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun render(viewState: SettingsScreenViewState.LoadSettingsList){ private fun render(viewState: SettingsScreenViewState.LoadSettingsList){
toursDownloaderTitle.text = viewState.settings.offlineStoreData[0].title +
"(${viewState.settings.offlineStoreData[0].amountBytes.bytesToSize()})"
flatDownloaderTitle.text = viewState.settings.offlineStoreData[1].title +
"(${viewState.settings.offlineStoreData[1].amountBytes.bytesToSize()})"
} }
private fun getComponent() = DaggerSettingsScreenComponent.factory() private fun getComponent() = DaggerSettingsScreenComponent.factory()
......
...@@ -41,6 +41,10 @@ class SettingsScreenPresenter @Inject constructor( ...@@ -41,6 +41,10 @@ class SettingsScreenPresenter @Inject constructor(
val fetchToursSize = interactor.fetchToursSizes() val fetchToursSize = interactor.fetchToursSizes()
.map { SettingsScreenViewState.OnSizePrefetch(it) } .map { SettingsScreenViewState.OnSizePrefetch(it) }
val fetchPlansSize = interactor.fetchPlanTypesSizes()
.map { it*1024L*1024L }
.map { SettingsScreenViewState.OnPlanTypesPrefetch(it) }
val onDownloadTours = intent(SettingsScreen::downloadAllTours) val onDownloadTours = intent(SettingsScreen::downloadAllTours)
.flatMap { interactor.startToursDownloading() .flatMap { interactor.startToursDownloading()
.andThen(Observable.just(SettingsScreenViewState.Idle())) .andThen(Observable.just(SettingsScreenViewState.Idle()))
...@@ -116,6 +120,7 @@ class SettingsScreenPresenter @Inject constructor( ...@@ -116,6 +120,7 @@ class SettingsScreenPresenter @Inject constructor(
val state = Observable.mergeDelayError( val state = Observable.mergeDelayError(
arrayListOf( arrayListOf(
restoreStateObservable, restoreStateObservable,
fetchPlansSize,
fetchSettings, fetchSettings,
onSignOut, onSignOut,
onClearCache, onClearCache,
......
...@@ -19,6 +19,7 @@ sealed class SettingsScreenViewState : BigantoBaseViewState() { ...@@ -19,6 +19,7 @@ sealed class SettingsScreenViewState : BigantoBaseViewState() {
class SignOut() : SettingsScreenViewState() class SignOut() : SettingsScreenViewState()
class OnCacheDeleting(val progress:Float) : SettingsScreenViewState() class OnCacheDeleting(val progress:Float) : SettingsScreenViewState()
class OnSizePrefetch(val size:Long) : SettingsScreenViewState() class OnSizePrefetch(val size:Long) : SettingsScreenViewState()
class OnPlanTypesPrefetch(val size:Long) : SettingsScreenViewState()
class LoadSubscriptions(val list:List<TitledSubscriptionModel>) : SettingsScreenViewState() class LoadSubscriptions(val list:List<TitledSubscriptionModel>) : SettingsScreenViewState()
class LoadCachInfo(val list: List<CachedDataModel>) : SettingsScreenViewState() class LoadCachInfo(val list: List<CachedDataModel>) : SettingsScreenViewState()
class SubscriptionStatus(val subId:Int,val subState: Boolean) : SettingsScreenViewState() class SubscriptionStatus(val subId:Int,val subState: Boolean) : SettingsScreenViewState()
......
...@@ -123,5 +123,7 @@ ...@@ -123,5 +123,7 @@
<string name="game_view_content_description" /> <string name="game_view_content_description" />
<string name="download_all_tours_settings_with_size">Скачать виртуальные туры моих квартир из избранного и сделок (%s)</string> <string name="download_all_tours_settings_with_size">Скачать виртуальные туры моих квартир из избранного и сделок (%s)</string>
<string name="download_all_plan_types_settings_with_sizes">Скачать карточки моих квартир из избранного и сделок (%s)</string> <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>
</resources> </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