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

downloader progress coding..

parent 4fdbf3bc
......@@ -2,8 +2,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.biganto.visual.roompark">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:name=".base.RoomParkApplication"
......@@ -58,6 +63,11 @@
android:resource="@color/colorAccent" />
</service>
<service
android:name=".data.service.download.DownloadManagerService"
android:enabled="true"
android:exported="false" />
</application>
</manifest>
\ No newline at end of file
......@@ -60,7 +60,7 @@ class BigantoMviConductorLifecycleListener<V : MvpView, P : MviPresenter<V, *>>
}
val viewMpv = callback?.mvpView ?: throw NullPointerException(
"MvpView returned from getMvpView() is null. Returned by " + controller.activity!!)
"MvpView returned from getMvpView() is null. Returned by ${controller.activity}")
if (viewStateWillBeRestored) {
callback!!.setRestoringViewState(true)
......
......@@ -60,12 +60,18 @@ class BigantoRetrofitRepository @Inject constructor(@Named("bigantoApi") retrof
.doOnError(::e)
override fun getOfferTours(multiTourId:Int): Observable<List<TourPreviewRaw>> =
override fun getOfferTours(multiTourIds:List<Int>): Observable<List<TourPreviewRaw>> =
api
.getOfferTours(offerId = multiTourId)
.getOfferTours(offerId = multiTourIds)
.compose(RetrofitResponseValidation())
.map { it.values.flatten() }
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
override fun getOfferTours(multiTourId:Int): Observable<List<TourPreviewRaw>> =
api
.getOfferTours(offerId = arrayListOf(multiTourId))
.compose(RetrofitResponseValidation())
.map { it[multiTourId.toString()]?.toList()?: error("No tours avaliable")}
.doOnError { e(it) }
.subscribeOn(Schedulers.io())
......
......@@ -25,4 +25,5 @@ interface IBigantoApi {
fun getToursPreviewById(tourIds: List<String>): Observable<List<TourPreviewRaw>>
fun getOfferTours(multiTourId:Int): Observable<List<TourPreviewRaw>>
fun getOfferTours(multiTourIds: List<Int>): Observable<List<TourPreviewRaw>>
}
\ No newline at end of file
......@@ -145,7 +145,7 @@ interface IBigantoMobileApi {
@Query(CLIENT_VERSION_PARAM) clientVersion: String = DEFAULT_CLIENT_VERSION,
@Query(API_VERSION_PARAM) apiVersion: String = DEFAULT_API_VERSION,
@Query(LANG_PARAM) languageCode: String = Locale.getDefault().language,
@Query(OFFER_GET_TOURS_ID) offerId: Int
@Query(OFFER_GET_TOURS_ID) offerId: List<Int>
): Observable<Response<Map<String,List<TourPreviewRaw>>>>
@Streaming
......
......@@ -36,7 +36,7 @@ private const val TIMEOUT_SECONDS=120L
private const val WRITE_SECONDS=120L
private const val READ_SECONDS=120L
val INTERCEPT_LOG_LEVEL = HttpLoggingInterceptor.Level.BODY
val INTERCEPT_LOG_LEVEL = HttpLoggingInterceptor.Level.NONE
@Module
class RetrofitModule{
......
......@@ -17,7 +17,7 @@ import com.biganto.visual.roompark.data.repository.db.requrey.model.fromRaw
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.service.lifecycle.ForegroundLifecycleObserver
import com.biganto.visual.roompark.data.service.notification.INotificationCenter
import com.biganto.visual.roompark.data.service.notification.NotificationCenter
import com.biganto.visual.roompark.domain.use_case.TOUR_IDS_TO_DOWNLOAD_KEY
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.TourPreviewEntity
import com.jakewharton.rxrelay2.PublishRelay
......@@ -41,7 +41,7 @@ import javax.inject.Singleton
*/
private const val DB_ACCESS_CHUNK_SIZE = 256
private const val READ_SYNC_MILLS = 64L
private const val READ_SYNC_MILLS = 12L
private const val DEQUE_REQUEST_TIMEOUT_MILLS=100L
private const val META_PREDICTION="/tourMeta_"
private const val META_FILE_TYPE=".json"
......@@ -127,7 +127,11 @@ class DownloadManagerService @Inject constructor(
if (disposable.size() == 0)
attachDownloader()
return Service.START_NOT_STICKY
intent?.getStringArrayListExtra(TOUR_IDS_TO_DOWNLOAD_KEY)
?.forEach { toursToDownloadObserver.accept(it) }
return START_NOT_STICKY
}
override fun onDestroy() {
......@@ -263,7 +267,9 @@ class DownloadManagerService @Inject constructor(
val fileEntities = raw.files.map(::fromRaw)
mergeFiles(fileEntities)
Timber.d("1")
val jlist = db.getTourFilesJunction(tour.id).toList()
Timber.d("2")
val junctionList = fileEntities
.map {file ->
val entity = jlist.firstOrNull{it.tour == tour.id && it.file == file.uri}
......@@ -275,6 +281,7 @@ class DownloadManagerService @Inject constructor(
entity
}
Timber.d("3")
setDownloadInfo(
raw.id.toString()
, downloadedSize = downloadedSize
......@@ -283,7 +290,9 @@ class DownloadManagerService @Inject constructor(
, filesCount = raw.files.count()
).map { junctionList }
}
.doOnNext{Timber.d("4")}
.flatMap{ db.upsertTourFileJunction(it) }
.doOnNext{Timber.d("5 ${it.count()}")}
.flatMapIterable { it }
.flatMap { junction ->
db.getFileEntity(junction.file)
......@@ -326,7 +335,9 @@ class DownloadManagerService @Inject constructor(
.map { downloadInfo }
}
.sequential()
.toObservable()
.observeOn(Schedulers.computation())
// .doOnNext{Timber.d("7 ${it}")}
.map { model ->
setDownloadInfo(
model.tourId
......@@ -338,7 +349,8 @@ class DownloadManagerService @Inject constructor(
model.tourId
}
.delay(12L, TimeUnit.MILLISECONDS)
.toObservable()
private val checkService =
Observable.interval(0L, DEQUE_REQUEST_TIMEOUT_MILLS, TimeUnit.MILLISECONDS)
......@@ -351,6 +363,7 @@ class DownloadManagerService @Inject constructor(
deleteTourFromQueue()
}
downloadQueue.isNotEmpty() -> {
Timber.w(" 8 to donload: ${downloadQueue.size}")
notifyDownloading()
downloadTourFromQueue()
}
......@@ -363,7 +376,9 @@ class DownloadManagerService @Inject constructor(
private fun downloadTourFromQueue(): Observable<String> =
Observable.fromCallable { activeDownloading.set(true);downloadQueue.poll() }
.doOnNext { Timber.w("loading tour $it") }
.flatMap { db.getTourPreview(it).observable() }
.doOnNext { Timber.w("loading tour status ${it.isDownloaded}") }
.filter {
val forward = it.isDownloaded == DownloadState.Downloading
activeDownloading.set(forward)
......
package com.biganto.visual.roompark.domain.interactor
import android.content.Context
import android.content.Intent
import android.os.Build
import com.biganto.visual.roompark.R
import com.biganto.visual.roompark.base.BaseRoomParkActivity
import com.biganto.visual.roompark.data.service.download.DownloadManagerService
import com.biganto.visual.roompark.domain.model.CachedDataModel
import com.biganto.visual.roompark.domain.model.PushSwitchModel
import com.biganto.visual.roompark.domain.model.SettingsModel
import com.biganto.visual.roompark.domain.model.SubscriptionModel
import com.biganto.visual.roompark.domain.use_case.AuthUseCase
import com.biganto.visual.roompark.domain.use_case.SettingsUseCase
import com.biganto.visual.roompark.domain.use_case.SubscriptionUseCase
import com.biganto.visual.roompark.domain.use_case.*
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import javax.inject.Inject
/**
......@@ -21,10 +23,35 @@ import javax.inject.Inject
class SettingsInteractor @Inject constructor(
private val auth: AuthUseCase,
private val settingsUseCase: SettingsUseCase,
private val activity: Context,
private val subUc: SubscriptionUseCase
private val activity: BaseRoomParkActivity,
private val subUc: SubscriptionUseCase,
private val toursUc: TourPreviewsUseCase
){
private fun startDownloadService(ids:List<String>){
Timber.d(" gonna startService ++")
try {
val i = Intent(activity, DownloadManagerService::class.java)
i.putStringArrayListExtra(TOUR_IDS_TO_DOWNLOAD_KEY, ArrayList(ids))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
activity.startForegroundService(i)
} else {
activity.startService(i)
}
}catch (e:Exception){
Timber.d(" gonna startService errror")
Timber.e(e)
}
}
fun startToursDownloading() =
toursUc.downloadAllDeelsAndEstates()
.doOnNext { Timber.d(" gonna startService") }
.doOnNext { tours ->
startDownloadService(tours.map { tour -> tour.id })
}.ignoreElements()
fun getSubscriptions() =
subUc.getCurrentUserSubscriptions()
......
......@@ -11,6 +11,7 @@ import com.biganto.visual.roompark.data.repository.db.requrey.model.TourFileJunc
import com.biganto.visual.roompark.data.repository.db.requrey.model.fromRaw
import com.biganto.visual.roompark.data.repository.file.FileModule
import com.biganto.visual.roompark.data.service.download.TourFileData
import com.biganto.visual.roompark.domain.contract.AuthContract
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.DownloadState
import com.biganto.visual.roomparkvr.data.repository.db.requery.model.TourPreviewEntity
import io.reactivex.BackpressureStrategy
......@@ -37,9 +38,12 @@ class DownloadUseCase @Inject constructor(
private val db: IDb,
private val api: IBigantoApi,
private val fileModule: FileModule,
private val auth: AuthContract,
private val context: Application
) {
private fun writeFile(
response: ResponseBody,
model: TourFileData,
......@@ -111,7 +115,7 @@ class DownloadUseCase @Inject constructor(
}
Timber.d("save files: ${files.size}")
db.upsertFileEntity(files)?.blockingSubscribe { Timber.d("file saved") }
db.upsertFileEntity(files).blockingSubscribe { Timber.d("file saved") }
}
@Volatile
......
......@@ -21,6 +21,7 @@ import javax.inject.Inject
*/
const val EMPTY_PARENT = -778
const val TOUR_IDS_TO_DOWNLOAD_KEY = "DOWNLOAD_MANAGER_IDS_TO LOAD"
class TourPreviewsUseCase @Inject constructor(
private val api:IBigantoApi
......@@ -54,7 +55,7 @@ class TourPreviewsUseCase @Inject constructor(
db.getTourPreview(tourId)
.observable()
.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> =
syncTour(tourId,parentId,calcTargetResolution())
......@@ -168,6 +169,46 @@ class TourPreviewsUseCase @Inject constructor(
return fromApi
}
fun downloadAllDeelsAndEstates(): Observable<Iterable<TourPreviewEntity>> =
auth.currentUser()
.map { user ->
user.deals
?.asSequence()
?.filter { it.estate.multitourId != null }
?.toList()
?.map {
Pair(
it.estate.multitourId!!
, TourRemoteRequestModel(
estateId = it.estate.id
, targetResolution = user.targetResolution
)
)
}
}
.doOnNext { Timber.d("merged list:${it?.size}") }
.map { list ->
list.map { pair ->
api.getOfferTours(pair.first)
.doOnNext { Timber.d(" gonna merge") }
.map {
mergeRaw(
it
, pair.second
)
}
.map { it }
.doOnNext { Timber.d("merged list:${it.size}") }
.blockingFirst()
}
.flatten()
}
// .map { it.flatten() }
.doOnNext { Timber.d("merged flatten list:${it.size}") }
.flatMap { db.upsertTourPreview(it) }
.subscribeOn(Schedulers.io())
}
data class TourRemoteRequestModel(val estateId: Int, val token: String? = null, val targetResolution: Int)
......
......@@ -9,6 +9,7 @@ import io.reactivex.Observable
*/
interface SettingsScreen : BigantoBaseContract<SettingsScreenViewState> {
fun downloadAllTours(): Observable<Int>
fun signOut(): Observable<Int>
fun clearCache(): Observable<Int>
fun refreshCacheInfo(): Observable<Int>
......
......@@ -51,6 +51,10 @@ 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())
private val refreshEmitter = BehaviorRelay.create<Int>()
override fun refreshCacheInfo(): Observable<Int> = refreshEmitter
......
package com.biganto.visual.roompark.presentation.screen.settings
import android.content.Context
import com.biganto.visual.roompark.base.BaseRoomParkActivity
import com.biganto.visual.roompark.base.RoomParkMainActivity
import com.biganto.visual.roompark.di.dagger.AppComponent
import com.biganto.visual.roompark.di.dagger.PerScreen
......@@ -33,7 +33,7 @@ abstract class SettingsScreenModule{
@PerScreen
@Binds
abstract fun provideContext(activity: RoomParkMainActivity): Context
abstract fun provideActivity(activity: RoomParkMainActivity): BaseRoomParkActivity
// @PerScreen
// @Binds
......
package com.biganto.visual.roompark.presentation.screen.settings
import android.content.Context
import com.biganto.visual.roompark.base.BaseRoomParkActivity
import com.biganto.visual.roompark.conductor.BigantoBasePresenter
import com.biganto.visual.roompark.domain.interactor.SettingsInteractor
import com.biganto.visual.roompark.domain.model.CachedDataModel
......@@ -21,7 +21,7 @@ import javax.inject.Inject
class SettingsScreenPresenter @Inject constructor(
private val interactor: SettingsInteractor,
private val activity: Context
private val activity: BaseRoomParkActivity
)
: BigantoBasePresenter<SettingsScreen, SettingsScreenViewState>() {
......@@ -38,6 +38,10 @@ class SettingsScreenPresenter @Inject constructor(
override fun bindIntents() {
val onDownloadTours = intent(SettingsScreen::downloadAllTours)
.flatMap { interactor.startToursDownloading()
.andThen(Observable.just(SettingsScreenViewState.Idle()))
}
val onSubChecked = intent(SettingsScreen::onSubscription)
.flatMap { sub ->
......@@ -115,7 +119,8 @@ class SettingsScreenPresenter @Inject constructor(
refreshInfo,
fetchSubscriptions,
fetchCache,
onSubChecked
onSubChecked,
onDownloadTours
)
)
.doOnError { Timber.e(it) }
......
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